1. 程式人生 > >AndroidO Treble架構下Tranport型別查詢過程

AndroidO Treble架構下Tranport型別查詢過程

通過前面文章的分析,我們知道,Client程序在查詢hidl服務介面物件時,會根據該hidl服務的Tranport型別選擇載入方式,如果是HWBINDER,那麼就從hwservicemanager中查詢,如果是PASSTHROUGH,那麼就通過PassthroughServiceManager將hal實現庫dlopen到當前程序地址空間。那麼hidl服務的Tranport型別是如何得到的呢?

[cpp] view plain copy print?
  1. const sp<::android::hidl::manager::V1_0::IServiceManager> sm = defaultServiceManager();  
  2. if (sm == nullptr) {  
  3.     ALOGE(”getService: defaultServiceManager() is null”);  
  4.     return nullptr;  
  5. }  
  6. Return<Transport> transportRet = sm->getTransport(IComposer::descriptor, serviceName);  
    const sp<::android::hidl::manager::V1_0::IServiceManager> sm = defaultServiceManager();
    if (sm == nullptr) {
        ALOGE("getService: defaultServiceManager() is null");
        return nullptr;
    }

    Return<Transport> transportRet = sm->getTransport(IComposer::descriptor, serviceName);

是呼叫hwservicemanager的getTransport函式來得到Tranport型別,這裡其實就是IPC進入hwservicemanager程序空間,執行ServiceManager物件的getTransport函式:

system\hwservicemanager\ServiceManager.cpp

[cpp] view plain copy print?
  1. Return<ServiceManager::Transport> ServiceManager::getTransport(const hidl_string& fqName,  
  2.                                                                const
     hidl_string& name) {  
  3.     using ::android::hardware::getTransport;  
  4.     pid_t pid = IPCThreadState::self()->getCallingPid();  
  5.     if (!mAcl.canGet(fqName, pid)) {  
  6.         return Transport::EMPTY;  
  7.     }  
  8.     switch (getTransport(fqName, name)) {  
  9.         case vintf::Transport::HWBINDER:  
  10.              return Transport::HWBINDER;  
  11.         case vintf::Transport::PASSTHROUGH:  
  12.              return Transport::PASSTHROUGH;  
  13.         case vintf::Transport::EMPTY:  
  14.         default:  
  15.              return Transport::EMPTY;  
  16.     }  
  17. }  
Return<ServiceManager::Transport> ServiceManager::getTransport(const hidl_string& fqName,
                                                               const hidl_string& name) {
    using ::android::hardware::getTransport;

    pid_t pid = IPCThreadState::self()->getCallingPid();
    if (!mAcl.canGet(fqName, pid)) {
        return Transport::EMPTY;
    }

    switch (getTransport(fqName, name)) {
        case vintf::Transport::HWBINDER:
             return Transport::HWBINDER;
        case vintf::Transport::PASSTHROUGH:
             return Transport::PASSTHROUGH;
        case vintf::Transport::EMPTY:
        default:
             return Transport::EMPTY;
    }
}

system\hwservicemanager\Vintf.cpp

[cpp] view plain copy print?
  1. vintf::Transport getTransport(const std::string &interfaceName, const std::string &instanceName) {  
  2.     FQName fqName(interfaceName);  
  3.     if (!fqName.isValid()) {  
  4.         LOG(DEBUG) << ”getTransport: ” << interfaceName << “ is not a valid fully-qualified name.”;  
  5.         return vintf::Transport::EMPTY;  
  6.     }  
  7.     if (!fqName.hasVersion()) {  
  8.         LOG(DEBUG) << ”getTransport: ” << fqName.string()  
  9.                    << ” does not specify a version. Using default transport.”;  
  10.         return vintf::Transport::EMPTY;  
  11.     }  
  12.     if (fqName.name().empty()) {  
  13.         LOG(DEBUG) << ”getTransport: ” << fqName.string()  
  14.                    << ” does not specify an interface name. Using default transport.”;  
  15.         return vintf::Transport::EMPTY;  
  16.     }  
  17.     vintf::Transport tr = getTransportFromManifest(fqName, instanceName,  
  18.             vintf::VintfObject::GetFrameworkHalManifest());  
  19.     if (tr != vintf::Transport::EMPTY) {  
  20.         return tr;  
  21.     }  
  22.     tr = getTransportFromManifest(fqName, instanceName,  
  23.             vintf::VintfObject::GetDeviceHalManifest());  
  24.     if (tr != vintf::Transport::EMPTY) {  
  25.         return tr;  
  26.     }  
  27.     LOG(WARNING) << ”getTransportFromManifest: Cannot find entry ”
  28.                  << fqName.string()  
  29.                  << ” in either framework or device manifest, using default transport.”;  
  30.     return vintf::Transport::EMPTY;  
  31. }  
