1. 程式人生 > >AndroidO Treble架構下Hal程序啟動及HIDL服務註冊過程--不全

AndroidO Treble架構下Hal程序啟動及HIDL服務註冊過程--不全

通過前面對Treble架構的介紹,我們知道,Android Framework程序和Hal分離,每個Hal獨立執行在自己的程序地址空間,那麼這些Hal程序是如何啟動的呢?本文以composer hal為例展開分析。

在以下路徑有composer hal的rc啟動指令碼:

hardware/interfaces/graphics/composer/2.1/default/[email protected]

  1. service hwcomposer-2-1 /vendor/bin/hw/[email protected]
  2. class hal animation
  3. user system
  4. group graphics drmrpc
  5. capabilities SYS_NICE
  6. 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

  1. int main() {
  2. // the conventional HAL might start binder services
  3. android::ProcessState::initWithDriver("/dev/vndbinder");
  4. android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
  5. android::ProcessState::self()->startThreadPool();
  6. // same as SF main thread
  7. struct sched_param param = {0};
  8. param.sched_priority = 2;
  9. if (sched_setscheduler(0, SCHED_FIFO | SCHED_RESET_ON_FORK,
  10. ¶m) != 0) {
  11. ALOGE("Couldn't set SCHED_FIFO: %d", errno);
  12. }
  13. return defaultPassthroughServiceImplementation<IComposer>(4);
  14. }
前面我們分析了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

  1. template<class Interface>
  2. __attribute__((warn_unused_result))
  3. status_t defaultPassthroughServiceImplementation(std::string name,
  4. size_t maxThreads = 1) {
  5. configureRpcThreadpool(maxThreads, true); //配置binder執行緒個數
  6. status_t result = registerPassthroughServiceImplementation<Interface>(name);
  7. if (result != OK) {
  8. return result;
  9. }
  10. joinRpcThreadpool();
  11. return 0;
  12. }
  1. template<class Interface>
  2. __attribute__((warn_unused_result))
  3. status_t registerPassthroughServiceImplementation(
  4. std::string name = "default") {
  5. sp<Interface> service = Interface::getService(name, true /* getStub */); //從當前程序空間中拿到IComposer介面類物件
  6. if (service == nullptr) {
  7. ALOGE("Could not get passthrough implementation for %s/%s.",
  8. Interface::descriptor, name.c_str());
  9. return EXIT_FAILURE;
  10. }
  11. LOG_FATAL_IF(service->isRemote(), "Implementation of %s/%s is remote!",
  12. Interface::descriptor, name.c_str());
  13. status_t status = service->registerAsService(name);//將IComposer註冊到hwservicemanager中
  14. if (status == OK) {
  15. ALOGI("Registration complete for %s/%s.",
  16. Interface::descriptor, name.c_str());
  17. } else {
  18. ALOGE("Could not register service %s/%s (%d).",
  19. Interface::descriptor, name.c_str(), status);
  20. }
  21. return status;
  22. }

Hal程序獲取IComposer類物件

在composer hal程序啟動時,首先呼叫IComposer 的getService(“default”,true)來獲取IComposer的類物件。

