HAL binder工作流程-以RILJ/RILD通信为例

Telephony(RIL Java,以下简称RILJ)与RILD(RIL Daemon)的通信在Android OO8.0以前都是基于socket通信,而Android 8.0则是基于HAL binder进行IPC的数据交换。有关RILJ与RILD的工作原理可以参考之前的两篇文章:Android RIL概述以及RILD详解。这篇文章主要分析RILJ与RILD是如何通过HAL Binder进行通信。

RILJ与RILD的通信,服务端是RILD,客户端是RILJ。对于RILD而言,其对应的HAL接口是/android/hardware/interfaces/radio/1.0/IRadio.hal:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

/**
* This interface is used by telephony & telecom to talk to cellular radio.
* All the functions have minimum one parameter:
* serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
* duration of a method call. If clients provide colliding serials (including passing the same
* serial to different methods), multiple responses (one for each method call) must still be served.
*/
interface IRadio {
/**
* Set response functions for radio requests & radio indications.
*
* @param radioResponse Object containing response functions
* @param radioIndication Object containing radio indications
*/
setResponseFunctions(IRadioResponse radioResponse,
IRadioIndication radioIndication);

/**
* Requests status of the ICC card
*
* @param serial Serial number of request.
*
* Response function is IRadioResponse.getIccCardStatusResponse()
*
*/
oneway getIccCardStatus(int32_t serial);

...
}

而RILJ对应的回调接口有两个:/android/hardware/interfaces/radio/1.0/IRadioResponse.hal(RILJ发送给RILD的请求响应); /android/hardware/interfaces/radio/1.0/IRadioIndication.hal(RILD主动上班的事件):

  • IRadioResponse.hal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30


/**
* Interface declaring response functions to solicited radio requests.
* Response functions defined in this interface are as per following convention:
* <xyz>Response is response to IRadio.<xyz>
*/
interface IRadioResponse {
/**
* @param info Response info struct containing response type, serial no. and error
* @param cardStatus ICC card status as defined by CardStatus in types.hal
*
* Valid errors returned:
* RadioError:NONE
*/
oneway getIccCardStatusResponse(RadioResponseInfo info, CardStatus cardStatus);

/**
* @param info Response info struct containing response type, serial no. and error
* @param remainingRetries Number of retries remaining, must be equal to -1 if unknown.
*
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE (radio resetting)
* RadioError:PASSWORD_INCORRECT
*/
oneway supplyIccPinForAppResponse(RadioResponseInfo info, int32_t remainingRetries);

....
}
  • IRadioIndication.hal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

/**
* Interface declaring unsolicited radio indications.
*/
interface IRadioIndication {
/**
* Indicates when radio state changes.
*
* @param type Type of radio indication
* @param radioState Current radio state
*/
oneway radioStateChanged(RadioIndicationType type, RadioState radioState);

/**
* Indicates when call state has changed.
* Callee must invoke IRadio.getCurrentCalls()
* Must be invoked on, for example,
* "RING", "BUSY", "NO CARRIER", and also call state
* transitions (DIALING->ALERTING ALERTING->ACTIVE)
*
* Redundent or extraneous invocations are tolerated
*
* @param type Type of radio indication
*/
oneway callStateChanged(RadioIndicationType type);

/**
* Indicates when voice or data network state changed
* Callee must invoke IRadio.getVoiceRegistrationState(), IRadio.getDataRegistrationState(),
* and IRadio.getOperator()
*
* @param type Type of radio indication
*/
oneway networkStateChanged(RadioIndicationType type);

....
}

RILJ与RILD的通信大致要经历三个步骤:

  • RILD启动后,向HwServiceManager注册服务slot1(第二个RILD对应slot2);
  • RILJ启动后,从HwServiceManager获取RILD服务,并且注册两个回调函数: IRadioRepsone.java以及IRadioIndication.java分别用于接收来自RILD的消息;
  • RILD收到来自RILJ的回调注册后,注册一个RILJ的死亡通知对象,并且发送消息告知RILJ链接建立成功。

注册RILD服务

在RILD启动后,加载完vendor RIL之后,vendor RIL注册一个回调函数RIL_RadioFunctions:

关于RILD的详细介绍可以参考

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

