5. 获取服务

  JAVA层HIDL服务获取如下图所示:

java 调用本地html中的js方法 java调用hidl_Android10.0

 

5.1 获取服务调用栈

java 调用本地html中的js方法 java调用hidl_Android q_02

 

5.2 onClick()

[/vendor/ingres/hidl_demo/app/src/main/java/com/android/hidldemo/MainActivity.java]
 private IDemo mHidlService;
     public void onClick(View v) {
        switch (v.getId()) {
            case R.id.getHelloBtn:
                Log.d(TAG, "start to click");
                try {
                           //1.获取IDemo的hidl服务
                    mHidlService = IDemo.getService();
                    if (mHidlService == null) {
                        Log.e(TAG, "fail to get demo service");
                    } else {
                        Log.d(TAG, "success to get demo service");
                               //2.调用hidl接口
                        String result =  mHidlService.getHelloString("IngresGe");
                        Log.d(TAG, "HIDL return:" + result);
                    }
                } catch (RemoteException ex) {
                    Log.e(TAG, "exception, fail to get demo service");
                }

                break;
        }
    }

5.3 getService()

[/frameworks/base/core/java/android/os/HwBinder.java]
public static native final IHwBinder getService(
        String iface,
        String serviceName,
        boolean retry)
    throws RemoteException, NoSuchElementException;

这是一个JNI接口,参考上一节《JAVA层HIDL服务的注册原理》中的JNI的转换,在JNI层,进入JHwBinder_native_getService()

 

5.4 JHwBinder_native_getService

[/frameworks/base/core/jni/android_os_HwBinder.cpp]
static jobject JHwBinder_native_getService(
        JNIEnv *env,
        jclass /* clazzObj */,
        jstring ifaceNameObj,
        jstring serviceNameObj,
        jboolean retry) {

    using ::android::hidl::base::V1_0::IBase;
    using ::android::hardware::details::getRawServiceInternal;

    std::string ifaceName;
    {
        ScopedUtfChars str(env, ifaceNameObj);
        if (str.c_str() == nullptr) {
            return nullptr;  // NPE will be pending.
        }
        ifaceName = str.c_str();
    }

    std::string serviceName;
    {
        ScopedUtfChars str(env, serviceNameObj);
        if (str.c_str() == nullptr) {
            return nullptr;  // NPE will be pending.
        }
        serviceName = str.c_str();
    }
        //1.根据servicename获取一个IBase对象,通过前文可知,这里是一个 BpHwBase对象
    sp<IBase> ret = getRawServiceInternal(ifaceName, serviceName, retry /* retry */, false /* getStub */);
         //2.将IBase对象转换为binder对象,参考[5.8]
    sp<hardware::IBinder> service = hardware::toBinder<hidl::base::V1_0::IBase>(ret);

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

    LOG(INFO) << "HwBinder: Starting thread pool for getting: " << ifaceName << "/" << serviceName;
    ::android::hardware::ProcessState::self()->startThreadPool();

        //转换hidlservice,使之成为一个Java层HwRemoteBinder对象,参考[5.9]
    return JHwRemoteBinder::NewObject(env, service);
}

5.5 getRawServiceInternal()

