get hidl service


1. BpHwServiceManager::_hidl_get()

transact(/*get*/)

2. BnHwServiceManager::_hidl_get()

上面transact()會call到hwservicemanager的BnHwServiceManager::_hidl_get(),在這個函數中,首先call hwservicemanager/ServiceManager.cpp的get()拿到一個BpHwBase對象,然后call toBinder()將其轉化為BpHwBinder對象,詳細分析如下:

因為iface為BpHwBase,在BpHwBase.h里,isRemote()被override里,會return true,所以ifacePtr->isRemote()條件成立。

sp<IBinder> toBinder(sp<IType> iface) {
    IType *ifacePtr = iface.get();
    if (ifacePtr == nullptr) {
        return nullptr;
    }
    if (ifacePtr->isRemote()) {
        return ::android::hardware::IInterface::asBinder(
            static_cast<BpInterface<IType>*>(ifacePtr));

 

然后call writeStrongBinder()將上面的BpHwBinder寫到Parcel reply里。在flatten_binder()里,因為參數binder為BpHwBinder,所以binder->localBinder()會return false,而binder->remoteBinder()會return this,即BpHwBinder this指針。

proxy->handle()即在registerAsService時在hwservicemanager的BnHwServiceManager::_hidl_add函數里call的readNullableStrongBinder()時創建BpHwBinder時作為BpHwBinder構造函數的參數的handle。

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
    flat_binder_object obj;

    if (binder != NULL) {
        BHwBinder *local = binder->localBinder();
        if (!local) {
            BpHwBinder *proxy = binder->remoteBinder();
            if (proxy == NULL) {
                ALOGE("null proxy");
            }
            const int32_t handle = proxy ? proxy->handle() : 0;
            obj.hdr.type = BINDER_TYPE_HANDLE;
            obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
            obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
            obj.handle = handle;
            obj.cookie = 0;

 

3. 從hwservicemanager返回,回到BpHwServiceManager::_hidl_get()

call readNullableStrongBinder(),這個函數call到getStrongProxyForHandle(),在這個函數里,根據handle拿到對應的handle_entry,這時e->binder不是null了,所以這個函數就是return一個BpHwBinder對象。

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        // We need to create a new BpHwBinder if there isn'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 = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            b = new BpHwBinder(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            // This little bit of nastyness is to allow us to add a primary
            // reference to the remote proxy when this team doesn't have one
            // but another team is sending the handle to us.
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

 

 

然后根據上面得到的BpHwBinder call fromBinder(),在fromBinder里,因為參數binderIface為BpHwBinder,所以,binderIface->localBinder()會return null,所以這里會new一個ProxyType,即new一個BpHwBase

template <typename IType, typename ProxyType, typename StubType>
sp<IType> fromBinder(const sp<IBinder>& binderIface) {
    using ::android::hidl::base::V1_0::IBase;
    using ::android::hidl::base::V1_0::BnHwBase;

    if (binderIface.get() == nullptr) {
        return nullptr;
    }
    if (binderIface->localBinder() == nullptr) {
        return new ProxyType(binderIface);
    } 

所以sm->get()會返回一個BpHwBase,然后call details::canCastInterface(),這個函數在system/libhidl/transport/hidltransportutils.cpp里。這里的castTo是omall.cpp里call getServiceInternal<BpHwOmx>()的BpHwOmx的pure成員,pure成員即是IOmx,注意這里的IOmx是out/soong下的IOmx,所以這里的castTo即是IOmx::descriptor,即在omxall.cpp中的:

const char* IOmx::descriptor("android.hardware.media.omx@1.0::IOmx");

 而IBase::descriptor是const char* IBase::descriptor("android.hidl.base@1.0::IBase"),所以會call到下面的interface->interfaceChain()

Return<bool> canCastInterface(IBase* interface, const char* castTo, bool emitError) {
    if (interface == nullptr) {
        return false;
    }

    // b/68217907
    // Every HIDL interface is a base interface.
    if (std::string(IBase::descriptor) == castTo) {
        return true;
    }

    bool canCast = false;
    auto chainRet = interface->interfaceChain([&](const hidl_vec<hidl_string> &types) {
        for (size_t i = 0; i < types.size(); i++) {
            if (types[i] == castTo) {
                canCast = true;
                break;
            }
        }
    });

    if (!chainRet.isOk()) {
        // call fails, propagate the error if emitError
        return emitError
                ? details::StatusOf<void, bool>(chainRet)
                : Return<bool>(false);
    }

    return canCast;
}

下面說下interface->interfaceChain()的call flow,這個interface是一個BpHwBase,所以是call的BpHwBase的interfaceChain(),而這個函數會call到BnHwBase::_hidl_interfaceChain()。這個函數會call static_cast<IBase*>(_hidl_this->getImpl().get())->interfaceChain(),而這個interfaceChain()是IOmx::interfaceChain(),所以寫到_hidl_reply里的_hidl_out_descriptors是:

::android::hardware::media::omx::V1_0::IOmx::descriptor
::android::hidl::base::V1_0::IBase::descriptor

 

BnHwBase::_hidl_interfaceChain()

static_cast<IBase*>(_hidl_this->getImpl().get())->interfaceChain([&](const auto &_hidl_out_descriptors) {
if (_hidl_callbackCalled) {

LOG_ALWAYS_FATAL("interfaceChain: _hidl_cb called a second time, but must be called once.");

}

_hidl_callbackCalled = true;

::android::hardware::writeToParcel(::android::hardware::Status::ok(), _hidl_reply);

size_t _hidl__hidl_out_descriptors_parent;

_hidl_err = _hidl_reply->writeBuffer(&_hidl_out_descriptors, sizeof(_hidl_out_descriptors), &_hidl__hidl_out_descriptors_parent);

 

 

::android::hardware::Return<void> IOmx::interfaceChain(interfaceChain_cb _hidl_cb){
_hidl_cb({

::android::hardware::media::omx::V1_0::IOmx::descriptor,

::android::hidl::base::V1_0::IBase::descriptor,

});

return ::android::hardware::Void();}

 

 

然后在返回到BpHwBase::_hidl_interfaceChain(),完成了這個函數里的transact()后,call Parcel::readBuffer從Parcel reply中讀取descriptors,然后再將這個descriptors作為參數call canCastInterface中的匿名函數,在這個匿名函數中,將descriptors中的descriptor和castTo比較,如上面分析,castTo是::android::hardware::media::omx::V1_0::IOmx::descriptor,而descriptors中其中一個就是它,所以canCast會被賦值為true。所以canCastInterface()會return true。

 

所以getRawServiceInternal()會返回一個BpHwBase。

 

回到getServiceInternal(),因為getRawServiceInternal()return的是一個BpHwBase,即base是一個BpHwBase,所以base->isRemote()會return true,所以這時會new一個BpHwOmx對象。

所以IOmx::getService()拿到的是一個BpHwOmx對象。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM