AndroidO Treble架構下Tranport型別查詢過程
通過前面文章的分析,我們知道,Client程序在查詢hidl服務介面物件時,會根據該hidl服務的Tranport型別選擇載入方式,如果是HWBINDER,那麼就從hwservicemanager中查詢,如果是PASSTHROUGH,那麼就通過PassthroughServiceManager將hal實現庫dlopen到當前程序地址空間。那麼hidl服務的Tranport型別是如何得到的呢?
[cpp] view plain copy print?- 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);
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?- Return<ServiceManager::Transport> ServiceManager::getTransport(const hidl_string& fqName,
- const
- 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;
- }
- }
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?- 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;
- }
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?- // 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”));
- }
// 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?- 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);
- }
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?- 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;
- }
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型別。