[/system/libhidl/transport/ServiceManagement.cpp]
sp<::android::hidl::base::V1_0::IBase> getRawServiceInternal(const std::string& descriptor,
                                                             const std::string& instance,
                                                             bool retry, bool getStub) {
    using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
    using ::android::hidl::manager::V1_0::IServiceManager;
    sp<Waiter> waiter;

    sp<IServiceManager1_1> sm;
    Transport transport = Transport::EMPTY;
    if (kIsRecovery) {
        transport = Transport::PASSTHROUGH;
    } else {
            //1.拿到HwServiceManager的对象,参考[4.4.3]
        sm = defaultServiceManager1_1();
        if (sm == nullptr) {
            ALOGE("getService: defaultServiceManager() is null");
            return nullptr;
        }
            //2.获取IDemo服务的transport,确认是直通式PASSTHROUGH,还是绑定式:HWBINDER
            //transport可以在/vendor/etc/vintf/manifest.xml中查看<transport>hwbinder</transport>
        Return<Transport> transportRet = sm->getTransport(descriptor, instance);

        if (!transportRet.isOk()) {
            ALOGE("getService: defaultServiceManager()->getTransport returns %s",
                  transportRet.description().c_str());
            return nullptr;
        }
        transport = transportRet;
    }

    const bool vintfHwbinder = (transport == Transport::HWBINDER); //绑定式服务
    const bool vintfPassthru = (transport == Transport::PASSTHROUGH); //直通式服务
        ...

    for (int tries = 0; !getStub && (vintfHwbinder || vintfLegacy); tries++) {
        if (waiter == nullptr && tries > 0) {
            waiter = new Waiter(descriptor, instance, sm);
        }
        if (waiter != nullptr) {
            waiter->reset();  // don't reorder this -- see comments on reset()
        }
            //3.如果是绑定式的服务,调用 BpHwServiceManager::get(),参考[5.6]
        Return<sp<IBase>> ret = sm->get(descriptor, instance);
        if (!ret.isOk()) {
            ALOGE("getService: defaultServiceManager()->get returns %s for %s/%s.",
                  ret.description().c_str(), descriptor.c_str(), instance.c_str());
            break;
        }
        sp<IBase> base = ret;
        if (base != nullptr) {
            Return<bool> canCastRet =
                details::canCastInterface(base.get(), descriptor.c_str(), true /* emitError */);

            if (canCastRet.isOk() && canCastRet) {
                if (waiter != nullptr) {
                    waiter->done();
                }
                return base; // still needs to be wrapped by Bp class.
            }

            if (!handleCastError(canCastRet, descriptor, instance)) break;
        }

        // In case of legacy or we were not asked to retry, don't.
        if (vintfLegacy || !retry) break;

        if (waiter != nullptr) {
            ALOGI("getService: Trying again for %s/%s...", descriptor.c_str(), instance.c_str());
            waiter->wait(true /* timeout */);
        }
    }

    if (waiter != nullptr) {
        waiter->done();
    }

    if (getStub || vintfPassthru || vintfLegacy) {
            //如果是直通式的hidl服务,获取直通式的HwServiceManager对象来获取服务
        const sp<IServiceManager> pm = getPassthroughServiceManager();
        if (pm != nullptr) {
            sp<IBase> base = pm->get(descriptor, instance).withDefault(nullptr);
            if (!getStub || trebleTestingOverride) {
                base = wrapPassthrough(base);
            }
            return base;
        }
    }

    return nullptr;
}

getRawServiceInternal()步骤如下:

1.获取HwServiceManager的代理对象

2.获取IDemo 这个hidl服务的transport,来确认是绑定式服务,还是直通式服务

3.根据transport类型,调用不同的接口来获取服务对象 (我们设计的IDemo是绑定式hidl服务)

 

5.6 BpHwServiceManager::get()

[/out/soong/.intermediates/system/libhidl/transport/manager/1.2/android.hidl.manager@1.2_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp]
::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>> BpHwServiceManager::get(const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name){
    ::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>>  _hidl_out = ::android::hidl::manager::V1_0::BpHwServiceManager::_hidl_get(this, this, fqName, name);

    return _hidl_out;
}

_hidl_get流程如下:

1.准备两个Parcel结构-- _hidl_data,_hidl_reply

2.组装Parcel数据

3.写入RPC头信息"android.hidl.manager@1.2::IServiceManager"

4.写入服务名称,如果没有配置的话,name为"default"

5.调用remote的transact,发送 1 /* get */的命令获取hidl服务

7.得到返回的reply数据

8.从reply中读取hidl binder的信息,转换成hidl service,发送出去

