AndroidO Treble架構下Hal程序啟動及HIDL服務註冊過程--不全
通過前面對Treble架構的介紹,我們知道,Android Framework程序和Hal分離,每個Hal獨立執行在自己的程序地址空間,那麼這些Hal程序是如何啟動的呢?本文以composer hal為例展開分析。
在以下路徑有composer hal的rc啟動指令碼:
hardware/interfaces/graphics/composer/2.1/default/[email protected]
- service hwcomposer-2-1 /vendor/bin/hw/[email protected]
- class hal animation
- user system
- group graphics drmrpc
- capabilities SYS_NICE
- onrestart restart surfaceflinger
編譯後,會將該指令碼檔案copy到vendor/etc/init目錄,在開機時,init程序會讀取並解析這個指令碼,然後啟動[email protected]程序:
system 661 1 32288 7832 0 0 S [email protected]
該程序的可執行檔案是:vendor/bin/hw/[email protected],
該可執行檔案對應的原始碼為:hardware/interfaces/graphics/composer/2.1/default/service.cpp
composer Hal啟動過程
hardware/interfaces/graphics/composer/2.1/default/service.cpp
- int main() {
- // the conventional HAL might start binder services
- android::ProcessState::initWithDriver("/dev/vndbinder");
- android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
- android::ProcessState::self()->startThreadPool();
- // same as SF main thread
- struct sched_param param = {0};
- param.sched_priority = 2;
- if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK,
- ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO: %d", errno);
- }
- return defaultPassthroughServiceImplementation<IComposer>(4);
- }
前面我們分析了Treble架構下的binder通訊變化,在Treble架構下,存在了3個binder裝置,分別是/dev/binder、/dev/vndbinder、/dev/hwbinder,上層需要通過binder庫來訪問這些binder裝置,而/dev/binder和/dev/vndbinder都是由libbinder來訪問,因此需要指定開啟的binder裝置。android::ProcessState::initWithDriver("/dev/vndbinder");
這句說明composer hal通過vndbinder來通訊的,接下來就是設定binder執行緒個數為4,並啟動binder執行緒池,然後呼叫defaultPassthroughServiceImplementation<IComposer>(4)
完成composer hal的啟動。
system\libhidl\transport\include\hidl\LegacySupport.h
- template<class Interface>
- __attribute__((warn_unused_result))
- status_t defaultPassthroughServiceImplementation(std::string name,
- size_t maxThreads = 1) {
- configureRpcThreadpool(maxThreads, true); //配置binder執行緒個數
- status_t result = registerPassthroughServiceImplementation<Interface>(name);
- if (result != OK) {
- return result;
- }
- joinRpcThreadpool();
- return 0;
- }
- template<class Interface>
- __attribute__((warn_unused_result))
- status_t registerPassthroughServiceImplementation(
- std::string name = "default") {
- sp<Interface> service = Interface::getService(name, true /* getStub */); //從當前程序空間中拿到IComposer介面類物件
- if (service == nullptr) {
- ALOGE("Could not get passthrough implementation for %s/%s.",
- Interface::descriptor, name.c_str());
- return EXIT_FAILURE;
- }
- LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
- Interface::descriptor, name.c_str());
- status_t status = service->registerAsService(name);//將IComposer註冊到hwservicemanager中
- if (status == OK) {
- ALOGI("Registration complete for %s/%s.",
- Interface::descriptor, name.c_str());
- } else {
- ALOGE("Could not register service %s/%s (%d).",
- Interface::descriptor, name.c_str(), status);
- }
- return status;
- }
Hal程序獲取IComposer類物件
在composer hal程序啟動時,首先呼叫IComposer 的getService(“default”,true)來獲取IComposer的類物件。
composer\2.1\[email protected]_genc++\gen\android\hardware\graphics\composer\2.1\ComposerAll.cpp
- ::android::sp<IComposer> IComposer::getService(const std::string &serviceName, const bool getStub) {
- using ::android::hardware::defaultServiceManager;
- using ::android::hardware::details::waitForHwService;
- using ::android::hardware::getPassthroughServiceManager;
- using ::android::hardware::Return;
- using ::android::sp;
- using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
- sp<IComposer> iface = nullptr;
- const sp<::android::hidl::manager::V1_0::IServiceManager> sm = defaultServiceManager(); //獲取hwservicemanager的代理
- if (sm == nullptr) {
- ALOGE("getService: defaultServiceManager() is null");
- return nullptr;
- }
- Return<Transport> transportRet = sm->getTransport(IComposer::descriptor, serviceName);//查詢IComposer的Transport
- if (!transportRet.isOk()) {
- ALOGE("getService: defaultServiceManager()->getTransport returns %s", transportRet.description().c_str());
- return nullptr;
- }
- Transport transport = transportRet;
- const bool vintfHwbinder = (transport == Transport::HWBINDER);
- const bool vintfPassthru = (transport == Transport::PASSTHROUGH); //Transport型別判斷
- #ifdef __ANDROID_TREBLE__
- #ifdef __ANDROID_DEBUGGABLE__
- const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
- const bool trebleTestingOverride = env && !strcmp(env, "true");
- const bool vintfLegacy = (transport == Transport::EMPTY) && trebleTestingOverride;
- #else // __ANDROID_TREBLE__ but not __ANDROID_DEBUGGABLE__
- const bool trebleTestingOverride = false;
- const bool vintfLegacy = false;
- #endif // __ANDROID_DEBUGGABLE__
- #else // not __ANDROID_TREBLE__
- const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
- const bool trebleTestingOverride = env && !strcmp(env, "true");
- const bool vintfLegacy = (transport == Transport::EMPTY);
- #endif // __ANDROID_TREBLE__
- //hwbinder方式下獲取IComposer物件
- for (int tries = 0; !getStub && (vintfHwbinder || (vintfLegacy && tries == 0)); tries++) {
- if (tries > 1) {
- ALOGI("getService: Will do try %d for %s/%s in 1s...", tries, IComposer::descriptor, serviceName.c_str());
- sleep(1);
- }
- if (vintfHwbinder && tries > 0) {
- waitForHwService(IComposer::descriptor, serviceName);
- }
- Return<sp<::android::hidl::base::V1_0::IBase>> ret =
- sm->get(IComposer::descriptor, serviceName);
- if (!ret.isOk()) {
- ALOGE("IComposer: defaultServiceManager()->get returns %s", ret.description().c_str());
- break;
- }
- sp<::android::hidl::base::V1_0::IBase> base = ret;
- if (base == nullptr) {
- if (tries > 0) {
- ALOGW("IComposer: found null hwbinder interface");
- }continue;
- }
- Return<sp<IComposer>> castRet = IComposer::castFrom(base, true /* emitError */);
- if (!castRet.isOk()) {
- if (castRet.isDeadObject()) {
- ALOGW("IComposer: found dead hwbinder service");
- continue;
- } else {
- ALOGW("IComposer: cannot call into hwbinder service: %s; No permission? Check for selinux denials.", castRet.description().c_str());
- break;
- }
- }
- iface = castRet;
- if (iface == nullptr) {
- ALOGW("IComposer: received incompatible service; bug in hwservicemanager?");
- break;
- }
- return iface;
- }
- //passthrough方式下獲取IComposer物件
- if (getStub || vintfPassthru || vintfLegacy) {
- const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
- if (pm != nullptr) {
- Return<sp<::android::hidl::base::V1_0::IBase>> ret =
- pm->get(IComposer::descriptor, serviceName);
- if (ret.isOk()) {
- sp<::android::hidl::base::V1_0::IBase> baseInterface = ret;
- if (baseInterface != nullptr) {
- iface = IComposer::castFrom(baseInterface);
- if (!getStub || trebleTestingOverride) {
- iface = new BsComposer(iface);
- }
- }
- }
- }
- }
- return iface;
- }
這裡通過hwservicemanager獲取當前服務的Tranport型別,Treble中定義的Tranport包括passthrough和binderized,每個hidl服務都在/system/manifest.xml或者/vendor/manifest.xml中指定了對應的Tranport型別:
manifest.xml檔案的讀取和解析都是由hwservicemanager來完成的,此時[email protected]作為hwservicemanager的client端,通過hwservicemanager的binder代理物件來請求hwservicemanager程序查詢IComposer的Transport型別,從上圖可以看出IComposer的Transport被定義為hwbinder,因此:
vintfHwbinder=true
vintfPassthru=false
vintfLegacy=false
hidl服務物件獲取方式包括2中:
1. 通過查詢hwservicemanager來獲取;
2.通過PassthroughServiceManager從本程序地址空間中獲取;
那如何選擇獲取方式呢? 其實就是vintfHwbinder、vintfPassthru、vintfLegacy、getStub這4個變數值來決定hidl服務的獲取方式。
1. 當getStub為true時,不管hal屬於什麼傳輸模式,都採用PassthroughServiceManager獲取介面物件;
2.當getStub為false時,則根據hal傳輸模式來選擇介面獲取方式;
《1》 當hal模式為Hwbinder時,則從hwservicemanager中查詢;
《2》當hal傳輸模式為Passthru或Legacy時,則採用PassthroughServiceManager來獲取;
那什麼是Hwbinder,什麼是Passthru及Legacy呢?下圖是google提供的hal的roadmap圖:
- if (getStub || vintfPassthru || vintfLegacy) {
- const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
- if (pm != nullptr) {
- Return<sp<::android::hidl::base::V1_0::IBase>> ret =
- pm->get(IComposer::descriptor, serviceName);
- if (ret.isOk()) {
- sp<::android::hidl::base::V1_0::IBase> baseInterface = ret;
- if (baseInterface != nullptr) {
- iface = IComposer::castFrom(baseInterface);
- if (!getStub || trebleTestingOverride) {
- iface = new BsComposer(iface);
- }
- }
- }
- }
- }
sp<Interface> service = Interface::getService(name, true /* getStub */)所以getStub=true. 這裡通過PassthroughServiceManager來獲取IComposer物件。其實所有的Hal 程序都是通過PassthroughServiceManager來得到hidl服務物件的,而作為Hal程序的Client端Framework程序在獲取hidl服務物件時,需要通過hal的Transport型別來選擇獲取方式。system\libhidl\transport\ServiceManagement.cpp- sp<IServiceManager> getPassthroughServiceManager() {
- static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
- return manager;
- }
這裡只是簡單的建立了一個PassthroughServiceManager物件。PassthroughServiceManager也實現了IServiceManager介面。然後通過PassthroughServiceManager詢服務:- Return<sp<IBase>> get(const hidl_string& fqName,
- const hidl_string& name) override {
- std::string stdFqName(fqName.c_str());
- //fqName looks like [email protected]::IFoo
- size_t idx = stdFqName.find("::");
- if (idx == std::string::npos ||
- idx + strlen("::") + 1 >= stdFqName.size()) {
- LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
- return nullptr;
- }
- std::string packageAndVersion = stdFqName.substr(0, idx);
- std::string ifaceName = stdFqName.substr(idx + strlen("::"));
- const std::string prefix = packageAndVersion + "-impl";
- const std::string sym = "HIDL_FETCH_" + ifaceName;
- const android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
- const int dlMode = RTLD_LAZY;
- void *handle = nullptr;
- // TODO: lookup in VINTF instead
- // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
- dlerror(); // clear
- for (const std::string &path : {
- HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
- }) {
- std::vector<std::string> libs = search(path, prefix, ".so");
- for (const std::string &lib : libs) {
- const std::string fullPath = path + lib;
- // If sphal namespace is available, try to load from the
- // namespace first. If it fails, fall back to the original
- // dlopen, which loads from the current namespace.
- if (sphal_namespace != nullptr && path != HAL_LIBRARY_PATH_SYSTEM) {
- const android_dlextinfo dlextinfo = {
- .flags = ANDROID_DLEXT_USE_NAMESPACE,
- // const_cast is dirty but required because
- // library_namespace field is non-const.
- .library_namespace = const_cast<android_namespace_t*>(sphal_namespace),
- };
- handle = android_dlopen_ext(fullPath.c_str(), dlMode, &dlextinfo);
- if (handle == nullptr) {
- const char* error = dlerror();
- LOG(WARNING) << "Failed to dlopen " << lib << " from sphal namespace:"
- << (error == nullptr ? "unknown error" : error);
- } else {
- LOG(DEBUG) << lib << " loaded from sphal namespace.";
- }
- }
- if (handle == nullptr) {
- handle = dlopen(fullPath.c_str(), dlMode);
- }
- if (handle == nullptr) {
- const char* error = dlerror();
- LOG(ERROR) << "Failed to dlopen " << lib << ": "
- << (error == nullptr ? "unknown error" : error);
- continue;
- }
- IBase* (*generator)(const char* name);
- *(void **)(&generator) = dlsym(handle, sym.c_str());
- if(!generator) {
- const char* error = dlerror();
- LOG(ERROR) << "Passthrough lookup opened " << lib
- << " but could not find symbol " << sym << ": "
- << (error == nullptr ? "unknown error" : error);
- dlclose(handle);
- continue;
- }
- IBase *interface = (*generator)(name.c_str());
- if (interface == nullptr) {
- dlclose(handle);
- continue; // this module doesn't provide this instance name
- }
- registerReference(fqName, name);
- return interface;
- }
- }
- return nullptr;
- }
根據傳入的fqName=([email protected]::IComposer")獲取當前的介面名IComposer,拼接出後面需要查詢的函式名HIDL_FETCH_IComposer和庫名字[email protected],然後查詢"/system/lib64/hw/"、"/vendor/lib64/hw/"、"/odm/lib64/hw/"下是否有對應的so庫。接著通過dlopen載入/vendor/lib/hw/[email protected],然後通過dlsym查詢並呼叫HIDL_FETCH_IComposer函式,最後呼叫registerReference(fqName, name)向hwservicemanager註冊。
hardware/interfaces/graphics/composer/2.1/default/Android.bp
從上面的編譯指令碼可知,[email protected]的原始碼檔案為Hwc.cpp:
- cc_library_shared {
- name: "[email protected]",
- defaults: ["hidl_defaults"],
- proprietary: true,
- relative_install_path: "hw",
- srcs: ["Hwc.cpp"],
- static_libs: ["libhwcomposer-client"],
- shared_libs: [
- "[email protected]",
- "[email protected]",
- "libbase",
- "libcutils",
- "libfmq",
- "libhardware",
- "libhidlbase",
- "libhidltransport",
- "liblog",
- "libsync",
- "libutils",
- "libhwc2on1adapter"
- ],
- }
hardware/interfaces/graphics/composer/2.1/default/Hwc.cpp
- IComposer* HIDL_FETCH_IComposer(const char*)
- {
- const hw_module_t* module = nullptr;
- int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
- if (err) {
- ALOGE("failed to get hwcomposer module");
- return nullptr;
- }
- return new HwcHal(module);
- }
hw_get_module就和AndroidO以前的Hal模式一致,這正是Passthrough複用原有hal的原理。載入hal庫後,得到hw_module_t,然後使用HwcHal來包裹hw_module_t,而HwcHal實現了IComposer介面。registerPassthroughClient
得到IComposer介面物件HwcHal後,需要註冊相關資訊到hwservicemanager中。
system\libhidl\transport\ServiceManagement.cpp
- static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
- sp<IServiceManager> binderizedManager = defaultServiceManager();
- if (binderizedManager == nullptr) {
- LOG(WARNING) << "Could not registerReference for "
- << interfaceName << "/" << instanceName
- << ": null binderized manager.";
- return;
- }
- auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
- if (!ret.isOk()) {
- LOG(WARNING) << "Could not registerReference for "
- << interfaceName << "/" << instanceName
- << ": " << ret.description();
- return;
- }
- LOG(VERBOSE) << "Successfully registerReference for "
- << interfaceName << "/" << instanceName;
- }
這裡通過hwservicemanager的代理物件跨程序呼叫registerPassthroughClient。[email protected]_genc++\gen\android\hidl\manager\1.0\ServiceManagerAll.cpp
- ::android::hardware::Return<void> BpHwServiceManager::registerPassthroughClient(const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name){
- ::android::hardware::Return<void> _hidl_out = ::android::hidl::manager::V1_0::BpHwServiceManager::_hidl_registerPassthroughClient(this, this, fqName, name);
- return _hidl_out;
- }
- ::android::hardware::Return<void> BpHwServiceManager::_hidl_registerPassthroughClient(::android::hardware::IInterface *_hidl_this, ::android::hardware::details::HidlInstrumentor *_hidl_this_instrumentor, const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name) {
- #ifdef __ANDROID_DEBUGGABLE__
- bool mEnableInstrumentation = _hidl_this_instrumentor->isInstrumentationEnabled();
- const auto &mInstrumentationCallbacks = _hidl_this_instrumentor->getInstrumentationCallbacks();
- #else
- (void) _hidl_this_instrumentor;
- #endif // __ANDROID_DEBUGGABLE__
- atrace_begin(ATRACE_TAG_HAL, "HIDL::IServiceManager::registerPassthroughClient::client");
- #ifdef __ANDROID_DEBUGGABLE__
- if (UNLIKELY(mEnableInstrumentation)) {
- std::vector<void *> _hidl_args;
- _hidl_args.push_back((void *)&fqName);
- _hidl_args.push_back((void *)&name);
- for (const auto &callback: mInstrumentationCallbacks) {
- callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hidl.manager", "1.0", "IServiceManager", "registerPassthroughClient", &_hidl_args);
- }
- }
- #endif // __ANDROID_DEBUGGABLE__
- ::android::hardware::Parcel _hidl_data;
- ::android::hardware::Parcel _hidl_reply;
- ::android::status_t _hidl_err;
- ::android::hardware::Status _hidl_status;
- _hidl_err = _hidl_data.writeInterfaceToken(BpHwServiceManager::descriptor);
- if (_hidl_err != ::android::OK) { goto _hidl_error; }
- size_t _hidl_fqName_parent;
- _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;
- _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; }
- _hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact(8 /* registerPassthroughClient */, _hidl_data, &_hidl_reply);
- if (_hidl_err != ::android::OK) { goto _hidl_error; }
- _hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);
- if (_hidl_err != ::android::OK) { goto _hidl_error; }
- if (!_hidl_status.isOk()) { return _hidl_status; }
- atrace_end(ATRACE_TAG_HAL);
- #ifdef __ANDROID_DEBUGGABLE__
- if (UNLIKELY(mEnableInstrumentation)) {
- std::vector<void *> _hidl_args;
- for (const auto &callback: mInstrumentationCallbacks) {
- callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hidl.manager", "1.0", "IServiceManager",