vintf::Transport getTransport(const std::string &interfaceName, const std::string &instanceName) {
    FQName fqName(interfaceName);
    if (!fqName.isValid()) {
        LOG(DEBUG) << "getTransport: " << interfaceName << " is not a valid fully-qualified name.";
        return vintf::Transport::EMPTY;
    }
    if (!fqName.hasVersion()) {
        LOG(DEBUG) << "getTransport: " << fqName.string()
                   << " does not specify a version. Using default transport.";
        return vintf::Transport::EMPTY;
    }
    if (fqName.name().empty()) {
        LOG(DEBUG) << "getTransport: " << fqName.string()
                   << " does not specify an interface name. Using default transport.";
        return vintf::Transport::EMPTY;
    }

    vintf::Transport tr = getTransportFromManifest(fqName, instanceName,
            vintf::VintfObject::GetFrameworkHalManifest());
    if (tr != vintf::Transport::EMPTY) {
        return tr;
    }
    tr = getTransportFromManifest(fqName, instanceName,
            vintf::VintfObject::GetDeviceHalManifest());
    if (tr != vintf::Transport::EMPTY) {
        return tr;
    }

    LOG(WARNING) << "getTransportFromManifest: Cannot find entry "
                 << fqName.string()
                 << " in either framework or device manifest, using default transport.";
    return vintf::Transport::EMPTY;
}

首先校驗介面包名是否合法,然後呼叫getTransportFromManifest函式分別從/system/manifest.xml和/vendor/manifest.xml檔案中讀取當前hidl服務的Transport型別。GetFrameworkHalManifest函式將讀取/system/manifest.xml檔案,GetDeviceHalManifest函式將讀取/vendor/manifest.xml檔案。這些manifest.xml定義了每個hidl的傳輸型別。

system\libvintf\VintfObject.cpp

[cpp] view plain copy print?
  1. // static
  2. const HalManifest *VintfObject::GetDeviceHalManifest(bool skipCache) {  
  3.     return Get(&gDeviceManifest, skipCache,  
  4.             std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1,  
  5.                 ”/vendor/manifest.xml”));  
  6. }  
  7. // static
  8. const HalManifest *VintfObject::GetFrameworkHalManifest(bool skipCache) {  
  9.     return Get(&gFrameworkManifest, skipCache,  
  10.             std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1,  
  11.                 ”/system/manifest.xml”));  
  12. }  
// static
const HalManifest *VintfObject::GetDeviceHalManifest(bool skipCache) {
    return Get(&gDeviceManifest, skipCache,
            std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1,
                "/vendor/manifest.xml"));
}

// static
const HalManifest *VintfObject::GetFrameworkHalManifest(bool skipCache) {
    return Get(&gFrameworkManifest, skipCache,
            std::bind(&HalManifest::fetchAllInformation, std::placeholders::_1,
                "/system/manifest.xml"));
}

這裡就是xml的讀取解析,具體過程不在展開分析。

system\hwservicemanager\Vintf.cpp