::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>> BpHwServiceManager::_hidl_get(::android::hardware::IInterface *_hidl_this, ::android::hardware::details::HidlInstrumentor *_hidl_this_instrumentor, const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name) {
        ...
    ::android::hardware::Parcel _hidl_data; //定义一个Parcel的data数据包
    ::android::hardware::Parcel _hidl_reply;//定义一个Parcel的reply数据包
    ::android::status_t _hidl_err;
    ::android::hardware::Status _hidl_status;

    ::android::sp<::android::hidl::base::V1_0::IBase> _hidl_out_service;

        //1.写入RPC头信息"android.hidl.manager@1.2::IServiceManager"
    _hidl_err = _hidl_data.writeInterfaceToken(BpHwServiceManager::descriptor);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    size_t _hidl_fqName_parent;

       //2.写入fqName,如果没有配置的话,name为"default"
    _hidl_err = _hidl_data.writeBuffer(&fqName, sizeof(fqName), &_hidl_fqName_parent);
    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    _hidl_err = ::android::hardware::writeEmbeddedToParcel(
            fqName,
            &_hidl_data,
            _hidl_fqName_parent,
            0 /* parentOffset */);

    if (_hidl_err != ::android::OK) { goto _hidl_error; }

    size_t _hidl_name_parent;
        //3.写入hidl 服务name
    _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; }
    //5.调用BpHwBinder::transact()
    //_hidl_this 指的是 BpHwServiceManager,通过asBinder转换为传输层面的BpHwBinder对象,其实就是取出BpHwServiceManager的成员变量mRemote的值
    _hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact(1 /* get */, _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; }

    {
            //7.从reply的数据中读取,hidl_Binder
        ::android::sp<::android::hardware::IBinder> _hidl_binder;
        _hidl_err = _hidl_reply.readNullableStrongBinder(&_hidl_binder);
        if (_hidl_err != ::android::OK) { goto _hidl_error; }

             //8.把hidl binder转换成hidl service
        _hidl_out_service = ::android::hardware::fromBinder<::android::hidl::base::V1_0::IBase,::android::hidl::base::V1_0::BpHwBase,::android::hidl::base::V1_0::BnHwBase>(_hidl_binder);
    }
        ...
    _hidl_status.setFromStatusT(_hidl_err);
        //9.返回hidl service对象
    return ::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>>(_hidl_out_service);

_hidl_error:
    _hidl_status.setFromStatusT(_hidl_err);
    return ::android::hardware::Return<::android::sp<::android::hidl::base::V1_0::IBase>>(_hidl_status);
}

根据如下调用栈所示,BpHwBinder::transact()最终会转到BnHwServiceManager::_hidl_get()

java 调用本地html中的js方法 java调用hidl_hwbinder_03

 

5.7 BnHwServiceManager::_hidl_get()