// ril_service.cpp
extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {
int ret;
int flags;

RLOGI("SIM_COUNT: %d", SIM_COUNT);

if (callbacks == NULL) {
RLOGE("RIL_register: RIL_RadioFunctions * null");
return;
}

RLOGE("RIL_register: RIL version %d", callbacks->version);

if (s_registerCalled > 0) {
RLOGE("RIL_register has been called more than once. "
"Subsequent call ignored");
return;
}

memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));

s_registerCalled = 1;

RLOGI("s_registerCalled flag set, %d", s_started);
// Little self-check

for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {
assert(i == s_commands[i].requestNumber);
}

for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {
assert(i + RIL_UNSOL_RESPONSE_BASE
== s_unsolResponses[i].requestNumber);
}

// 注册RILD服务
radio::registerService(&s_callbacks, s_commands);
RLOGI("RILHIDL called registerService");
}

注册RILD服务:(1) 启动RILD服务所需的HAL binder线程池,线程数目为1;(2)将RIL服务RadioImpl注册为系统服务,供客户端调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

void radio::registerService(RIL_RadioFunctions *callbacks, CommandInfo *commands) {
using namespace android::hardware;
int simCount = 1;
const char *serviceNames[] = {
android::RIL_getServiceName()
#if (SIM_COUNT >= 2)
, RIL2_SERVICE_NAME
#if (SIM_COUNT >= 3)
, RIL3_SERVICE_NAME
#if (SIM_COUNT >= 4)
, RIL4_SERVICE_NAME
#endif
#endif
#endif
};
#if (SIM_COUNT >= 2)
simCount = SIM_COUNT;
#endif

configureRpcThreadpool(1, true /* callerWillJoin */);
for (int i = 0; i < simCount; i++) {
pthread_rwlock_t *radioServiceRwlockPtr = getRadioServiceRwlock(i);
int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
assert(ret == 0);

radioService[i] = new RadioImpl;
radioService[i]->mSlotId = i;
oemHookService[i] = new OemHookImpl;
oemHookService[i]->mSlotId = i;
RLOGD("registerService: starting IRadio %s", serviceNames[i]);
android::status_t status = radioService[i]->registerAsService(serviceNames[i]);
status = oemHookService[i]->registerAsService(serviceNames[i]);

ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
assert(ret == 0);
}

s_vendorFunctions = callbacks;
s_commands = commands;
}

RadioImpl实际继承了IRadio.hal中定义的接口,这个接口在编译时,Android利用HIDL的工具hidl-gen来产生对应的客户端代理Proxy对象以及服务端存根Stub对象,但IRadio.hal中并没有声明registerAsService接口,那么这个接口是从何而来了?猜测应该是由HIDL工具主动生成的接口。不妨看看hidl-gen的代码/android/system/tools/hidl/。找到相应的main函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93

int main(int argc, char **argv) {
std::string outputPath;
std::vector<std::string> packageRootPaths;
std::vector<std::string> packageRoots;

const char *me = argv[0];
OutputHandler *outputFormat = nullptr;

// 解析参数
int res;
while ((res = getopt(argc, argv, "ho:r:L:")) >= 0) {
switch (res) {
case 'o':
{
outputPath = optarg;
break;
}

case 'r':
{
std::string val(optarg);
auto index = val.find_first_of(':');
CHECK(index != std::string::npos);

auto package = val.substr(0, index);
auto path = val.substr(index + 1);
packageRootPaths.push_back(path);
packageRoots.push_back(package);
break;
}

case 'L':
{
CHECK(outputFormat == nullptr) << "Only one -L option allowed.";
for (auto &e : formats) {
if (e.mKey == optarg) {
outputFormat = &e;
break;
}
}
CHECK(outputFormat != nullptr) << "Output format not recognized.";
break;
}

case '?':
case 'h':
default:
{
usage(me);
exit(1);
break;
}
}
}


argc -= optind;
argv += optind;
....

// 负责产生.hal接口的头文件,源文件
Coordinator coordinator(packageRootPaths, packageRoots);

for (int i = 0; i < argc; ++i) {
FQName fqName(argv[i]);

if (!fqName.isValid()) {
fprintf(stderr,
"ERROR: Invalid fully-qualified name.\n");
exit(1);
}

OutputHandler::ValRes valid =
outputFormat->validate(fqName, outputFormat->mKey);

if (valid == OutputHandler::FAILED) {
fprintf(stderr,
"ERROR: output handler failed.\n");
exit(1);
}

// 产生对应的代理与存根文件
status_t err =
outputFormat->generate(fqName, me, &coordinator, outputPath);

if (err != OK) {
exit(1);
}
}

return 0;
}