[cpp] view plain copy print?
  1. vintf::Transport getTransportFromManifest(  
  2.         const FQName &fqName, const std::string &instanceName,  
  3.         const vintf::HalManifest *vm) {  
  4.     if (vm == nullptr) {  
  5.         return vintf::Transport::EMPTY;  
  6.     }  
  7.     return vm->getTransport(fqName.package(),  
  8.             vintf::Version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()},  
  9.             fqName.name(), instanceName);  
  10. }  
vintf::Transport getTransportFromManifest(
        const FQName &fqName, const std::string &instanceName,
        const vintf::HalManifest *vm) {
    if (vm == nullptr) {
        return vintf::Transport::EMPTY;
    }
    return vm->getTransport(fqName.package(),
            vintf::Version{fqName.getPackageMajorVersion(), fqName.getPackageMinorVersion()},
            fqName.name(), instanceName);
}

system\libvintf\HalManifest.cpp

[cpp] view plain copy print?
  1. Transport HalManifest::getTransport(const std::string &package, const Version &v,  
  2.             const std::string &interfaceName, const std::string &instanceName) const {  
  3.     for (const ManifestHal *hal : getHals(package)) {  
  4.         bool found = false;  
  5.         for (auto& ver : hal->versions) {  
  6.             if (ver.majorVer == v.majorVer && ver.minorVer >= v.minorVer) {  
  7.                 found = true;  
  8.                 break;  
  9.             }  
  10.         }  
  11.         if (!found) {  
  12.             LOG(DEBUG) << ”HalManifest::getTransport(“ << to_string(mType) << “): Cannot find ”
  13.                       << to_string(v) << ” in supported versions of ” << package;  
  14.             continue;  
  15.         }  
  16.         auto it = hal->interfaces.find(interfaceName);  
  17.         if (it == hal->interfaces.end()) {  
  18.             LOG(DEBUG) << ”HalManifest::getTransport(“ << to_string(mType) << “): Cannot find interface ’”
  19.                       << interfaceName << ”’ in ” << package << “@” << to_string(v);  
  20.             continue;  
  21.         }  
  22.         const auto &instances = it->second.instances;  
  23.         if (instances.find(instanceName) == instances.end()) {  
  24.             LOG(DEBUG) << ”HalManifest::getTransport(“ << to_string(mType) << “): Cannot find instance ’”
  25.                       << instanceName << ”’ in ”
  26.                       << package << ”@” << to_string(v) << “::” << interfaceName;  
  27.             continue;  
  28.         }  
  29.         return hal->transportArch.transport;  
  30.     }  
  31.     LOG(DEBUG) << ”HalManifest::getTransport(“ << to_string(mType) << “): Cannot get transport for ”
  32.                  << package << ”@” << v << “::” << interfaceName << “/” << instanceName;  
  33.     return Transport::EMPTY;  
  34. }  
Transport HalManifest::getTransport(const std::string &package, const Version &v,
            const std::string &interfaceName, const std::string &instanceName) const {

    for (const ManifestHal *hal : getHals(package)) {
        bool found = false;
        for (auto& ver : hal->versions) {
            if (ver.majorVer == v.majorVer && ver.minorVer >= v.minorVer) {
                found = true;
                break;
            }
        }
        if (!found) {
            LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find "
                      << to_string(v) << " in supported versions of " << package;
            continue;
        }
        auto it = hal->interfaces.find(interfaceName);
        if (it == hal->interfaces.end()) {
            LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find interface '"
                      << interfaceName << "' in " << package << "@" << to_string(v);
            continue;
        }
        const auto &instances = it->second.instances;
        if (instances.find(instanceName) == instances.end()) {
            LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot find instance '"
                      << instanceName << "' in "
                      << package << "@" << to_string(v) << "::" << interfaceName;
            continue;
        }
        return hal->transportArch.transport;
    }
    LOG(DEBUG) << "HalManifest::getTransport(" << to_string(mType) << "): Cannot get transport for "
                 << package << "@" << v << "::" << interfaceName << "/" << instanceName;
    return Transport::EMPTY;

}

這裡就是讀取解析manifest.xml,並從manifest.xml中查詢對應hidl服務的transport型別。