[/out/soong/.intermediates/system/libhidl/transport/manager/1.2/android.hidl.manager@1.2_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp]
::android::status_t BnHwServiceManager::_hidl_get(
        ::android::hidl::base::V1_0::BnHwBase* _hidl_this,
        const ::android::hardware::Parcel &_hidl_data,
        ::android::hardware::Parcel *_hidl_reply,
        TransactCallback _hidl_cb) {

        ...
    ::android::status_t _hidl_err = ::android::OK;
    if (!_hidl_data.enforceInterface(BnHwServiceManager::Pure::descriptor)) {
        _hidl_err = ::android::BAD_TYPE;
        return _hidl_err;
    }

    const ::android::hardware::hidl_string* fqName;
    const ::android::hardware::hidl_string* name;

    size_t _hidl_fqName_parent;

        //1.获取hidl服务的fqName
    _hidl_err = _hidl_data.readBuffer(sizeof(*fqName), &_hidl_fqName_parent,  reinterpret_cast<const void **>(&fqName));

    if (_hidl_err != ::android::OK) { return _hidl_err; }

    _hidl_err = ::android::hardware::readEmbeddedFromParcel(
            const_cast<::android::hardware::hidl_string &>(*fqName),
            _hidl_data,
            _hidl_fqName_parent,
            0 /* parentOffset */);

    if (_hidl_err != ::android::OK) { return _hidl_err; }

    size_t _hidl_name_parent;

        //2.获取hidl服务的name
    _hidl_err = _hidl_data.readBuffer(sizeof(*name), &_hidl_name_parent,  reinterpret_cast<const void **>(&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; }

    atrace_begin(ATRACE_TAG_HAL, "HIDL::IServiceManager::get::server");
        ...
        //3.根据hidl服务的fqName和name,从HwServiceManager的hidl service的map中拿到服务对象
    ::android::sp<::android::hidl::base::V1_0::IBase> _hidl_out_service = static_cast<IServiceManager*>(_hidl_this->getImpl().get())->get(*fqName, *name);

        //4.把reply信息写入Parcel
    ::android::hardware::writeToParcel(::android::hardware::Status::ok(), _hidl_reply);

    if (_hidl_out_service == nullptr) {
        _hidl_err = _hidl_reply->writeStrongBinder(nullptr);
    } else {
            //5.把获取的hidl服务转成IBinder对象
        ::android::sp<::android::hardware::IBinder> _hidl_binder = ::android::hardware::getOrCreateCachedBinder(_hidl_out_service.get());
        if (_hidl_binder.get() != nullptr) {
                  //6.把转换后的IBinder对象,写入reply的Parcel数据中
            _hidl_err = _hidl_reply->writeStrongBinder(_hidl_binder);
        } else {
            _hidl_err = ::android::UNKNOWN_ERROR;
        }
    }
    /* _hidl_err ignored! */

    atrace_end(ATRACE_TAG_HAL);
         ..
     //7.通过回调,把reply的Parcel数据给发给client
    _hidl_cb(*_hidl_reply);
    return _hidl_err;
}

_hidl_get流程如下:

       1.获取hidl服务的fqName

       2.获取hidl服务的name

       3.根据hidl服务的fqName和name,从HwServiceManager的hidl service的map中拿到服务对象

       4.把reply信息写入Parcel

       5.把获取的hidl服务转成IBinder对象

       6.把转换后的IBinder对象,写入reply的Parcel数据中

       7.通过回调,把reply的Parcel数据给发给client

 

5.7.1 ServiceManager::get()

[/system/hwservicemanager/ServiceManager.cpp]
Return<sp<IBase>> ServiceManager::get(const hidl_string& hidlFqName,
                                      const hidl_string& hidlName) {
    const std::string fqName = hidlFqName;
    const std::string name = hidlName;

    if (!mAcl.canGet(fqName, getBinderCallingContext())) {
        return nullptr;
    }

        //1.根据fqName和name找到对应的hidlService
    HidlService* hidlService = lookup(fqName, name);
    if (hidlService == nullptr) {
        tryStartService(fqName, name);
        return nullptr;
    }

    //2.根据hidlService 拿到IBase的对象
    sp<IBase> service = hidlService->getService();
    if (service == nullptr) {
        tryStartService(fqName, name);
        return nullptr;
    }

    hidlService->guaranteeClient();

    hardware::addPostCommandTask([hidlService] {
        hidlService->handleClientCallbacks(false /* isCalledOnInterval */);
    });

    return service;
}

5.7.2 ServiceManager::lookup()

  主要是根据fqName和name从 HwServiceManager的服务map:mServiceMap 中找到对应的hidlservice

[/system/hwservicemanager/ServiceManager.cpp]
HidlService* ServiceManager::lookup(const std::string& fqName, const std::string& name) {
        //1.根据fqName从 mServiceMap 中 找到一个节点
    auto ifaceIt = mServiceMap.find(fqName);
    if (ifaceIt == mServiceMap.end()) {
        return nullptr;
    }
        //2.从找到的map节点中,拿到PackageInterfaceMap的内容
    PackageInterfaceMap &ifaceMap = ifaceIt->second;
        //3.从PackageInterfaceMap中根据name找到hidlService
    HidlService *hidlService = ifaceMap.lookup(name);

    return hidlService;
}

5.7.3 HidlService::getService()

返回hidlservice的mService成员

[/system/hwservicemanager/HidlService.cpp]
sp<IBase> HidlService::getService() const {
    return mService;
}

HwServiceManager中hidl服务的管理map:

java 调用本地html中的js方法 java调用hidl_Android q_04

5.8 toBinder()

  toBinder接口将IBase对象转换为binder对象,其实就是从BpHwBase中拿到其成员变量mRemote中的BpHwBinder对象

[/system/libhidl/transport/include/hidl/HidlBinderSupport.h]
sp<IBinder> toBinder(sp<IType> iface) {
    IType *ifacePtr = iface.get();
    return getOrCreateCachedBinder(ifacePtr);
}

sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr) {
    if (ifacePtr == nullptr) {
        return nullptr;
    }

    if (ifacePtr->isRemote()) {
        using ::android::hidl::base::V1_0::BpHwBase;
            //从BpHwBase中拿到其成员变量mRemote中的BpHwBinder对象
        BpHwBase* bpBase = static_cast<BpHwBase*>(ifacePtr);
        BpHwRefBase* bpRefBase = static_cast<BpHwRefBase*>(bpBase);
        return sp<IBinder>(bpRefBase->remote());
    }

    std::string descriptor = details::getDescriptor(ifacePtr);
    if (descriptor.empty()) {
        // interfaceDescriptor fails
        return nullptr;
    }

    // for get + set
    std::unique_lock<std::mutex> _lock = details::gBnMap->lock();

    wp<BHwBinder> wBnObj = details::gBnMap->getLocked(ifacePtr, nullptr);
    sp<IBinder> sBnObj = wBnObj.promote();

    if (sBnObj == nullptr) {
        auto func = details::getBnConstructorMap().get(descriptor, nullptr);
        if (!func) {
            // TODO(b/69122224): remove this static variable when prebuilts updated
            func = details::gBnConstructorMap->get(descriptor, nullptr);
        }
        LOG_ALWAYS_FATAL_IF(func == nullptr, "%s gBnConstructorMap returned null for %s", __func__,
                            descriptor.c_str());

        sBnObj = sp<IBinder>(func(static_cast<void*>(ifacePtr)));
        LOG_ALWAYS_FATAL_IF(sBnObj == nullptr, "%s Bn constructor function returned null for %s",
                            __func__, descriptor.c_str());

        details::gBnMap->setLocked(ifacePtr, static_cast<BHwBinder*>(sBnObj.get()));
    }

    return sBnObj;
}

