AndroidO Treble架构下HIDL服务Java框架实现

前面介绍了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层同样也定义了相关的服务框架。

AndroidO Treble架构下HIDL服务Java框架实现_第1张图片

上图是Java层binder和hwbinder之间的类基础图对比。当我们定义一个.hal接口文件时,通过hidl-gen编译为Java文件后,将按上图中的类继承关系自动生成代码。

AndroidO Treble架构下HIDL服务Java框架实现_第2张图片

如上图所示,当我们定义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的构造函数。

AndroidO Treble架构下HIDL服务Java框架实现_第3张图片

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(&releaseNativeContext);
}

static void JHwBinder_native_setup(JNIEnv *env, jobject thiz) {
    sp context = new JHwBinderHolder;
    JHwBinder::SetNativeContext(env, thiz, context);
}

这里创建一个JHwBinderHolder 对象,并保存在HwBinder类的mNativeContext变量中。

sp JHwBinder::SetNativeContext(
        JNIEnv *env, jobject thiz, const sp &context) {
    sp 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他们的类继承图如下:

AndroidO Treble架构下HIDL服务Java框架实现_第4张图片

红线标识了这3个类对象之间的关系,为了更加清晰地描述他们之间的关联关系,如下图所示:

AndroidO Treble架构下HIDL服务Java框架实现_第5张图片

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 binder = JHwBinder::GetNativeBinder(env, thiz);

    /* TODO(b/33440494) this is not right */
    sp 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 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::GetNativeBinder(
        JNIEnv *env, jobject thiz) {
    JHwBinderHolder *holder =
        reinterpret_cast(
                env->GetLongField(thiz, gFields.contextID));

    return holder->get(env, thiz);
}
sp get(JNIEnv *env, jobject obj) {
    Mutex::Autolock autoLock(mLock);

    sp binder = mBinder.promote();

    if (binder == NULL) {
        binder = new JHwBinder(env, obj);
        mBinder = binder;
    }

    return binder;
}

从HwBinder的成员变量mNativeContext中得到JHwBinderHolder的对象指针,然后调用其get函数得到JHwBinder对象。然后将JHwBinder封装为BpHwBase对象。

[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") {
}

因此Java hidl服务向hwservicemanager注册的还是BpHwBase对象,BpHwBase的mRemote变量引用的是JHwBinder对象,JHwBinder的成员变量mObject又保存了Java层的HwBinder的引用。

AndroidO Treble架构下HIDL服务Java框架实现_第6张图片

从进程空间角度来看Java hidl服务注册,如下:

AndroidO Treble架构下HIDL服务Java框架实现_第7张图片

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("[email protected]::IWifi",serviceName));
}

public static IWifi getService() throws android.os.RemoteException {
	return IWifi.asInterface(android.os.HwBinder.getService("[email protected]::IWifi","default"));
}

这里首先调用android.os.HwBinder.getService("[email protected]::IWifi","default")来查询hidl服务,然后通过asInterface接口转换为与业务相关的接口对象。

服务查询过程

这里首先通过HwBinder.getService()接口从hwservicemanager进程中根据包名"[email protected]::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 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> ret = manager->get(ifaceNameHStr, serviceNameHStr);

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

    sp 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对象。

AndroidO Treble架构下HIDL服务Java框架实现_第8张图片

这里接着通过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 &binder) {
    ScopedLocalRef 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(), "", "()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(&releaseNativeContext);
}

static void JHwRemoteBinder_native_setup_empty(JNIEnv *env, jobject thiz) {
    sp context =
        new JHwRemoteBinder(env, thiz, NULL /* service */);

    JHwRemoteBinder::SetNativeContext(env, thiz, context);
}
JHwRemoteBinder::JHwRemoteBinder(
        JNIEnv *env, jobject thiz, const sp &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::SetNativeContext(
        JNIEnv *env, jobject thiz, const sp &context) {
    sp 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 &binder) {
    mBinder = binder;
}

这些对象之间的关系如下图所示:

AndroidO Treble架构下HIDL服务Java框架实现_第9张图片

因此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调用。

AndroidO Treble架构下HIDL服务Java框架实现_第10张图片

到此Treble架构下的hwBinder实现过程就基本介绍完成。

你可能感兴趣的:(【Android,系统分析】)