hidl-gen大致包含了以下几个参数:

  • 输出路径;
  • 产生的语言类型,C++还是Java还是头文件;
  • 接口所在的根目录;
  • 接口的全限定名(Full qulified name);
1
2

hidl-gen -o output-path -L language (-r interface-root) fqname

对于RILD服务来说,其生成的指令如下(参考对应接口目录的Android.bp脚本):

1
2

hidl-gen -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0",

对于C++源文件,最后会调用generatedCpp.cpp中的generateCppSources函数产生接口对应的Proxy/Stub代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

status_t AST::generateCppSources(const std::string &outputPath) const {

std::string path = outputPath;
path.append(mCoordinator->convertPackageRootToPath(mPackage));
path.append(mCoordinator->getPackagePath(mPackage, true /* relative */));

std::string ifaceName;
std::string baseName;

const Interface *iface = nullptr;
bool isInterface;
if (!AST::isInterface(&ifaceName)) {
baseName = "types";
isInterface = false;
} else {
iface = mRootScope->getInterface();
baseName = iface->getBaseName();
isInterface = true;
}

path.append(baseName);

if (baseName != "types") {
path.append("All");
}

path.append(".cpp");

CHECK(Coordinator::MakeParentHierarchy(path));
FILE *file = fopen(path.c_str(), "w");

if (file == NULL) {
return -errno;
}

Formatter out(file);

out << "#include <android/log.h>\n";
out << "#include <cutils/trace.h>\n";
out << "#include <hidl/HidlTransportSupport.h>\n\n";
if (isInterface) {
// This is a no-op for IServiceManager itself.
out << "#include <android/hidl/manager/1.0/IServiceManager.h>\n";

// TODO(b/34274385) remove this
out << "#include <hidl/LegacySupport.h>\n";

generateCppPackageInclude(out, mPackage, iface->getProxyName());
generateCppPackageInclude(out, mPackage, iface->getStubName());
generateCppPackageInclude(out, mPackage, iface->getPassthroughName());

for (const Interface *superType : iface->superTypeChain()) {
generateCppPackageInclude(out,
superType->fqName(),
superType->fqName().getInterfaceProxyName());
}

out << "#include <hidl/ServiceManagement.h>\n";
} else {
generateCppPackageInclude(out, mPackage, "types");
generateCppPackageInclude(out, mPackage, "hwtypes");
}
....
if (err == OK && isInterface) {
const Interface *iface = mRootScope->getInterface();

// need to be put here, generateStubSource is using this.
out << "const char* "
<< iface->localName()
<< "::descriptor(\""
<< iface->fqName().string()
<< "\");\n\n";
out << "__attribute__((constructor))";
out << "static void static_constructor() {\n";
out.indent([&] {
out << "::android::hardware::details::gBnConstructorMap.set("
<< iface->localName()
<< "::descriptor,\n";
out.indent(2, [&] {
out << "[](void *iIntf) -> ::android::sp<::android::hardware::IBinder> {\n";
out.indent([&] {
out << "return new "
<< iface->getStubName()
<< "(static_cast<"
<< iface->localName()
<< " *>(iIntf));\n";
});
out << "});\n";
});
out << "::android::hardware::details::gBsConstructorMap.set("
<< iface->localName()
<< "::descriptor,\n";
out.indent(2, [&] {
out << "[](void *iIntf) -> ::android::sp<"
<< gIBaseFqName.cppName()
<< "> {\n";
out.indent([&] {
out << "return new "
<< iface->getPassthroughName()
<< "(static_cast<"
<< iface->localName()
<< " *>(iIntf));\n";
});
out << "});\n";
});
});
out << "};\n\n";
out << "__attribute__((destructor))";
out << "static void static_destructor() {\n";
out.indent([&] {
out << "::android::hardware::details::gBnConstructorMap.erase("
<< iface->localName()
<< "::descriptor);\n";
out << "::android::hardware::details::gBsConstructorMap.erase("
<< iface->localName()
<< "::descriptor);\n";
});
out << "};\n\n";

err = generateInterfaceSource(out);
}

if (err == OK && isInterface) {
err = generateProxySource(out, iface->fqName());
}

if (err == OK && isInterface) {
err = generateStubSource(out, iface);
}

if (err == OK && isInterface) {
err = generatePassthroughSource(out);
}

if (err == OK && isInterface) {
const Interface *iface = mRootScope->getInterface();

if (isIBase()) {
out << "// skipped getService, registerAsService, registerForNotifications\n";
} else {
std::string package = iface->fqName().package()
+ iface->fqName().atVersion();

implementServiceManagerInteractions(out, iface->fqName(), package);
}
}

正是在implementServiceManagerInteractions这个函数里,对于IRadio.hal接口生成了获取服务getService以及注册服务的registerAsService的接口。可以看到,registerAsService利用了defaultServiceManager()来调用IServiceManager进行服务注册。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52

static void implementServiceManagerInteractions(Formatter &out,
const FQName &fqName, const std::string &package) {

const std::string interfaceName = fqName.getInterfaceName();

implementGetService(out, fqName, true /* isTry */);
implementGetService(out, fqName, false /* isTry */);

out << "::android::status_t " << interfaceName << "::registerAsService("
<< "const std::string &serviceName) ";
out.block([&] {
out << "::android::hardware::details::onRegistration(\""
<< fqName.getPackageAndVersion().string() << "\", \""
<< interfaceName
<< "\", serviceName);\n\n";
out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
out.indent(2, [&] {
out << "= ::android::hardware::defaultServiceManager();\n";
});
out.sIf("sm == nullptr", [&] {
out << "return ::android::INVALID_OPERATION;\n";
}).endl();
out << "::android::hardware::Return<bool> ret = "
<< "sm->add(serviceName.c_str(), this);\n"
<< "return ret.isOk() && ret ? ::android::OK : ::android::UNKNOWN_ERROR;\n";
}).endl().endl();

out << "bool " << interfaceName << "::registerForNotifications(\n";
out.indent(2, [&] {
out << "const std::string &serviceName,\n"
<< "const ::android::sp<::android::hidl::manager::V1_0::IServiceNotification> "
<< "&notification) ";
});
out.block([&] {
out << "const ::android::sp<::android::hidl::manager::V1_0::IServiceManager> sm\n";
out.indent(2, [&] {
out << "= ::android::hardware::defaultServiceManager();\n";
});
out.sIf("sm == nullptr", [&] {
out << "return false;\n";
}).endl();
out << "::android::hardware::Return<bool> success =\n";
out.indent(2, [&] {
out << "sm->registerForNotifications(\"" << package << "::" << interfaceName << "\",\n";
out.indent(2, [&] {
out << "serviceName, notification);\n";
});
});
out << "return success.isOk() && success;\n";
}).endl().endl();
}

defaultServiceManagerServiceManagement.cpp中定义,HAL服务管家HwServiceManager初始化完成后,会设置属性值hwservicemanager.ready;这样defaultServiceManager实际返回的是一个强引用的变量gDefaultServiceManager:

代码路径/android/system/libhidl/transport/ServiceManagement.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

sp<IServiceManager> defaultServiceManager() {
{
AutoMutex _l(details::gDefaultServiceManagerLock);
if (details::gDefaultServiceManager != NULL) {
return details::gDefaultServiceManager;
}

if (access("/dev/hwbinder", F_OK|R_OK|W_OK) != 0) {
// HwBinder not available on this device or not accessible to
// this process.
return nullptr;
}

waitForHwServiceManager();

while (details::gDefaultServiceManager == NULL) {
details::gDefaultServiceManager =
fromBinder<IServiceManager, BpHwServiceManager, BnHwServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (details::gDefaultServiceManager == NULL) {
LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
sleep(1);
}
}
}

return details::gDefaultServiceManager;
}

//等待hwservicemanager启动完成
void waitForHwServiceManager() {
using std::literals::chrono_literals::operator""s;

while (!WaitForProperty(kHwServicemanagerReadyProperty, "true", 1s)) {
LOG(WARNING) << "Waited for hwservicemanager.ready for a second, waiting another...";
}
}

那么,gDefaultServiceManager又是什么东东了?先来看看ProcessState::self()->getContextObject(NULL)得到的是一个什么对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;

AutoMutex _l(mLock);

handle_entry* e = lookupHandleLocked(handle);

if (e != NULL) {
// We need to create a new BpHwBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpHwBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}

return result;
}

从上面的代码不难看出,ProcessState::self()->getContextObject(NULL)实际返回的是一个BpHwBinder(0)的Binder代理对象,函数fromBinder会根据这个Binder对象转换成相应的IServiceManager: BpHwServerceManager(BpHwBinder(0)),BpHwServerceManager实际上也是根据接口IServiceManager.hal通过generatedCpp.cpp中的函数生成的代理对象,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

template <typename IType, typename ProxyType, typename StubType>
sp<IType> fromBinder(const sp<IBinder>& binderIface) {
using ::android::hidl::base::V1_0::IBase;
using ::android::hidl::base::V1_0::BnHwBase;

if (binderIface.get() == nullptr) {
return nullptr;
}
// 代理对象,本地binder为空
if (binderIface->localBinder() == nullptr) {
return new ProxyType(binderIface);
}
sp<IBase> base = static_cast<BnHwBase*>(binderIface.get())->getImpl();
if (details::canCastInterface(base.get(), IType::descriptor)) {
StubType* stub = static_cast<StubType*>(binderIface.get());
return stub->getImpl();
} else {
return nullptr;
}
}

这样HwServiceManager的在客户端的代理对象BpHwServerceManager将客户端请求发送给HAL Binder驱动;HAL Binder驱动则将请求发送给HAL服务管家的stub对象BnHwServiceManagerBnHwServiceManager在何时成为HAL服务上下文管家的,可以看看上一篇文章“Android HAL binder详解”)来完成服务的注册。