5.9 JHwRemoteBinder::NewObject()

  在JNI层将调用JHwRemoteBinder::NewObject()函数来创建一个Java层HwRemoteBinder对象,转换hidlservice,使之成为一个Java层HwRemoteBinder对象

[/frameworks/base/core/jni/android_os_HwRemoteBinder.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;
}

 

5.10 asInterface(android.os.IHwBinder binder)

  通过服务查询得到HwRemoteBinder对象,这个只是传输层面的对象而已,需要转换为业务层面的对象,这个是由IXXX.asInterface函数完成

[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]
    /* package private */ static IDemo asInterface(android.os.IHwBinder binder) {
        if (binder == null) {
            return null;
        }

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

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

        IDemo proxy = new IDemo.Proxy(binder);

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

        return null;
    }

6. Client-Server接口调用

  JAVA层 Client和Server的对象转换如下图所示:

java 调用本地html中的js方法 java调用hidl_binder_05

在[4] 和[5]节中,我们知道了服务注册registerService()和获取服务getService()的流程,接下来我们再看一看接口调用是如何进行的。

       上面调用的流程,其实和registerService()、getService()类似,都是组装Parcel数据,准备服务端的code,调用HwBinderProxy.transact()发送到服务端。

       但是和服务注册不同的是,在服务注册中,Native的HwServiceManager是Server端,服务实体是Client端。接口调用时,服务实体是Server端。

       服务端接收到CLient的请求后,根据下图的流程,最终流转到服务实体的onTransact()中,对解析出来的Parcel数据进行处理。

java 调用本地html中的js方法 java调用hidl_hwbinder_06

 

7.代码路径

/system/libhwbinder/BpHwBinder.cpp
/system/libhwbinder/IPCThreadState.cpp
/system/hwservicemanager/HidlService.cpp
/system/hwservicemanager/ServiceManager.cpp
/system/libhidl/transport/ServiceManagement.cpp
/system/libhidl/transport/include/hidl/HidlBinderSupport.h
/frameworks/base/core/jni/android_os_HwBinder.cpp
/frameworks/base/core/java/android/os/HwBinder.java
/frameworks/base/core/jni/android_os_HwRemoteBinder.cpp
/vendor/ingres/hal_demo/java/src/com/android/demo/Server.java
/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
/out/soong/.intermediates/system/libhidl/transport/base/1.0/android.hidl.base@1.0_genc++/gen/android/hidl/base/1.0/BaseAll.cpp
/out/soong/.intermediates/system/libhidl/transport/manager/1.2/android.hidl.manager@1.2_genc++/gen/android/hidl/manager/1.2/ServiceManagerAll.cpp