上文中详细分析了Hal的整个启动过程,这里将补充上文中没有详细分析的Binder对象转换过程,下图为hidl服务的完整注册过程:
1. HwcHal继承于IBase类,是对hw_module_t的封装,该对象位于Hal进程空间;
2. 通过hwservicemanager的binder代理将HwcHal对象注册到hwservicemanager进程空间;
3. 在IPC调用过程中,HwcHal对象的身份一直在变化,到达hwservicemanager进程后,变成BpHwBase对象,该对象封装了BpHwBinder,并保存在hwservicemanager进程中。
我们知道,binder通信可以传输的数据类型包括:
1. 普通数据类型;
2. fd句柄类型;
3. IBinder类型;
4. 经过序列化的自定义类型;
在注册HwcHal这个hidl服务对象时,由于HwcHal继承IBase类,并非binder类型,而在BpHwServiceManager::_hidl_add函数中会通过以下代码段将HwcHal这个对象发送给hwservicemanager进程,那么发送的是否是HwcHal对象本身呢?
if (service &#61;&#61; nullptr) { _hidl_err &#61; _hidl_data.writeStrongBinder(nullptr); } else { ::android::sp<::android::hardware::IBinder> _hidl_binder &#61; ::android::hardware::toBinder< ::android::hidl::base::V1_0::IBase>(service); if (_hidl_binder.get() !&#61; nullptr) { _hidl_err &#61; _hidl_data.writeStrongBinder(_hidl_binder); } else { _hidl_err &#61; ::android::UNKNOWN_ERROR; } }
::android::hardware::toBinder<::android::hidl::base::V1_0::IBase>(service)system\libhidl\transport\include\hidl\HidlBinderSupport.h
template <typename IType, typename ProxyType>
sp
}
这里首先判断IComposer这个业务对象是否是BpHwComposer&#xff0c;如果是&#xff0c;那么调用asBinder来得到BpHwBinder对象。在BpHwComposer中&#xff0c;isRemote()默认为true&#xff0c;而在IComposer中&#xff0c;isRemote()默认为false。
struct BpHwComposer : public ::android::hardware::BpInterface<IComposer>, public ::android::hardware::details::HidlInstrumentor { explicit BpHwComposer(const ::android::sp<::android::hardware::IBinder> &_hidl_impl); typedef IComposer Pure; virtual bool isRemote() const override { return true; } struct IComposer : public ::android::hidl::base::V1_0::IBase { virtual bool isRemote() const override { return false; }
这里注册的是HwcHal对象&#xff0c;他实现了IComposer接口。因此将根据接口描述符从gBnConstructorMap中找到对应的构造函数指针&#xff0c;然后回调构造函数&#xff1a;
composer\2.1\android.hardware.graphics.composer&#64;2.1_genc&#43;&#43;\gen\android\hardware\graphics\composer\2.1\ComposerAll.cpp
const char* IComposer::descriptor("android.hardware.graphics.composer&#64;2.1::IComposer"); __attribute__((constructor))static void static_constructor() { ::android::hardware::details::gBnConstructorMap.set(IComposer::descriptor, [](void *iIntf) -> ::android::sp<::android::hardware::IBinder> { return new BnHwComposer(static_cast
}; __attribute__((destructor))static void static_destructor() { ::android::hardware::details::gBnConstructorMap.erase(IComposer::descriptor); ::android::hardware::details::gBsConstructorMap.erase(IComposer::descriptor);
};
这里会创建一个BnHwComposer对象&#xff0c;并将HwcHal保存到其变量_hidl_mImpl中&#xff1a;
BnHwComposer::BnHwComposer(const ::android::sp
}
所以toBinder函数功能如下&#xff1a;
如果是BpHwComposer对象&#xff0c;则得到BpHwComposer的成员变量BpHwBinder对象&#xff1b;
如果是BpHwComposer对象&#xff0c;则创建BnHwComposer对象&#xff1b;
由于这里转换的是HwcHal对象&#xff0c;该对象实现了IComposer接口&#xff0c;但并不是BpHwComposer类型&#xff0c;因此将创建并返回一个BnHwComposer对象&#xff0c;接着通过_hidl_data.writeStrongBinder(_hidl_binder)将这个BnHwComposer对象传输给hwservicemanager进程&#xff0c;我们知道&#xff0c;binder驱动可以传输binder实体对象&#xff0c;binder驱动自动识别binder实体对象&#xff0c;并转化为binder代理对象&#xff0c;对端进程将得到binder代理对象。
system\libhwbinder\Parcel.cpp
status_t Parcel::writeStrongBinder(const sp
{ return flatten_binder(ProcessState::self(), val, this);
} status_t flatten_binder(const sp
{ flat_binder_object obj; obj.flags &#61; 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; if (binder !&#61; NULL) { sp
}
Hal进程将BnHwComposer对象传递给hwservicemanager后&#xff0c;hwservicemanager进程通过_hidl_err&#61;_hidl_data.readNullableStrongBinder(&_hidl_service_binder);拿到client进程发送过来的BnHwComposer对象&#xff0c;binder实体到达目的端进程将变为binder代理对象&#xff1a;
system\libhwbinder\Parcel.cpp
sp
{ sp
} status_t Parcel::readNullableStrongBinder(sp
{ return unflatten_binder(ProcessState::self(), *this, val);
} status_t unflatten_binder(const sp
{ const flat_binder_object* flat &#61; in.readObject
}
system\libhwbinder\ProcessState.cpp
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{ sp<IBinder> result; AutoMutex _l(mLock); handle_entry* e &#61; lookupHandleLocked(handle); if (e !&#61; NULL) { // We need to create a new BpHwBinder if there isn&#39;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 &#61; e->binder; if (b &#61;&#61; NULL || !e->refs->attemptIncWeak(this)) { b &#61; new BpHwBinder(handle); e->binder &#61; b; if (b) e->refs &#61; b->getWeakRefs(); result &#61; b; } else { // This little bit of nastyness is to allow us to add a primary // reference to the remote proxy when this team doesn&#39;t have one // but another team is sending the handle to us. result.force_set(b); e->refs->decWeak(this); } } return result;
}
因此hwservicemanager进程通过readStrongBinder()函数将得到BpHwBinder对象&#xff0c;然后通过fromBinder函数将binder代理对象转换为业务代理对象&#xff1a;
service &#61; ::android::hardware::fromBinder
template <typename IType, typename ProxyType, typename StubType>
sp
}
因此fromBinder函数功能如下&#xff1a;
如果是binder代理&#xff0c;则基于binder代理创建业务代理对象&#xff1b;
如果是binder实体&#xff0c;则得到业务实现类对象&#xff1b;
通过fromBinder函数后&#xff0c;这里将创建一个BpHwBase对象&#xff0c;并将BpHwBinder保存到其成员变量_hidl_impl中。
BpHwBase::BpHwBase(const ::android::sp<::android::hardware::IBinder> &_hidl_impl) : BpInterface<IBase>(_hidl_impl), ::android::hardware::details::HidlInstrumentor("android.hidl.base&#64;1.0", "IBase") {
}
Hal进程在向hwservicemanager进程注册IComposer接口服务时&#xff0c;通过服务实现类对象HwcHal经过toBinder函数将在Hal进程地址空间中创建binder实体对象BnHwComposer&#xff0c;然后将BnHwComposer发送给hwservicemanager进程&#xff0c;hwservicemanager进程将得到其binder代理对象BpHwBinder&#xff0c;然后经过fromBinder函数在自身进程地址空间中创建BpHwBase对象&#xff0c;如下图所示&#xff1a;
因此BnHwComposer和BpHwBinder才是真正的IBinder对象&#xff0c;hwservicemanager进程中的BpHwBase和Hal进程中的HwcHal就是通过BnHwComposer和BpHwBinder建立关联的&#xff0c;在Treble的binder架构中&#xff0c;无论是Client端还是Server端都是采用代理模式来实现的&#xff0c;这里与普通的binder通信框架有所区别&#xff0c;普通binder通信框架中&#xff0c;BpBinder和BnBinder都继承IBinder类&#xff0c;Client端的业务代理和Binder代理直接采用代理模式&#xff0c;而在Server端&#xff0c;业务实现在本地Binder的子类中。hwBinder下&#xff0c;命名有所混乱&#xff0c;让人很容易误以为BpHwXXX和BnHwXXX是binder通信下的代理对象和本地对象。
在AndroidO以前&#xff0c;Hal采用Legacy模式&#xff0c;Framework Server进程直接dlopen hal库&#xff0c;如下图所示&#xff1a;
但在AndroidO以后&#xff0c;所有的Hal独立运行在自己的进程空间&#xff0c;Framework Server进程通过binder访问Hal&#xff0c;为了兼容之前版本的hal实现&#xff0c;在hal库之上定义了一个hal实现类&#xff0c;用于封装hal接口&#xff0c;编译为XXX&#64;impl.so&#xff0c;hal进程在启动时通过dlopen该so库库得到Hal接口类对象&#xff0c;而XXX&#64;impl.so中又会dlopen真正的hal实现库。
上图说明对于Hal进程来说&#xff0c;默认使用PassthroughServiceManager来加载XXX&#64;impl.so库&#xff0c;并得到Hidl服务接口类对象&#xff0c;而对于要访问Hal的Client进程&#xff0c;比如Framework server进程&#xff0c;需要根据当前访问的hidl服务的Transport类型来决定获取方式&#xff0c;如果当前访问的hidl服务是hwbinder&#xff0c;那么就从hwservicemanager中查询&#xff0c;如果当前方位的hidl服务是PASSTHROUGH&#xff0c;那么久会采用PassthroughServiceManager将XXX&#64;impl.so库加载到当前进程地址空间。