获取RILD服务

RILD HAL服务注册完成之后,RILJ是如何获取到服务的了?Phone进程启动后,对RILJ进行初始化,这时RILJ会去获取RILD服务,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

public RIL(Context context, int preferredNetworkType, int cdmaSubscription) {
this(context, preferredNetworkType, cdmaSubscription, null);
}

public RIL(Context context, int preferredNetworkType,
int cdmaSubscription, Integer instanceId) {
super(context);

mContext = context;
mPreferredNetworkType = preferredNetworkType;
mPhoneType = RILConstants.NO_PHONE;
mPhoneId = instanceId;

ConnectivityManager cm = (ConnectivityManager)context.getSystemService(
Context.CONNECTIVITY_SERVICE);
mIsMobileNetworkSupported = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE);

// 新建response,indication,用于接收RILD的消息
mRadioResponse = new RadioResponse(this);
mRadioIndication = new RadioIndication(this);
mOemHookResponse = new OemHookResponse(this);
mOemHookIndication = new OemHookIndication(this);
mRilHandler = new RilHandler();
mRadioProxyDeathRecipient = new RadioProxyDeathRecipient();
....
// 获取RILD HAL服务
getRadioProxy(null);
getOemHookProxy(null);
}

getRadioProxy首先判断终端是否支持移动数据,如果没有移动数据(没有modem),则直接返回空;如果已经获取到了,则返回之前获取到的代理对象mRadioProxy。如果都不是,通过IRadio.getService来获取RILD服务的代理对象,接着向RILD注册回调函数mRadioResponse以及mRadioIndication,同时还需要注册RILD服务的死亡注册通知接收器,以便RILD异常退出后,RILJ能够收到该信息做相应的处理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