composer\2.1\[email protected]_genc++\gen\android\hardware\graphics\composer\2.1\ComposerAll.cpp

  1. ::android::sp<IComposer> IComposer::getService(const std::string &serviceName, const bool getStub) {
  2. using ::android::hardware::defaultServiceManager;
  3. using ::android::hardware::details::waitForHwService;
  4. using ::android::hardware::getPassthroughServiceManager;
  5. using ::android::hardware::Return;
  6. using ::android::sp;
  7. using Transport = ::android::hidl::manager::V1_0::IServiceManager::Transport;
  8. sp<IComposer> iface = nullptr;
  9. const sp<::android::hidl::manager::V1_0::IServiceManager> sm = defaultServiceManager(); //獲取hwservicemanager的代理
  10. if (sm == nullptr) {
  11. ALOGE("getService: defaultServiceManager() is null");
  12. return nullptr;
  13. }
  14. Return<Transport> transportRet = sm->getTransport(IComposer::descriptor, serviceName);//查詢IComposer的Transport
  15. if (!transportRet.isOk()) {
  16. ALOGE("getService: defaultServiceManager()->getTransport returns %s", transportRet.description().c_str());
  17. return nullptr;
  18. }
  19. Transport transport = transportRet;
  20. const bool vintfHwbinder = (transport == Transport::HWBINDER);
  21. const bool vintfPassthru = (transport == Transport::PASSTHROUGH); //Transport型別判斷
  22. #ifdef __ANDROID_TREBLE__
  23. #ifdef __ANDROID_DEBUGGABLE__
  24. const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
  25. const bool trebleTestingOverride = env && !strcmp(env, "true");
  26. const bool vintfLegacy = (transport == Transport::EMPTY) && trebleTestingOverride;
  27. #else // __ANDROID_TREBLE__ but not __ANDROID_DEBUGGABLE__
  28. const bool trebleTestingOverride = false;
  29. const bool vintfLegacy = false;
  30. #endif // __ANDROID_DEBUGGABLE__
  31. #else // not __ANDROID_TREBLE__
  32. const char* env = std::getenv("TREBLE_TESTING_OVERRIDE");
  33. const bool trebleTestingOverride = env && !strcmp(env, "true");
  34. const bool vintfLegacy = (transport == Transport::EMPTY);
  35. #endif // __ANDROID_TREBLE__
  36.     //hwbinder方式下獲取IComposer物件
  37. for (int tries = 0; !getStub && (vintfHwbinder || (vintfLegacy && tries == 0)); tries++) {
  38. if (tries > 1) {
  39. ALOGI("getService: Will do try %d for %s/%s in 1s...", tries, IComposer::descriptor, serviceName.c_str());
  40. sleep(1);
  41. }
  42. if (vintfHwbinder && tries > 0) {
  43. waitForHwService(IComposer::descriptor, serviceName);
  44. }
  45. Return<sp<::android::hidl::base::V1_0::IBase>> ret =
  46. sm->get(IComposer::descriptor, serviceName);
  47. if (!ret.isOk()) {
  48. ALOGE("IComposer: defaultServiceManager()->get returns %s", ret.description().c_str());
  49. break;
  50. }
  51. sp<::android::hidl::base::V1_0::IBase> base = ret;
  52. if (base == nullptr) {
  53. if (tries > 0) {
  54. ALOGW("IComposer: found null hwbinder interface");
  55. }continue;
  56. }
  57. Return<sp<IComposer>> castRet = IComposer::castFrom(base, true /* emitError */);
  58. if (!castRet.isOk()) {
  59. if (castRet.isDeadObject()) {
  60. ALOGW("IComposer: found dead hwbinder service");
  61. continue;
  62. } else {
  63. ALOGW("IComposer: cannot call into hwbinder service: %s; No permission? Check for selinux denials.", castRet.description().c_str());
  64. break;
  65. }
  66. }
  67. iface = castRet;
  68. if (iface == nullptr) {
  69. ALOGW("IComposer: received incompatible service; bug in hwservicemanager?");
  70. break;
  71. }
  72. return iface;
  73. }
  74. //passthrough方式下獲取IComposer物件
  75.     if (getStub || vintfPassthru || vintfLegacy) {
  76.         const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
  77.         if (pm != nullptr) {
  78.             Return<sp<::android::hidl::base::V1_0::IBase>> ret =
  79.                     pm->get(IComposer::descriptor, serviceName);
  80.             if (ret.isOk()) {
  81.                 sp<::android::hidl::base::V1_0::IBase> baseInterface = ret;
  82.                 if (baseInterface != nullptr) {
  83.                     iface = IComposer::castFrom(baseInterface);
  84.                     if (!getStub || trebleTestingOverride) {
  85.                         iface = new BsComposer(iface);
  86.                     }
  87.                 }
  88.             }
  89.         }
  90.     }
  91.     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圖:


  1. if (getStub || vintfPassthru || vintfLegacy) {
  2. const sp<::android::hidl::manager::V1_0::IServiceManager> pm = getPassthroughServiceManager();
  3. if (pm != nullptr) {
  4. Return<sp<::android::hidl::base::V1_0::IBase>> ret =
  5. pm->get(IComposer::descriptor, serviceName);
  6. if (ret.isOk()) {
  7. sp<::android::hidl::base::V1_0::IBase> baseInterface = ret;
  8. if (baseInterface != nullptr) {
  9. iface = IComposer::castFrom(baseInterface);
  10. if (!getStub || trebleTestingOverride) {
  11. iface = new BsComposer(iface);
  12. }
  13. }
  14. }
  15. }
  16. }
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
  1. sp<IServiceManager> getPassthroughServiceManager() {
  2. static sp<PassthroughServiceManager> manager(new PassthroughServiceManager());
  3. return manager;
  4. }
這裡只是簡單的建立了一個PassthroughServiceManager物件。PassthroughServiceManager也實現了IServiceManager介面。然後通過PassthroughServiceManager詢服務:
  1. Return<sp<IBase>> get(const hidl_string& fqName,
  2. const hidl_string& name) override {
  3. std::string stdFqName(fqName.c_str());
  4. //fqName looks like [email protected]::IFoo
  5. size_t idx = stdFqName.find("::");
  6. if (idx == std::string::npos ||
  7. idx + strlen("::") + 1 >= stdFqName.size()) {
  8. LOG(ERROR) << "Invalid interface name passthrough lookup: " << fqName;
  9. return nullptr;
  10. }
  11. std::string packageAndVersion = stdFqName.substr(0, idx);
  12. std::string ifaceName = stdFqName.substr(idx + strlen("::"));
  13. const std::string prefix = packageAndVersion + "-impl";
  14. const std::string sym = "HIDL_FETCH_" + ifaceName;
  15. const android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
  16. const int dlMode = RTLD_LAZY;
  17. void *handle = nullptr;
  18. // TODO: lookup in VINTF instead
  19. // TODO(b/34135607): Remove HAL_LIBRARY_PATH_SYSTEM
  20. dlerror(); // clear
  21. for (const std::string &path : {
  22. HAL_LIBRARY_PATH_ODM, HAL_LIBRARY_PATH_VENDOR, HAL_LIBRARY_PATH_SYSTEM
  23. }) {
  24. std::vector<std::string> libs = search(path, prefix, ".so");
  25. for (const std::string &lib : libs) {
  26. const std::string fullPath = path + lib;
  27. // If sphal namespace is available, try to load from the
  28. // namespace first. If it fails, fall back to the original
  29. // dlopen, which loads from the current namespace.
  30. if (sphal_namespace != nullptr && path != HAL_LIBRARY_PATH_SYSTEM) {
  31. const android_dlextinfo dlextinfo = {
  32. .flags = ANDROID_DLEXT_USE_NAMESPACE,
  33. // const_cast is dirty but required because
  34. // library_namespace field is non-const.
  35. .library_namespace = const_cast<android_namespace_t*>(sphal_namespace),
  36. };
  37. handle = android_dlopen_ext(fullPath.c_str(), dlMode, &dlextinfo);
  38. if (handle == nullptr) {
  39. const char* error = dlerror();
  40. LOG(WARNING) << "Failed to dlopen " << lib << " from sphal namespace:"
  41. << (error == nullptr ? "unknown error" : error);
  42. } else {
  43. LOG(DEBUG) << lib << " loaded from sphal namespace.";
  44. }
  45. }
  46. if (handle == nullptr) {
  47. handle = dlopen(fullPath.c_str(), dlMode);
  48. }
  49. if (handle == nullptr) {
  50. const char* error = dlerror();
  51. LOG(ERROR) << "Failed to dlopen " << lib << ": "
  52. << (error == nullptr ? "unknown error" : error);
  53. continue;
  54. }
  55. IBase* (*generator)(const char* name);
  56. *(void **)(&generator) = dlsym(handle, sym.c_str());
  57. if(!generator) {
  58. const char* error = dlerror();
  59. LOG(ERROR) << "Passthrough lookup opened " << lib
  60. << " but could not find symbol " << sym << ": "
  61. << (error == nullptr ? "unknown error" : error);
  62. dlclose(handle);
  63. continue;
  64. }
  65. IBase *interface = (*generator)(name.c_str());
  66. if (interface == nullptr) {
  67. dlclose(handle);
  68. continue; // this module doesn't provide this instance name
  69. }
  70. registerReference(fqName, name);
  71. return interface;
  72. }
  73. }
  74. return nullptr;
  75. }

根據傳入的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

  1. cc_library_shared {
  2. name: "[email protected]",
  3. defaults: ["hidl_defaults"],
  4. proprietary: true,
  5. relative_install_path: "hw",
  6. srcs: ["Hwc.cpp"],
  7. static_libs: ["libhwcomposer-client"],
  8. shared_libs: [
  9. "[email protected]",
  10. "[email protected]",
  11. "libbase",
  12. "libcutils",
  13. "libfmq",
  14. "libhardware",
  15. "libhidlbase",
  16. "libhidltransport",
  17. "liblog",
  18. "libsync",
  19. "libutils",
  20. "libhwc2on1adapter"
  21. ],
  22. }
從上面的編譯指令碼可知,[email protected]的原始碼檔案為Hwc.cpp:
hardware/interfaces/graphics/composer/2.1/default/Hwc.cpp
  1. IComposer* HIDL_FETCH_IComposer(const char*)
  2. {
  3. const hw_module_t* module = nullptr;
  4. int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
  5. if (err) {
  6. ALOGE("failed to get hwcomposer module");
  7. return nullptr;
  8. }
  9. return new HwcHal(module);
  10. }
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

  1. static void registerReference(const hidl_string &interfaceName, const hidl_string &instanceName) {
  2. sp<IServiceManager> binderizedManager = defaultServiceManager();
  3. if (binderizedManager == nullptr) {
  4. LOG(WARNING) << "Could not registerReference for "
  5. << interfaceName << "/" << instanceName
  6. << ": null binderized manager.";
  7. return;
  8. }
  9. auto ret = binderizedManager->registerPassthroughClient(interfaceName, instanceName);
  10. if (!ret.isOk()) {
  11. LOG(WARNING) << "Could not registerReference for "
  12. << interfaceName << "/" << instanceName
  13. << ": " << ret.description();
  14. return;
  15. }
  16. LOG(VERBOSE) << "Successfully registerReference for "
  17. << interfaceName << "/" << instanceName;
  18. }
這裡通過hwservicemanager的代理物件跨程序呼叫registerPassthroughClient。

[email protected]_genc++\gen\android\hidl\manager\1.0\ServiceManagerAll.cpp

  1. ::android::hardware::Return<void> BpHwServiceManager::registerPassthroughClient(const ::android::hardware::hidl_string& fqName, const ::android::hardware::hidl_string& name){
  2. ::android::hardware::Return<void> _hidl_out = ::android::hidl::manager::V1_0::BpHwServiceManager::_hidl_registerPassthroughClient(this, this, fqName, name);
  3. return _hidl_out;
  4. }
  1. ::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) {
  2. #ifdef __ANDROID_DEBUGGABLE__
  3. bool mEnableInstrumentation = _hidl_this_instrumentor->isInstrumentationEnabled();
  4. const auto &mInstrumentationCallbacks = _hidl_this_instrumentor->getInstrumentationCallbacks();
  5. #else
  6. (void) _hidl_this_instrumentor;
  7. #endif // __ANDROID_DEBUGGABLE__
  8. atrace_begin(ATRACE_TAG_HAL, "HIDL::IServiceManager::registerPassthroughClient::client");
  9. #ifdef __ANDROID_DEBUGGABLE__
  10. if (UNLIKELY(mEnableInstrumentation)) {
  11. std::vector<void *> _hidl_args;
  12. _hidl_args.push_back((void *)&fqName);
  13. _hidl_args.push_back((void *)&name);
  14. for (const auto &callback: mInstrumentationCallbacks) {
  15. callback(InstrumentationEvent::CLIENT_API_ENTRY, "android.hidl.manager", "1.0", "IServiceManager", "registerPassthroughClient", &_hidl_args);
  16. }
  17. }
  18. #endif // __ANDROID_DEBUGGABLE__
  19. ::android::hardware::Parcel _hidl_data;
  20. ::android::hardware::Parcel _hidl_reply;
  21. ::android::status_t _hidl_err;
  22. ::android::hardware::Status _hidl_status;
  23. _hidl_err = _hidl_data.writeInterfaceToken(BpHwServiceManager::descriptor);
  24. if (_hidl_err != ::android::OK) { goto _hidl_error; }
  25. size_t _hidl_fqName_parent;
  26. _hidl_err = _hidl_data.writeBuffer(&fqName, sizeof(fqName), &_hidl_fqName_parent);
  27. if (_hidl_err != ::android::OK) { goto _hidl_error; }
  28. _hidl_err = ::android::hardware::writeEmbeddedToParcel(
  29. fqName,
  30. &_hidl_data,
  31. _hidl_fqName_parent,
  32. 0 /* parentOffset */);
  33. if (_hidl_err != ::android::OK) { goto _hidl_error; }
  34. size_t _hidl_name_parent;
  35. _hidl_err = _hidl_data.writeBuffer(&name, sizeof(name), &_hidl_name_parent);
  36. if (_hidl_err != ::android::OK) { goto _hidl_error; }
  37. _hidl_err = ::android::hardware::writeEmbeddedToParcel(
  38. name,
  39. &_hidl_data,
  40. _hidl_name_parent,
  41. 0 /* parentOffset */);
  42. if (_hidl_err != ::android::OK) { goto _hidl_error; }
  43. _hidl_err = ::android::hardware::IInterface::asBinder(_hidl_this)->transact(8 /* registerPassthroughClient */, _hidl_data, &_hidl_reply);
  44. if (_hidl_err != ::android::OK) { goto _hidl_error; }
  45. _hidl_err = ::android::hardware::readFromParcel(&_hidl_status, _hidl_reply);
  46. if (_hidl_err != ::android::OK) { goto _hidl_error; }
  47. if (!_hidl_status.isOk()) { return _hidl_status; }
  48. atrace_end(ATRACE_TAG_HAL);
  49. #ifdef __ANDROID_DEBUGGABLE__
  50. if (UNLIKELY(mEnableInstrumentation)) {
  51. std::vector<void *> _hidl_args;
  52. for (const auto &callback: mInstrumentationCallbacks) {
  53. callback(InstrumentationEvent::CLIENT_API_EXIT, "android.hidl.manager", "1.0", "IServiceManager",