摘要:本节主要来讲解Android10.0 JAVA层HIDL服务的注册原理
阅读本文大约需要花费22分钟。
文章首发微信公众号:IngresGe
专注于Android系统级源码分析,Android的平台设计,欢迎关注我,谢谢!
[Android取经之路] 的源码都基于Android-Q(10.0) 进行分析
[Android取经之路] 系列文章:
《系统启动篇》
《日志系统篇》
《Binder通信原理》:
《HwBinder通信原理》
前面我们学习了Native层 HIDL服务的注册获取原理,这一节我们来看看JAVA层HIDL服务的注册原理。
上一节中,我们了解了Native层的HIDL服务注册和获取流程,HAL服务的注册和获取,其实就是从HwServiceManager的mServiceMap中,插入和获取对应的hidl服务。通常情况下,HAL的服务都是在Native层,Client可以在Native也可以在framework、应用层。但是Android新引入的HIDL是支持JAVA侧的服务创建和Client验证的,这一节,我们深度分析JAVA层的HAL服务的注册和获取。
JAVA层的HIDL服务注册和获取流程和Native层类似,只是在JAVA到Native层的过渡中,采用了JNI的机制来进行Native层的相关接口转换。
HwBinder通信原理:
当Init进程启动后,孵化Zygote进程时,会有一个虚拟机注册过程,在这个过程中完成了JNI的注册,我们现在不需要深入去理解JNI的原理,现在我们只要知道 JAVA和Native侧的函数对应关系在哪里即可。
HwBinder的JNI中有个一个HwBinder的映射数组:gMethods。
我们在撸代码时,是要根据JAVA的函数入口找到JNI的函数调用即可,暂时不要太追求细枝末节,等流程理顺后,再专攻细节分析。
Zygote进程启动时,JNI的注册调用栈如下所示:
其中gRegJNI保存了我们不同JNI的入口,里面就包含我们HwBinder的JNI入口
static const RegJNIRec gRegJNI[] = {
...
REG_JNI(register_android_os_HwBinder),
...
};
[/frameworks/base/core/jni/android_os_HwBinder.cpp]
int register_android_os_HwBinder(JNIEnv *env) {
jclass errorClass = FindClassOrDie(env, "java/lang/Error");
gErrorClass = MakeGlobalRefOrDie(env, errorClass);
//注册JNI对应的接口
return RegisterMethodsOrDie(env, CLASS_PATH, gMethods, NELEM(gMethods));
}
HwBinder JAVA层和Native层的JNI接口对应关系
static JNINativeMethod gMethods[] = {
{ "native_init", "()J", (void *)JHwBinder_native_init },
{ "native_setup", "()V", (void *)JHwBinder_native_setup },
{ "transact",
"(IL" PACKAGE_PATH "/HwParcel;L" PACKAGE_PATH "/HwParcel;I)V",
(void *)JHwBinder_native_transact },
{ "registerService", "(Ljava/lang/String;)V",
(void *)JHwBinder_native_registerService },
{ "getService", "(Ljava/lang/String;Ljava/lang/String;Z)L" PACKAGE_PATH "/IHwBinder;",
(void *)JHwBinder_native_getService },
{ "configureRpcThreadpool", "(JZ)V",
(void *)JHwBinder_native_configureRpcThreadpool },
{ "joinRpcThreadpool", "()V",
(void *)JHwBinder_native_joinRpcThreadpool },
{ "native_report_sysprop_change", "()V",
(void *)JHwBinder_report_sysprop_change },
};
我们本节主要分析的就是 注册服务:registerService 和 获取服务getService
JAVA层的HIDL服务注册流程如下图所示:
[vendor/ingres/hal_demo/java/src/com/android/demo/Server.java]
public static void main(String args[]){
Log.d(TAG, "start");
//1.启动HwBinder线程池
HwBinder.configureRpcThreadpool(1, true);
Demo demo = new Demo();
try {
//2.注册HIDL服务
demo.registerAsService("default");
Log.d(TAG, "success to register demo service");
} catch (RemoteException ex) {
Log.e(TAG, "exception, fail to register demo service");
}
//3.把当前的进程加入HwBinder的线程池进行循环
HwBinder.joinRpcThreadpool();
}
步骤如下:
1.启动HwBinder线程池
2.注册HIDL服务
3.把当前的进程加入HwBinder的线程池进行循环
IDemo服务中注册最终调用的是HwBinder的registerService,接着通过JNI,走到了Native层进行服务注册
[out/soong/.intermediates/vendor/ingres/interfaces/demo/1.0/vendor.ingres.demo-V1.0-java_gen_java/gen/srcs/vendor/ingres/demo/V1_0/IDemo.java]
public void registerAsService(String serviceName) throws android.os.RemoteException {
registerService(serviceName);
}
[/frameworks/base/core/java/android/os/HwBinder.java]
public native final void registerService(String serviceName)
throws RemoteException;
[/frameworks/base/core/jni/android_os_HwBinder.cpp]
static void JHwBinder_native_registerService(
JNIEnv *env,
jobject thiz,
jstring serviceNameObj) {
ScopedUtfChars str(env, serviceNameObj);
if (str.c_str() == nullptr) {
return; // NPE will be pending.
}
//1.获取一个JHwBinder对象,父类为HwBinder
sp binder = JHwBinder::GetNativeBinder(env, thiz);
/* TODO(b/33440494) this is not right */
//2.创建一个BpHwBase来包装JHwBinder
sp base = new hidl::base::V1_0::BpHwBase(binder);
//3.拿到HwServiceManager对象
auto manager = hardware::defaultServiceManager();
if (manager == nullptr) {
LOG(ERROR) << "Could not get hwservicemanager.";
signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return;
}
//4.进行服务注册,参数为:服务名称和对象
Return ret = manager->add(str.c_str(), base);
bool ok = ret.isOk() && ret;
if (ok) {
LOG(INFO) << "HwBinder: Starting thread pool for " << str.c_str();
::android::hardware::ProcessState::self()->startThreadPool();
}
signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /* canThrowRemoteException */);
}
步骤:
1.通过GetNativeBinder获取一个JHwBinder对象,父类为HwBinder
2.创建一个BpHwBase来包装JHwBinder
3.拿到HwServiceManager对象
4.将BpHwBase注册到hwservicemanager中,参数为:服务名称和对象
获取一个JHwBinder 对象
[/frameworks/base/core/jni/android_os_HwBinder.cpp]
sp JHwBinder::GetNativeBinder(
JNIEnv *env, jobject thiz) {
//从env中获取之前保存的JHwBinderHolder对象,native_setup时,会创建这个对象,并保存到env中
JHwBinderHolder *holder =
reinterpret_cast(
env->GetLongField(thiz, gFields.contextID));
//从JHwBinderHolder对象中取出 JHwBinder对象
return holder->get(env, thiz);
}
sp get(JNIEnv *env, jobject obj) {
Mutex::Autolock autoLock(mLock);
sp binder = mBinder.promote();
if (binder == NULL) {
//创建一个JHwBinder对象
binder = new JHwBinder(env, obj);
mBinder = binder;
}
return binder;
}
从HwBinder的成员变量mNativeContext中得到JHwBinderHolder的对象指针,然后调用其get函数得到JHwBinder对象。然后将JHwBinder封装为BpHwBase对象
[/out/soong/.intermediates/system/libhidl/transport/base/1.0/[email protected]_genc++/gen/android/hidl/base/1.0/BaseAll.cpp]
BpHwBase::BpHwBase(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)
: BpInterface(_hidl_impl),
::android::hardware::details::HidlInstrumentor("[email protected]", "IBase") {
}
[/system/libhidl/transport/ServiceManagement.cpp]
sp defaultServiceManager() {
return defaultServiceManager1_2();
}
defaultServiceManager1_2()是用来拿到HwServiceManager的代理对象--BpHwServiceManager
sp defaultServiceManager1_2() {
using android::hidl::manager::V1_2::BnHwServiceManager;
using android::hidl::manager::V1_2::BpHwServiceManager;
static std::mutex gDefaultServiceManagerLock;
static sp gDefaultServiceManager;
{
std::lock_guard _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager != nullptr) {
return gDefaultServiceManager;
}
//1.检查hwbinder的节点是否存在,如果不存在说明不支持hwbinder
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;
}
//2.等待属性"hwservicemanager.ready" 变为true,表明hwservicemanager已经启动好
waitForHwServiceManager();
while (gDefaultServiceManager == nullptr) {
//3.拿到HwServiceManager的代理对象,参考Native层[4.5.1]
gDefaultServiceManager =
fromBinder(
ProcessState::self()->getContextObject(nullptr));
if (gDefaultServiceManager == nullptr) {
LOG(ERROR) << "Waited for hwservicemanager, but got nullptr.";
sleep(1);
}
}
}
return gDefaultServiceManager;
}
至此,我们可以看到JAVA-JNI-Native,三层共有三个对象的转换:HwBinder、JHwBinderHolder、JHwBinder。
它们的类继承如下图所示:
它们的对象关系如下图所示:
调用BpHwServiceManager::_hidl_add的方法进行服务注册
[/out/soong/.intermediates/system/libhidl/transport/manager/1.2/[email protected]_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp]
::android::hardware::Return BpHwServiceManager::add(const ::android::hardware::hidl_string& name, const ::android::sp<::android::hidl::base::V1_0::IBase>& service){
::android::hardware::Return _hidl_out = ::android::hidl::manager::V1_0::BpHwServiceManager::_hidl_add(this, this, name, service);
return _hidl_out;
}
_hidl_add的主要步骤如下:
1.准备两个Parcel结构-- _hidl_data,_hidl_reply
2.组装Parcel数据
3.写入RPC头信息"[email protected]::IServiceManager"
4.写入服务名称,如果没有配置的话,name为"default"
5.写入服务的实体对象--new Demo()
6.调用remote的transact,发送 12 /* addWithChain */ 的命令进行服务的注册
7.得到返回的reply数据
[/out/soong/.intermediates/system/libhidl/transport/manager/1.2/[email protected]_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp]
::android::hardware::Return BpHwServiceManager::_hidl_add(::android::hardware::IInterface *_hidl_this, ::android::hardware::details::HidlInstrumentor *_hidl_this_instrumentor, const ::android::hardware::hidl_string& name, const ::android::sp<::android::hidl::base::V1_0::IBase>& service) {
...
::android::hardware::Parcel _hidl_data; //定义一个Parcel的data数据包
::android::hardware::Parcel _hidl_reply;//定义一个Parcel的reply数据包
::android::status_t _hidl_err;
::android::hardware::Status _hidl_status;
bool _hidl_out_success;
//1.写入RPC头信息"[email protected]::IServiceManager"
_hidl_err = _hidl_data.writeInterfaceToken(BpHwServiceManager::descriptor);
if (_hidl_err != ::android::OK) { goto _hidl_error; }
size_t _hidl_name_parent;
//2.写入服务名称,如果没有配置的话,name为"default"
_hidl_err = _hidl_data.writeBuffer(&name, sizeof(name), &_hidl_name_parent);
if (_hidl_err != ::android::OK) { goto _hidl_error; }
_hidl_err = ::android::hardware::writeEmbeddedToParcel(
name,
&_hidl_data,
_hidl_name_parent,
0 /* parentOffset */);
if (_hidl_err != ::android::OK) { goto _hidl_error; }
if (service == nullptr) {
_hidl_err = _hidl_data.writeStrongBinder(nullptr);
} else {
//3.根据传入的service,获取对应的hidl binder实体,把一个binder实体“打扁”并写入parcel,实体为 new Demo()
::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::getOrCreateCachedBinder(service.get());
if (_hidl_binder.get() != nullptr) {
_hidl_err = _hidl_data.writeStrongBinder(_hidl_binder);
} else {
_hidl_err = ::android::UNKNOWN_ERROR;
}
}
if (_hidl_err != ::android::OK) { goto _hidl_error; }
//4.启动一个线程池
::android::hardware::ProcessState::self()->startThreadPool();
//5.调用BpHwBinder::transact(),asBinder转换过程,参考下图
//_hidl_this 指的是 BpHwServiceManager,通过asBinder转换为传输层面的BpHwBinder对象,其实就是取出BpHwServiceManager的成员变量mRemote的值
_hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact(2 /* add */, _hidl_data, &_hidl_reply);
if (_hidl_err != ::android::OK) { goto _hidl_error; }
//6.从_hidl_reply读取返回结果
_hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);
if (_hidl_err != ::android::OK) { goto _hidl_error; }
if (!_hidl_status.isOk()) { return _hidl_status; }
_hidl_err = _hidl_reply.readBool(&_hidl_out_success);
if (_hidl_err != ::android::OK) { goto _hidl_error; }
#ifdef __ANDROID_DEBUGGABLE__
if (UNLIKELY(mEnableInstrumentation)) {
std::vector _hidl_args;
_hidl_args.push_back((void *)&_hidl_out_success);
for (const auto &callback: mInstrumentationCallbacks) {
callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hidl.manager", "1.0", "IServiceManager", "add", &_hidl_args);
}
}
#endif // __ANDROID_DEBUGGABLE__
_hidl_status.setFromStatusT(_hidl_err);
return ::android::hardware::Return(_hidl_out_success);
_hidl_error:
_hidl_status.setFromStatusT(_hidl_err);
return ::android::hardware::Return(_hidl_status);
}
BpHwBinder::transact调用后,会把组装的Parcel数据传到/dev/hwbinder,HwServiceManager发现hwbinder有数据变化,进行数据读取,最终根据传入的code=2,找到_hidl_add,进行服务注册
调用栈如下:
_hidl_add()主要步骤如下:
1.读取注册的Service Name
2. 读取注册的hidl_binder
3.通过hidl_binder,转换得到,注册时的服务实体
4.调用ServiceManager::add(),进行服务注册
5.向_hidl_reply中写入OK
6.把服务注册的结构,写入_hidl_reply
7.返回replay数据
[/out/soong/.intermediates/system/libhidl/transport/manager/1.2/[email protected]_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp]
::android::status_t BnHwServiceManager::_hidl_add(
::android::hidl::base::V1_0::BnHwBase* _hidl_this,
const ::android::hardware::Parcel &_hidl_data,
::android::hardware::Parcel *_hidl_reply,
TransactCallback _hidl_cb) {
...
const ::android::hardware::hidl_string* name;
::android::sp<::android::hidl::base::V1_0::IBase> service;
size_t _hidl_name_parent;
//1.读取注册的Service Name
_hidl_err = _hidl_data.readBuffer(sizeof(*name), &_hidl_name_parent, reinterpret_cast(&name));
if (_hidl_err != ::android::OK) { return _hidl_err; }
_hidl_err = ::android::hardware::readEmbeddedFromParcel(
const_cast<::android::hardware::hidl_string &>(*name),
_hidl_data,
_hidl_name_parent,
0 /* parentOffset */);
if (_hidl_err != ::android::OK) { return _hidl_err; }
{
//2. 读取注册的hidl_binder
::android::sp<::android::hardware::IBinder> _hidl_binder;
_hidl_err = _hidl_data.readNullableStrongBinder(&_hidl_binder);
if (_hidl_err != ::android::OK) { return _hidl_err; }
//3.通过hidl_binder,转换得到,注册时的服务实体
service = ::android::hardware::fromBinder<::android::hidl::base::V1_0::IBase,::android::hidl::base::V1_0::BpHwBase,::android::hidl::base::V1_0::BnHwBase>(_hidl_binder);
}
atrace_begin(ATRACE_TAG_HAL, "HIDL::IServiceManager::add::server");
...
//5.调用ServiceManager::add(),进行服务注册,参考[4.7.2]
bool _hidl_out_success = static_cast(_hidl_this->getImpl().get())->add(*name, service);
//6.向_hidl_reply中写入OK
::android::hardware::writeToParcel(::android::hardware::Status::ok(), _hidl_reply);
//7.把服务注册的结构,写入_hidl_reply
_hidl_err = _hidl_reply->writeBool(_hidl_out_success);
/* _hidl_err ignored! */
atrace_end(ATRACE_TAG_HAL);
...
//8.返回replay数据
_hidl_cb(*_hidl_reply);
return _hidl_err;
}
_hidl_add的调用栈如下:
获取当前binder调用的pid、sid 上下文信息后,开始注册服务,即把Demo对象注册到mServiceMap中
在过程中,要进行selinux检查,确认该进程有权限添加service后,再检查是否有重复注册,而且如果子类在父类上注册,则注销它,
排除一切问题后,把需要注册的服务,注册到mServiceMap中,最后建立一个死亡连接,当服务挂掉时会接收到通知,做一些清理工作。
[/system/hwservicemanager/ServiceManager.cpp]
bool ServiceManager::addImpl(const std::string& name,
const sp& service,
const hidl_vec& interfaceChain,
const AccessControl::CallingContext& callingContext) {
//传入的interfaceChain size大于0
if (interfaceChain.size() == 0) {
LOG(WARNING) << "Empty interface chain for " << name;
return false;
}
//1.首先,检查是否有权限来否允许add()整个接口层次结构,最终调用的是selinux_check_access来检查,是否有 hwservice_manager的权限
for(size_t i = 0; i < interfaceChain.size(); i++) {
const std::string fqName = interfaceChain[i];
if (!mAcl.canAdd(fqName, callingContext)) {
return false;
}
}
// 2.检查是否有重复注册
if (interfaceChain.size() > 1) {
// 倒数第二的条目应该是除IBase之外的最高基类。
const std::string baseFqName = interfaceChain[interfaceChain.size() - 2];
const HidlService *hidlService = lookup(baseFqName, name);
if (hidlService != nullptr && hidlService->getService() != nullptr) {
// This shouldn't occur during normal operation. Here are some cases where
// it might get hit:
// - bad configuration (service installed on device multiple times)
// - race between death notification and a new service being registered
// (previous logs should indicate a separate problem)
const std::string childFqName = interfaceChain[0];
pid_t newServicePid = IPCThreadState::self()->getCallingPid();
pid_t oldServicePid = hidlService->getDebugPid();
LOG(WARNING) << "Detected instance of " << childFqName << " (pid: " << newServicePid
<< ") registering over instance of or with base of " << baseFqName << " (pid: "
<< oldServicePid << ").";
}
}
// 3.如果子类在父类上注册,则注销它
{
// For IBar extends IFoo if IFoo/default is being registered, remove
// IBar/default. This makes sure the following two things are equivalent
// 1). IBar::castFrom(IFoo::getService(X))
// 2). IBar::getService(X)
// assuming that IBar is declared in the device manifest and there
// is also not an IBaz extends IFoo and there is no race.
const std::string childFqName = interfaceChain[0];
const HidlService *hidlService = lookup(childFqName, name);
if (hidlService != nullptr) {
const sp remove = hidlService->getService();
if (remove != nullptr) {
const std::string instanceName = name;
removeService(remove, &instanceName /* restrictToInstanceName */);
}
}
}
// 4.排除问题后,把需要注册的服务,注册到mServiceMap中
for(size_t i = 0; i < interfaceChain.size(); i++) {
const std::string fqName = interfaceChain[i];
PackageInterfaceMap &ifaceMap = mServiceMap[fqName];
HidlService *hidlService = ifaceMap.lookup(name);
if (hidlService == nullptr) {
//服务插入 mServiceMap,以后从这取出服务,参考 [4.9.3]
ifaceMap.insertService(
std::make_unique(fqName, name, service, callingContext.pid));
} else {
hidlService->setService(service, callingContext.pid);
}
ifaceMap.sendPackageRegistrationNotification(fqName, name);
}
//建立一个死亡连接,当服务挂掉时会接收到通知,做一些清理工作
bool linkRet = service->linkToDeath(this, kServiceDiedCookie).withDefault(false);
if (!linkRet) {
LOG(ERROR) << "Could not link to death for " << interfaceChain[0] << "/" << name;
}
return true;
}
把传入的hidlservice插入到mInstanceMap 中,即 mServiceMap的value--PackageInterfaceMap 中
[/system/hwservicemanager/ServiceManager.cpp]
void ServiceManager::PackageInterfaceMap::insertService(
std::unique_ptr &&service) {
mInstanceMap.insert({service->getInstanceName(), std::move(service)});
}
HwServiceManager中hidl服务的管理map:
至此,我们JAVA层的IDemo服务注册完成,对象转换如下图所示:
注册步骤分为以下几个步骤:
1.服务进程先通过JNI注册得到一个JHwBinder对象
2.获取HwServiceManager的代理对象HwBpServiceManager,主要通过new BpHwBinder(0)得到。
3.调用HwBpServiceManager的_hidl_add,组装一个Parce数据,传入服务名称、服务实体对象--BHwBinder、执行2 /* add */
4.先通过IPCThreadThread的writeTransactionData()把上面的Parcel数据写入mOut,用来进行发送
5.通过IPCThreadThread的talkWithDriver()与HwBinder驱动通信,传递语义BINDER_WRITE_READ
6.HwServiceManager有个for循环,调用epoll_wait()监控hwbinder的变化
7.waitForResponse()收到BR_TRANSACTION响应码后,最终后调用executeCommand()进行命令执行,根据逻辑处理,最终会调用到BnHwServiceManager::onTransact(),根据传入的code=12,调用addWithChain,最终把服务名称和实体对象插入到mServiceMap这个map中
8.注册成功后,把注册结果写入reply,返回reply信息
9.最终完成服务的注册流程
下一节,我们一起来看看《JAVA层HIDL服务的获取原理》
我的微信公众号:IngresGe