private IRadio getRadioProxy(Message result) {
if (!mIsMobileNetworkSupported) {
if (RILJ_LOGV) riljLog("getRadioProxy: Not calling getService(): wifi-only");
if (result != null) {
AsyncResult.forMessage(result, null,
CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
result.sendToTarget();
}
return null;
}

if (mRadioProxy != null) {
return mRadioProxy;
}

try {
mRadioProxy = IRadio.getService(HIDL_SERVICE_NAME[mPhoneId == null ? 0 : mPhoneId]);
if (mRadioProxy != null) {
mRadioProxy.linkToDeath(mRadioProxyDeathRecipient,
mRadioProxyCookie.incrementAndGet());
mRadioProxy.setResponseFunctions(mRadioResponse, mRadioIndication);
} else {
riljLoge("getRadioProxy: mRadioProxy == null");
}
} catch (RemoteException | RuntimeException e) {
mRadioProxy = null;
riljLoge("RadioProxy getService/setResponseFunctions: " + e);
}

if (mRadioProxy == null) {
if (result != null) {
AsyncResult.forMessage(result, null,
CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
result.sendToTarget();
}

// 此时RILD服务还无法获取到,则延迟几秒再次获取
mRilHandler.sendMessageDelayed(
mRilHandler.obtainMessage(EVENT_RADIO_PROXY_DEAD,
mRadioProxyCookie.incrementAndGet()),
IRADIO_GET_SERVICE_DELAY_MILLIS);
}

return mRadioProxy;
}

这里有一个问题,搜索Android源码并没有IRadio.java类,那么只能说同之前HwServiceMananger一样,这个类也是通过hidl-gen来产生的。看下IRadio.hal对应目录的Android.bp并没有定义生成规则,是不是在Android.mk里边了?搜了下,果然在:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#
# Build IRadio.hal
#
GEN := $(intermediates)/android/hardware/radio/V1_0/IRadio.java
$(GEN): $(HIDL)
$(GEN): PRIVATE_HIDL := $(HIDL)
$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IRadio.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IRadioIndication.hal
$(GEN): $(LOCAL_PATH)/IRadioIndication.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IRadioResponse.hal
$(GEN): $(LOCAL_PATH)/IRadioResponse.hal
$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
$(GEN): $(LOCAL_PATH)/types.hal
$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
$(GEN): PRIVATE_CUSTOM_TOOL = \
$(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-Ljava \
-randroid.hardware:hardware/interfaces \
-randroid.hidl:system/libhidl/transport \
android.hardware.radio@1.0::IRadio

$(GEN): $(LOCAL_PATH)/IRadio.hal
$(transform-generated-source)
LOCAL_GENERATED_SOURCES += $(GEN)

可以简单的写成如下这个指令,其作用是生成一个Java层的类用于获取RILD的服务。

hidl-gen利用generateJava.cpp中的函数generateJava来自动生成对应的类

1
2

hidl-gen -o $(PRIVATE_OUTPUT_DIR) -LJava -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport `

generateJava.cpp生成的IRadio.java大致结构如下(只写了几个关键函数)。绕来绕去,IRadio.getService("slot1")实际返回的是一个由HwBinder.getService返回的IHwBinder对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

package android.hardware.radio;

public interface IRaio extends android.os.IHwInterface {
public static final String kInterfaceName = "android.hardware.radio::IRadio";

static asInterface(android.os.IHwBinder binder) {
if (binder == null) {
return null;
}

android.os.IHwInterface iface = binder.queryLocalInterface(kInterfaceName);

if (iface != null && iface instanceof IRaio) {
return (IRadio)iface;
}

IRadio proxy = new IRadio.Proxy(binder);

try {
for (String descriptor : proxy.interfaceChain()) {
if (descriptor.equals(kInterfaceName)) {
return proxy;
}
}
} catch (android.os.RemoteException e) {

}

return null;

...

public static getService(String serviceName) throws android.os.RemoteException {
return IRadio.asInterface(android.os.HwBinder.getService(
android.hardware.radio@1.0::IRadio, serviceName));
}

...
public static final class Proxy implements IRadio {
private android.os.IHwBinder mRemote;

public Proxy(android.os.IHwBinder remote) {
mRemote = java.util.Objects.requireNonNull(remote);
}

@Override
public android.os.IHwBinder asBinder() {
return mRemote;
}
}
...
}
}

继续看看HwBinder.getService返回的是什么东东?原来是一个native函数调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

public abstract class HwBinder implements IHwBinder {
private static final String TAG = "HwBinder";

private static final NativeAllocationRegistry sNativeRegistry;

public HwBinder() {
native_setup();

sNativeRegistry.registerNativeAllocation(
this,
mNativeContext);
}

@Override
public final native void transact(
int code, HwParcel request, HwParcel reply, int flags)
throws RemoteException;

public abstract void onTransact(
int code, HwParcel request, HwParcel reply, int flags)
throws RemoteException;

public native final void registerService(String serviceName)
throws RemoteException;

// native接口
public static native final IHwBinder getService(
String iface,
String serviceName)
throws RemoteException, NoSuchElementException;

// Returns address of the "freeFunction".
private static native final long native_init();

private native final void native_setup();

static {
long freeFunction = native_init();

sNativeRegistry = new NativeAllocationRegistry(
HwBinder.class.getClassLoader(),
freeFunction,
128 /* size */);
}

private long mNativeContext;
}

native层获取HAL服务,仍然是通过defaultServiceManager来获取服务的代理对象,从上面获取上下文服务ServiceManager的过程不难看出hardware::defaultServiceManager()->get("android.hardware.radio@1.0::IRadio", "slot1")返回的实际上是一个与RILD服务binder代理对象BpHwBinder(handle)(handle由注册服务时binder驱动自动生成):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99


static jobject JHwBinder_native_getService(
JNIEnv *env,
jclass /* clazzObj */,
jstring ifaceNameObj,
jstring serviceNameObj) {

using ::android::hidl::base::V1_0::IBase;
using ::android::hidl::manager::V1_0::IServiceManager;

if (ifaceNameObj == NULL) {
jniThrowException(env, "java/lang/NullPointerException", NULL);
return NULL;
}
if (serviceNameObj == NULL) {
jniThrowException(env, "java/lang/NullPointerException", NULL);
return NULL;
}

auto manager = hardware::defaultServiceManager();

if (manager == nullptr) {
LOG(ERROR) << "Could not get hwservicemanager.";
signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return NULL;
}

const char *ifaceNameCStr = env->GetStringUTFChars(ifaceNameObj, NULL);
if (ifaceNameCStr == NULL) {
return NULL; // XXX exception already pending?
}
std::string ifaceName(ifaceNameCStr);
env->ReleaseStringUTFChars(ifaceNameObj, ifaceNameCStr);
::android::hardware::hidl_string ifaceNameHStr;
ifaceNameHStr.setToExternal(ifaceName.c_str(), ifaceName.size());

const char *serviceNameCStr = env->GetStringUTFChars(serviceNameObj, NULL);
if (serviceNameCStr == NULL) {
return NULL; // XXX exception already pending?
}
std::string serviceName(serviceNameCStr);
env->ReleaseStringUTFChars(serviceNameObj, serviceNameCStr);
::android::hardware::hidl_string serviceNameHStr;
serviceNameHStr.setToExternal(serviceName.c_str(), serviceName.size());

// 判断当前service是直通式(C/S在同一进程)还是跨进程的binder类型
Return<IServiceManager::Transport> transportRet =
manager->getTransport(ifaceNameHStr, serviceNameHStr);
....

IServiceManager::Transport transport = transportRet;

if (transport != IServiceManager::Transport::HWBINDER && !vintfLegacy) {
LOG(ERROR) << "service " << ifaceName << " declares transport method "
<< toString(transport) << " but framework expects hwbinder.";
signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return NULL;
}

// 返回一个BpHwBinder(handle)对象
Return<sp<hidl::base::V1_0::IBase>> ret = manager->get(ifaceNameHStr, serviceNameHStr);

if (!ret.isOk()) {
signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return NULL;
}

//对于远程代理对象,toBinder返回的是一个downcast后的`IBinder`对象(BpHwBinder)
sp<hardware::IBinder> service = hardware::toBinder<
hidl::base::V1_0::IBase, hidl::base::V1_0::BpHwBase>(ret);

if (service == NULL) {
signalExceptionForError(env, NAME_NOT_FOUND);
return NULL;
}

LOG(INFO) << "Starting thread pool.";
::android::hardware::ProcessState::self()->startThreadPool();

// 返回一个HwRemoteBinder(BpHwBinder(handle))
return JHwRemoteBinder::NewObject(env, service);
}

// static
jobject JHwRemoteBinder::NewObject(
JNIEnv *env, const sp<hardware::IBinder> &binder) {
ScopedLocalRef<jclass> clazz(env, FindClassOrDie(env, CLASS_PATH));

// XXX Have to look up the constructor here because otherwise that static
// class initializer isn't called and gProxyOffsets.constructID is undefined :(

jmethodID constructID = GetMethodIDOrDie(env, clazz.get(), "<init>", "()V");

jobject obj = env->NewObject(clazz.get(), constructID);
JHwRemoteBinder::GetNativeContext(env, obj)->setBinder(binder);

return obj;
}

native层得到RILD服务的IBinder对象后,将其保存到native对象JHwRemoteBinder(其对应的Java对象是HwRemoteBinder.java),这样Java层代码binder就可以通过native接口来实现binder通信了。回到最开始调用的地方,至此我们知道,实际RILJ通过调用IRadio.getService得到的是一个私有变量mRemote=HwRemoteBinderProxy代理对象。这样RILJ就可以通过该代理对象与RILD进行通信了。大功告成。RILJ跟RILD的通信还差最后一步:RILJ向RILD注册回调。

HAL服务的类型(直通或者binder类型)是由各个厂商定义的,配置文件manifest.xml放在/android/device/目录下,其基本结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

<manifest version="1.0" type="device">
<hal format="hidl">
<name>android.hardware.radio</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IRadio</name>
<instance>slot1</instance>
<instance>slot2</instance>
</interface>
<interface>
<name>ISap</name>
<instance>slot1</instance>
<instance>slot2</instance>
</interface>
</hal>
<hal format="hidl">
<name>android.hardware.radio.deprecated</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IOemHook</name>
<instance>slot1</instance>
<instance>slot2</instance>
</interface>
</hal>
</manifest>

RILJ注册回调,通信建立完成

RILJ获取到RILD的代理对象后,就可以通过远程调用向RILD发送请求了。但在建立最后的通信,还需要做三件事情:

  • RILJ向RILD注册一个死亡通知: 当RILD异常退出后,通过该接收者来接受死亡消息

    1
    2
        
    mRadioProxy.linkToDeath(mRadioProxyDeathReceipent, mRadioProxyCookie.incrementAndGet());
  • RILJ向RILD注册回调,RILD可通过该回调向RILJ发送消息:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28

    Return<void> RadioImpl::setResponseFunctions(
    const ::android::sp<IRadioResponse>& radioResponseParam,
    const ::android::sp<IRadioIndication>& radioIndicationParam) {
    RLOGD("setResponseFunctions");

    pthread_rwlock_t *radioServiceRwlockPtr = radio::getRadioServiceRwlock(mSlotId);
    int ret = pthread_rwlock_wrlock(radioServiceRwlockPtr);
    assert(ret == 0);

    mRadioResponse = radioResponseParam;
    mRadioIndication = radioIndicationParam;

    //< RNTFIX::
    mSecRadioResponse = NULL;
    mSecRadioIndication = NULL;
    //> RNTFIX

    mCounterRadio[mSlotId]++;

    ret = pthread_rwlock_unlock(radioServiceRwlockPtr);
    assert(ret == 0);

    // client is connected. Send initial indications.
    android::onNewCommandConnect((RIL_SOCKET_ID) mSlotId);

    return Void();
    }
  • RILD发送消息告知RILJ通信建立成功:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
        

    void onNewCommandConnect(RIL_SOCKET_ID socket_id) {
    // Inform we are connected and the ril version
    int rilVer = s_callbacks.version;
    RIL_UNSOL_RESPONSE(RIL_UNSOL_RIL_CONNECTED,
    &rilVer, sizeof(rilVer), socket_id);

    // implicit radio state changed
    RIL_UNSOL_RESPONSE(RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED,
    NULL, 0, socket_id);

    // Send last NITZ time data, in case it was missed
    if (s_lastNITZTimeData != NULL) {
    resendLastNITZTimeData(socket_id);
    }

    // Get version string
    if (s_callbacks.getVersion != NULL) {
    const char *version;
    version = s_callbacks.getVersion();
    RLOGI("RIL Daemon version: %s\n", version);

    property_set(PROPERTY_RIL_IMPL, version);
    } else {
    RLOGI("RIL Daemon version: unavailable\n");
    property_set(PROPERTY_RIL_IMPL, "unavailable");
    }

    }

参考资料