前面介绍了HIDL服务在native层的实现过程,包括HIDL服务加载创建、服务注册、服务查询过程等,那么Java层是否也实现了相关的服务框架呢? 通常情况下,所有的Hal都实现在native层面,每个hal进程都是一个native进程,由init进程启动,在hal进程启动时会完成HIDL服务注册,Framework Server进程不一定完全是native进程,比如system_server进程,它运行在虚拟机环境中,由zygote进程fork而来,这时,Java层也需要请求HIDL服务,因此Android不仅在native层HIDL化了hal,在Java层同样也定义了相关的服务框架。
上图是Java层binder和hwbinder之间的类基础图对比。当我们定义一个.hal接口文件时,通过hidl-gen编译为Java文件后,将按上图中的类继承关系自动生成代码。
如上图所示,当我们定义IXXX.hal文件后,通过编译将在out/target/common/gen/JAVA_LIBRARIES目录下生成对应的IXXX.java,该文件按上述类继承关系自动生成相关代码,我们只需要定义一个XXXImp类,继承Stub并实现所有方法,然后在某个服务进程中创建一个XXXImp对象,并调用registerService()函数进行hidl服务注册,如下所示:
XXXImp mXXXImp = new XXXImp();
mXXXImp.registerAsService("XXXImp");
这样就完成了一个Java层的hidl服务注册,当然在当前Android系统中,大部分还是native层的hidl服务,Java层的hidl服务还是比较少的。从上述可知,Java层的hidl服务包括2个步骤:
1. hidl服务对象创建;
2.hidl服务注册;
Java hidl服务创建过程
从上面的类继承图可知,hidl服务实现类继承于Stub,Stub又继承于HwBinder,因此创建一个XXXImp对象时,会调用HwBinder的构造函数。
frameworks\base\core\java\android\os\HwBinder.java
public HwBinder() {
native_setup();
sNativeRegistry.registerNativeAllocation(
this,
mNativeContext);
}
static {
long freeFunction = native_init();
sNativeRegistry = new NativeAllocationRegistry(
HwBinder.class.getClassLoader(),
freeFunction,
128 /* size */);
}
创建HwBinder对象会首先执行native_init()函数,然后调用native_setup()函数。
frameworks\base\core\jni\android_os_HwBinder.cpp
static jlong JHwBinder_native_init(JNIEnv *env) {
JHwBinder::InitClass(env);
return reinterpret_cast<jlong>(&releaseNativeContext);
}
static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) {
sp<JHwBinderHolder> context = new JHwBinderHolder;
JHwBinder::SetNativeContext(env, thiz, context);
}
这里创建一个JHwBinderHolder 对象,并保存在HwBinder类的mNativeContext变量中。
sp<JHwBinderHolder> JHwBinder::SetNativeContext(
JNIEnv *env, jobject thiz, const sp<JHwBinderHolder> &context) {
sp<JHwBinderHolder> old =
(JHwBinderHolder *)env->GetLongField(thiz, gFields.contextID);
if (context != NULL) {
context->incStrong(NULL /* id */);
}
if (old != NULL) {
old->decStrong(NULL /* id */);
}
env->SetLongField(thiz, gFields.contextID, (long)context.get());
return old;
}
这里出现了多个binder类型:HwBinder、JHwBinderHolder、JHwBinder他们的类继承图如下:
红线标识了这3个类对象之间的关系,为了更加清晰地描述他们之间的关联关系,如下图所示:
Java hidl服务注册过程
当我们创建好了hidl服务类对象后,将调用mXXXImp.registerAsService("XXXImp");进行注册,注册过程如下:
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) {
if (serviceNameObj == NULL) {
jniThrowException(env, "java/lang/NullPointerException", NULL);
return;
}
const char *serviceName = env->GetStringUTFChars(serviceNameObj, NULL);
if (serviceName == NULL) {
return; // XXX exception already pending?
}
sp<hardware::IBinder> binder = JHwBinder::GetNativeBinder(env, thiz);
/* TODO(b/33440494) this is not right */
sp<hidl::base::V1_0::IBase> base = new hidl::base::V1_0::BpHwBase(binder);
auto manager = hardware::defaultServiceManager();
if (manager == nullptr) {
LOG(ERROR) << "Could not get hwservicemanager.";
signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return;
}
Return<bool> ret = manager->add(serviceName, base);
env->ReleaseStringUTFChars(serviceNameObj, serviceName);
serviceName = NULL;
bool ok = ret.isOk() && ret;
if (ok) {
LOG(INFO) << "Starting thread pool.";
::android::hardware::ProcessState::self()->startThreadPool();
}
signalExceptionForError(env, (ok ? OK : UNKNOWN_ERROR), true /* canThrowRemoteException */);
}
首先通过GetNativeBinder函数得到JHwBinder对象,然后创建一个BpHwBase来包装JHwBinder,并将BpHwBase注册到hwservicemanager中。
sp<JHwBinder> JHwBinder::GetNativeBinder(
JNIEnv *env, jobject thiz) {
JHwBinderHolder *holder =
reinterpret_cast<JHwBinderHolder *>(
env->GetLongField(thiz, gFields.contextID));
return holder->get(env, thiz);
}
sp<JHwBinder> get(JNIEnv *env, jobject obj) {
Mutex::Autolock autoLock(mLock);
sp<JHwBinder> binder = mBinder.promote();
if (binder == NULL) {
binder = new JHwBinder(env, obj);
mBinder = binder;
}
return binder;
}
从HwBinder的成员变量mNativeContext中得到JHwBinderHolder的对象指针,然后调用其get函数得到JHwBinder对象。然后将JHwBinder封装为BpHwBase对象。
android.hidl.base@1.0_genc++\gen\android\hidl\base\1.0\BaseAll.cpp
BpHwBase::BpHwBase(const ::android::sp<::android::hardware::IBinder> &_hidl_impl)
: BpInterface<IBase>(_hidl_impl),
::android::hardware::details::HidlInstrumentor("android.hidl.base@1.0", "IBase") {
}
因此Java hidl服务向hwservicemanager注册的还是BpHwBase对象,BpHwBase的mRemote变量引用的是JHwBinder对象,JHwBinder的成员变量mObject又保存了Java层的HwBinder的引用。
从进程空间角度来看Java hidl服务注册,如下:
BpHwBase注册到hwservicemanager的详细过程在前面的文章中已经有详细的介绍,这里不再重复。
Java hidl服务查询过程
既然有注册,那么肯定存在服务查询,那么Client进程如何查询这些运行在Server进程端的Java hidl服务呢?
out/target/common/gen/JAVA_LIBRARIES/android.hardware.wifi-V1.1-java_intermediates/android/hardware/wifi/V1_1/IWifi.java
public static IWifi getService(String serviceName) throws android.os.RemoteException {
return IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.1::IWifi",serviceName));
}
public static IWifi getService() throws android.os.RemoteException {
return IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.1::IWifi","default"));
}
这里首先调用android.os.HwBinder.getService("android.hardware.wifi@1.1::IWifi","default")来查询hidl服务,然后通过asInterface接口转换为与业务相关的接口对象。
服务查询过程
这里首先通过HwBinder.getService()接口从hwservicemanager进程中根据包名"android.hardware.wifi@1.1::IWifi","default"的hwBinder代理。
frameworks\base\core\java\android\os\HwBinder.java
public static native final IHwBinder getService(
String iface,
String serviceName)
throws RemoteException, NoSuchElementException;
frameworks\base\core\jni\android_os_HwBinder.cpp
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());
LOG(INFO) << "Looking for service "
<< ifaceName
<< "/"
<< serviceName;
Return<IServiceManager::Transport> transportRet =
manager->getTransport(ifaceNameHStr, serviceNameHStr);
if (!transportRet.isOk()) {
signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return NULL;
}
IServiceManager::Transport transport = transportRet;
#ifdef __ANDROID_TREBLE__
#ifdef __ANDROID_DEBUGGABLE__
const char* testingOverride = std::getenv("TREBLE_TESTING_OVERRIDE");
const bool vintfLegacy = (transport == IServiceManager::Transport::EMPTY)
&& testingOverride && !strcmp(testingOverride, "true");
#else // __ANDROID_TREBLE__ but not __ANDROID_DEBUGGABLE__
const bool vintfLegacy = false;
#endif // __ANDROID_DEBUGGABLE__
#else // not __ANDROID_TREBLE__
const bool vintfLegacy = (transport == IServiceManager::Transport::EMPTY);
#endif // __ANDROID_TREBLE__";
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;
}
Return<sp<hidl::base::V1_0::IBase>> ret = manager->get(ifaceNameHStr, serviceNameHStr);
if (!ret.isOk()) {
signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */);
return NULL;
}
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();
return JHwRemoteBinder::NewObject(env, service);
}
首先检查当前查询的hidl服务的Transport是否为hwbinder,然后通过hardware::defaultServiceManager()得到IServiceManager 在native层的业务代理对象BpHwServiceManager,接着通过BpHwServiceManager向hwservicemanager查询hidl服务,其实就是根据接口包名从hwservicemanager进程中的mServiceMap表中查找对应的HidlService对象,从而得到BpHwBase对象,通过前面文章对hidl服务查询过程分析可知,查询返回的IBase对象是BpHwBase对象。
这里接着通过hardware::toBinder接口将IBase对象转换为binder对象,其实就是从BpHwBase中拿到其成员变量mRemote中的BpHwBinder对象,最后在JNI层将调用JHwRemoteBinder::NewObject()函数来创建一个Java层HwRemoteBinder对象。
frameworks\base\core\jni\android_os_HwBinder.cpp
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;
}
首先调用HwRemoteBinder的构造函数创建一个HwRemoteBinder对象。
frameworks\base\core\java\android\os\HwRemoteBinder.java
static {
long freeFunction = native_init();
sNativeRegistry = new NativeAllocationRegistry(
HwRemoteBinder.class.getClassLoader(),
freeFunction,
128 /* size */);
}
public HwRemoteBinder() {
native_setup_empty();
sNativeRegistry.registerNativeAllocation(
this,
mNativeContext);
}
首先将执行静态代码块,做必要的初始化,然后执行对象的构造函数。
frameworks\base\core\jni\android_os_HwRemoteBinder.cpp
static jlong JHwRemoteBinder_native_init(JNIEnv *env) {
JHwRemoteBinder::InitClass(env);
return reinterpret_cast<jlong>(&releaseNativeContext);
}
static void JHwRemoteBinder_native_setup_empty(JNIEnv *env, jobject thiz) {
sp<JHwRemoteBinder> context =
new JHwRemoteBinder(env, thiz, NULL /* service */);
JHwRemoteBinder::SetNativeContext(env, thiz, context);
}
JHwRemoteBinder::JHwRemoteBinder(
JNIEnv *env, jobject thiz, const sp<hardware::IBinder> &binder)
: mBinder(binder) {
mDeathRecipientList = new HwBinderDeathRecipientList();
jclass clazz = env->GetObjectClass(thiz);
CHECK(clazz != NULL);
mObject = env->NewWeakGlobalRef(thiz);
}
这里在JNI层创建一个JHwRemoteBinder对象,并将其对象指针保存到Java层HwRemoteBinder的mNativeContext变量中。
sp<JHwRemoteBinder> JHwRemoteBinder::SetNativeContext(
JNIEnv *env, jobject thiz, const sp<JHwRemoteBinder> &context) {
sp<JHwRemoteBinder> old =
(JHwRemoteBinder *)env->GetLongField(thiz, gProxyOffsets.contextID);
if (context != NULL) {
context->incStrong(NULL /* id */);
}
if (old != NULL) {
old->decStrong(NULL /* id */);
}
env->SetLongField(thiz, gProxyOffsets.contextID, (long)context.get());
return old;
}
到此就完成了HwRemoteBinder对象的创建过程,接着会将查询到的IBinder保存到JHwRemoteBinder的mBinder变量中。
JHwRemoteBinder::GetNativeContext(env,obj)->setBinder(binder);
void JHwRemoteBinder::setBinder(const sp<hardware::IBinder> &binder) {
mBinder = binder;
}
这些对象之间的关系如下图所示:
因此Java hidl服务查询最终得到一个HwRemoteBinder对象。
接口转换过程
通过服务查询得到HwRemoteBinder对象,这个只是传输层面的对象而已,需要转换为业务层面的对象,这个是由IXXX.asInterface函数完成。
/* package private */ static IWifi asInterface(android.os.IHwBinder binder) {
if (binder == null) {
return null;
}
android.os.IHwInterface iface =
binder.queryLocalInterface(kInterfaceName);
if ((iface != null) && (iface instanceof IWifi)) {
return (IWifi)iface;
}
IWifi proxy = new IWifi.Proxy(binder);
try {
for (String descriptor : proxy.interfaceChain()) {
if (descriptor.equals(kInterfaceName)) {
return proxy;
}
}
} catch (android.os.RemoteException e) {
}
return null;
}
这里在HwRemoteBinder对象的基础上包裹了一层与业务相关的Proxy对象,这样业务和传输分离,通过代理方式实现IPC调用。
到此Treble架构下的hwBinder实现过程就基本介绍完成。