一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Android 12 系統(tǒng)源碼分析 | Native Binder 代碼變遷

 開花結(jié)果 2022-06-14 發(fā)布于北京
作者:秋城
注:廣義上 Native Binder 可理解為包含 vnd,hw,rpc 等內(nèi)容,本文所討論的Native Binder 指的僅是 servicemanager 服務(wù)程序及 libbinder 中相關(guān)代碼,不做廣義的延伸

一、前言

Servicemanager 程序(以下簡稱SM)是 Android 系統(tǒng) binder 模塊重要的組成部分,扮演著類似 C/S 架構(gòu)中的 DNS 服務(wù)器的角色,提供服務(wù)增查和權(quán)限管理等功能支撐

在 Android 11 之前的版本里,SM 是面向 binder 驅(qū)動編程,直接使用 open、mmap、ioctl 等 api 與 binder 驅(qū)動交互。而從 Android 11 開始,SM 放棄使用這些較底層的接口,轉(zhuǎn)向 libbinder 庫和 AIDL。標(biāo)志性的提交如下,該提交奠定了新的 SM 架構(gòu)基礎(chǔ),此后多次提交對此進(jìn)行完善填充

frameworks/native
servicemanager: use libbinder

Bug: 135768100Test: boot
Test: servicemanager_test
Change-Id: I9d657b6c0d0be0f763b6d54e0e6c6bc1c1e3fc7a
(cherry picked from commit 3e092daa14c63831d76d3ad6e56b2919a0523536)

本文代碼基于 Android 12,以 SM 為主視角,從架構(gòu)和情景流程上帶大家認(rèn)識新的 Native Binder

二. 軟件架構(gòu)

2.1 架構(gòu)概述

圖1:切換到 aidl 和 libbinder 后的 ServiceManager 類關(guān)系圖

圖注:
為了畫圖方便,將 namespace 寫成了下劃線形式。
android_os_BpServiceManager 和 android_os_BnServiceManager、android_os_IServiceManager 類均在 android os 的 namespace 中,其他無下劃線的類名,處于 android namespace 中。

一圖勝千言,11 之前的 SM 是寫在 c 文件里,沒有類的概念,現(xiàn)在基于 aidl 和 libbinder,使用 cpp 語言,用 uml 就可以很形象地展示類關(guān)系了。就著這幅圖我們大致描述新的軟件架構(gòu)

  • 紅色線段大概地將服務(wù)端與客戶端類相分隔,服務(wù)端在右下角

一些 libbinder 的用于繼承的公共類請讀者自行剝離,而不是將其歸入某一端。例如 IBinder,我們知道他是 BBinder 和 BpBinder 的父類,是公共的接口約束

  • libbinder 中客戶端的入口變?yōu)椋篒ServiceManager.cpp#ServiceManagerShim

之前無該輔助類,而是直接操作 BpServiceManager,這個輔助類封裝了 aidl 自動生成的 BpServiceManager,所以現(xiàn)在的客戶端代碼流就變成如下三步:

1.用戶代碼
2.libbinder代碼 binder/IServiceManager.cpp#ServiceManagerShim
3.aidl代碼      android/os/IServiceManager.cpp#BpServiceManager接口

所以 libbinder 中的 ServiceManagerShim 起到了一個中轉(zhuǎn)的作用,把請求轉(zhuǎn)給 out 下 aidl 自動生成的 BpServiceManager

  • BpServiceManager 的實現(xiàn)挪到 out

原來是在 libbinder#IServiceManager.cpp 中手寫實現(xiàn),現(xiàn)在是 aidl 幫你實現(xiàn)。

當(dāng)然,該文件中同樣自動實現(xiàn)了 BnServiceManager 類

代碼路徑

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm64_armv8-a_shared/gen/aidl/android/os/IServiceManager.cpp
  • 服務(wù)端的核心實現(xiàn)在 ServiceManager.cpp

原來是沒有 Bn 的,而是一個 binder_loop 方法溝通驅(qū)動,現(xiàn)在則是ServiceManager 繼承了 BnServiceManager 來獲得代碼流。

  • waitForService 的改動:IServiceCallback.aidl

Waiter 類。新增了 binder 匿名服務(wù)用來向 sm 注冊跨進(jìn)程的回調(diào),當(dāng) sm 檢測到有服務(wù)注冊時,會返回通知

  • 服務(wù)的客戶端數(shù)量監(jiān)聽:IServiceCallback.aidl

IServiceCallback.aidl 這個匿名 binder 服務(wù)就是用于該目的,可以監(jiān)聽某個服務(wù)的客戶端數(shù)量

2.2、文件路徑

  • AIDL

AIDL 是一種方便的接口定義語言,用于 Binder-IPC 編程。詳細(xì)介紹與使用可參考:AIDL Overview

我們關(guān)注三個 aidl,分別是 IServiceManager.aidl、IServiceCallback.aidl、IClientCallback.aidl,對應(yīng)的編譯后生成的文件路徑為:

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/
IClientCallback.cpp
IServiceCallback.cpp
IServiceManager.cpp
  • libbinder 中的代碼路徑

frameworks/native/libs/binder/IServiceManager.cpp
  • SM 服務(wù)端代碼路徑

frameworks/native/cmds/servicemanager/
main.cpp
Access.cpp
ServiceManager.cpp

本小節(jié)僅展示涉及變遷的文件路徑。簡潔起見只寫了 cpp 文件,對應(yīng)的 h 頭文件可以附近查找。

另外需要特別區(qū)分的是,有兩個 IServiceManager。

一個在 libbinder 中,是 Android 的 name space,直接被用戶#include<binder/IServiceManager>使用。

另一個是 aidl 自動生成的 Android os 的 name space,被上面的 libbinder 所使#include<android/os/IServiceManager>。

2.3、小結(jié)

第二章節(jié)從全局的角度展示了 SM 切換到 aidl 和 libbinder的軟件架構(gòu),結(jié)合圖來看還是非常清楚易于理解的

接下來跟蹤幾個情景流程,展示新架構(gòu)中的細(xì)節(jié)

三 servicemanager 啟動流程分析

圖2:servicemanager 啟動時序圖

如上圖,啟動流程的變動主要在進(jìn)入循環(huán)的方式,Android 11 之前是通過binder_loop方法,而現(xiàn)在是通過 looper。下面展示細(xì)節(jié)

frameworks/native/cmds/servicemanager/main.cpp
int main(int argc, char** argv) {
   if (argc > 2) {
       LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
  }

   const char* driver = argc == 2 ? argv[1] : "/dev/binder";//溝通binder驅(qū)動,open,mmap   sp<ProcessState> ps = ProcessState::initWithDriver(driver);
   ps->setThreadPoolMaxThreadCount(0);
   //oneway限制,sm發(fā)起的binder調(diào)用必須是單向,否則打印堆棧日志提示   ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
   //實例化ServiceManager,傳入Access類用于鑒權(quán)   sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
   if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
       LOG(ERROR) << "Could not self register servicemanager";
  }
   //設(shè)置全局變量給IPCThreadState   IPCThreadState::self()->setTheContextObject(manager);
   //注冊到驅(qū)動,成為binder管理員,handle是0   ps->becomeContextManager();
   //準(zhǔn)備looper   sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
   //通知驅(qū)動BC_ENTER_LOOPER,監(jiān)聽驅(qū)動fd,有消息時回調(diào)到handleEvent處理binder調(diào)用   BinderCallback::setupTo(looper);
   //服務(wù)的注冊監(jiān)聽相關(guān)   ClientCallbackCallback::setupTo(looper, manager);
   //無限循環(huán)等消息   while(true) {
       looper->pollAll(-1);
  }

   // should not be reached   return EXIT_FAILURE;}

和原來的 servicemanager 服務(wù)相比較,使用了 libbinder 后,代碼更規(guī)范化,和其他 native 的服務(wù)風(fēng)格一致了。

  • 之前是直接 open、mmap 現(xiàn)在是借助 libbinder

  • 之前是 binder_loop死 循環(huán)接收驅(qū)動的消息,現(xiàn)在是通過 looper 監(jiān)聽 fd 來handleEvent

  • 之前的鑒權(quán)現(xiàn)在被獨(dú)立到單獨(dú)文件 Access.cpp

突然想起一個題目,servicemanager 映射的虛擬內(nèi)存有多大?現(xiàn)在的答案是和普通應(yīng)用一樣大:1M-2 頁。

frameworks/native/libs/binder/ProcessState.cpp
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

啟動流程比較清晰不多贅述,下一小節(jié)看 addService 的流程。

四、addService 流程分析

圖3:defaultServiceManager流程

圖4:addService 客戶端流程

圖5:addService 服務(wù)端流程

先上圖,總覽 native 的代碼流程,客戶端是 libbinder 里的 IServiceManager.cpp,服務(wù)端是我們的 ServiceManager.cpp

4.1 ServiceManagerShim::addService

frameworks/native/libs/binder/IServiceManager.cpp
status_t ServiceManagerShim::(const String16& name, const sp<IBinder>& service,
                                       bool allowIsolated, int dumpsysPriority){
   Status status = mTheRealServiceManager->addService(
       String8(name).c_str(), service, allowIsolated, dumpsysPriority);
   return status.exceptionCode();}

直接使用的 mTheRealServiceManager,澄清疑問,mTheRealServiceManager 是誰?

4.1.1 mTheRealServiceManager 是誰?

frameworks/native/libs/binder/IServiceManager.cpp
#include <android/os/IServiceManager.h>using AidlServiceManager = android::os::IServiceManager;class ServiceManagerShim : public IServiceManager{protected:
   sp<AidlServiceManager> mTheRealServiceManager;......ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl): mTheRealServiceManager(impl){}

可以看到,mTheRealServiceManager 就是一個 android::os::IServiceManager 類型的實例,并且在 ServiceManagerShim 實例化時賦值。

那么 ServiceManagerShim 何時實例化呢?答案是 defaultServiceManager() 中

frameworks/native/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager(){
   std::call_once(gSmOnce, []() {
       sp<AidlServiceManager> sm = nullptr;
       while (sm == nullptr) {
           //1、拿到AidlServiceManager類型的BpServiceManager(new BpBinder(0))實例           sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
           if (sm == nullptr) {
               ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
               sleep(1);
          }
      }
       //2、new ServiceManagerShim       gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
  });

   return gDefaultServiceManager;}

如注釋1、2,mTheRealServiceManager 就是在這樣流程中賦值的。他的真是面目是BpServiceManager(new BpBinder(0))。

由圖1可知,我們拿到了操作 binder 驅(qū)動的入口,BpServiceManager-->BpBinder-->IPCThreadState-->ioctl

關(guān)于一部分舊知識會貼拓展鏈接本文不做展開。interface_cast 的實現(xiàn)可參考:淺談 Android 系統(tǒng)進(jìn)程間通信(IPC)機(jī)制Binder 中的 Server 和 Client 獲得 Service Manager 接口之路

好現(xiàn)在返回上節(jié),直接走入 BpServiceManager#addService 方法

4.2 BpServiceManager::addService

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/IServiceManager.cpp
namespace android {namespace os {BpServiceManager::BpServiceManager(const ::android::sp<::android::IBinder>& _aidl_impl)
  : BpInterface<IServiceManager>(_aidl_impl){//_aidl_impl就是BpBinder(0)實例}--------------------------------------------------
  ::android::binder::Status BpServiceManager::addService(const ::std::string& name, const ::android::sp<::android::IBinder>& service, bool allowIsolated, int32_t dumpPriority) {::android::Parcel _aidl_data;
 _aidl_data.markForBinder(remoteStrong());//0、和rpc binder有關(guān)::android::Parcel _aidl_reply;::android::status_t _aidl_ret_status = ::android::OK;::android::binder::Status _aidl_status;
 //1、寫interface _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
 if (((_aidl_ret_status) != (::android::OK))) {
   goto _aidl_error;}
 //2、寫name _aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name);
 if (((_aidl_ret_status) != (::android::OK))) {
   goto _aidl_error;}
 //3、寫binder對象 _aidl_ret_status = _aidl_data.writeStrongBinder(service);
 if (((_aidl_ret_status) != (::android::OK))) {
   goto _aidl_error;}
 //4、寫allowIsolated _aidl_ret_status = _aidl_data.writeBool(allowIsolated);
 if (((_aidl_ret_status) != (::android::OK))) {
   goto _aidl_error;}
 //5、寫dumpPriority _aidl_ret_status = _aidl_data.writeInt32(dumpPriority);
 if (((_aidl_ret_status) != (::android::OK))) {
   goto _aidl_error;}
 //6、借助BpBinder(0)-transact來發(fā)起binder通信 _aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_addService, _aidl_data, &_aidl_reply, 0);
 if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IServiceManager::getDefaultImpl())) {
    return IServiceManager::getDefaultImpl()->addService(name, service, allowIsolated, dumpPriority);}
 if (((_aidl_ret_status) != (::android::OK))) {
   goto _aidl_error;}
 //7、如果有返回值就從這個parcel包里讀 _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
 if (((_aidl_ret_status) != (::android::OK))) {
   goto _aidl_error;}
 if (!_aidl_status.isOk()) {
   return _aidl_status;}
 _aidl_error:
 _aidl_status.setFromStatusT(_aidl_ret_status);
 return _aidl_status;}

把 Android 10 的貼上來,我們對比看看

frameworks/native/libs/binder/IServiceManager.cpp
virtual status_t addService(const String16& name, const sp<IBinder>& service,
                               bool allowIsolated, int dumpsysPriority) {
       Parcel data, reply;
       data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
       data.writeString16(name);
       data.writeStrongBinder(service);
       data.writeInt32(allowIsolated ? 1 : 0);
       data.writeInt32(dumpsysPriority);
       status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
       return err == NO_ERROR ? reply.readExceptionCode() : err;
  }

和11之前手寫的 BpServiceManager 相比,本質(zhì)是沒變的,就是多了些花里胡哨的規(guī)范性代碼。

到這里,客戶端的代碼就大致展示完了,transact 再往后就是舊有的流程,可參考:淺談 Android 系統(tǒng)進(jìn)程間通信(IPC)機(jī)制 Binder 中的 Server 和 Client 獲得Service Manager 接口之路

之后走到 binder 驅(qū)動,驅(qū)動又根據(jù) handle == 0 找到對端,我們的 servicemanager 進(jìn)程,喚醒他開始處理請求。

4.3 BinderCallback::handleEvent

如圖4:addService 服務(wù)端流程,現(xiàn)在開始服務(wù)端的流程展示

frameworks/native/cmds/servicemanager/main.cpp
class BinderCallback : public LooperCallback {public:......
       int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
       IPCThreadState::self()->handlePolledCommands();
       return 1;  // Continue receiving callbacks.  }};

之后走到 BR_TRANSACTION

frameworks/native/libs/binder/IPCThreadState.cpp
status_t IPCThreadState::executeCommand(int32_t cmd){switch ((uint32_t)cmd) {case BR_TRANSACTION:
      {
      if (tr.target.ptr) {
      //因為目的端sm所以是tr.target.ptr是0      }else {//開始業(yè)務(wù)分發(fā)          error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
      }

the_context_object 是 SM 啟動的時候設(shè)置好的

sp<BBinder> the_context_object;void IPCThreadState::setTheContextObject(const sp<BBinder>& obj){
   the_context_object = obj;}

是 ServiceManager 類實例,所以也是一個 BBinder 對象,所以就有了 transact()-->onTransact() 的處理能力。

所以現(xiàn)在the_context_object->transact()調(diào)用就走到 BBinder 的 transact 又走到BnServiceManager的onTransact()方法,回到了這個aidl自動生成的IServiceManager.cpp文件里

兜兜轉(zhuǎn)轉(zhuǎn)還是在這個文件

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/IServiceManager.cpp
::android::status_t BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {::android::status_t _aidl_ret_status = ::android::OK;
 switch (_aidl_code) {
 case BnServiceManager::TRANSACTION_addService:{
  ::std::string in_name;
  ::android::sp<::android::IBinder> in_service;
   bool in_allowIsolated;
   int32_t in_dumpPriority;
   //檢查interface   if (!(_aidl_data.checkInterface(this))) {
     _aidl_ret_status = ::android::BAD_TYPE;
     break;
  }
   //讀name   _aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);
   if (((_aidl_ret_status) != (::android::OK))) {
     break;
  }
   //讀binder   _aidl_ret_status = _aidl_data.readStrongBinder(&in_service);
   if (((_aidl_ret_status) != (::android::OK))) {
     break;
  }
   //讀in_allowIsolated   _aidl_ret_status = _aidl_data.readBool(&in_allowIsolated);
   if (((_aidl_ret_status) != (::android::OK))) {
     break;
  }
   //讀in_dumpPriority   _aidl_ret_status = _aidl_data.readInt32(&in_dumpPriority);
   if (((_aidl_ret_status) != (::android::OK))) {
     break;
  }
   //調(diào)用真正的ServiceManager.cpp中的實現(xiàn)  ::android::binder::Status _aidl_status(addService(in_name, in_service, in_allowIsolated, in_dumpPriority));
   //如果有返回寫返回到_aidl_reply   _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
   if (((_aidl_ret_status) != (::android::OK))) {
     break;
  }
   if (!_aidl_status.isOk()) {
     break;
  }}

和Bp端是對稱的操作,下一步走到 ServiceManager.cpp::addService 方法

4.4 ServiceManager::addService

frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
   auto ctx = mAccess->getCallingContext();

   // uid鑒權(quán)   if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
       return Status::fromExceptionCode(Status::EX_SECURITY);
  }
   //selinux鑒權(quán)   if (!mAccess->canAdd(ctx, name)) {
       return Status::fromExceptionCode(Status::EX_SECURITY);
  }

   if (binder == nullptr) {
       return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
  }
   //檢查name命名   if (!isValidServiceName(name)) {
       LOG(ERROR) << "Invalid service name: " << name;
       return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
  }
   //如果vndservicemanager則檢查VINTF manifest#ifndef VENDORSERVICEMANAGER
   if (!meetsDeclarationRequirements(binder, name)) {
       // already logged       return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
  }#endif  // !VENDORSERVICEMANAGER   //和rpc有關(guān),死亡監(jiān)聽   // implicitly unlinked when the binder is removed   if (binder->remoteBinder() != nullptr &&
       binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
       LOG(ERROR) << "Could not linkToDeath when adding " << name;
       return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
  }
   //新增一個結(jié)構(gòu)體到map中   // Overwrite the old service if it exists   mNameToService[name] = Service {
      .binder = binder,
      .allowIsolated = allowIsolated,
      .dumpPriority = dumpPriority,
      .debugPid = ctx.debugPid,
  };
   //架構(gòu)中提到的waiteForService的跨進(jìn)程   auto it = mNameToRegistrationCallback.find(name);
   if (it != mNameToRegistrationCallback.end()) {
       for (const sp<IServiceCallback>& cb : it->second) {
           mNameToService[name].guaranteeClient = true;
           // permission checked in registerForNotifications           cb->onRegistration(name, binder);
      }
  }

   return Status::ok();}

五、其他值得關(guān)注的細(xì)節(jié)

前兩節(jié)是全局總覽、經(jīng)典情景的視角看代碼,現(xiàn)在我們換一個視角,展示一些邊邊角角的內(nèi)容為上面的主干填充細(xì)節(jié)。

5.1 Servicemanager 的能力變化

Android 11 之前僅有 4 種接口暴露給應(yīng)用

frameworks/native/libs/binder/include/binder/IServiceManager.h
enum {
      GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
      CHECK_SERVICE_TRANSACTION,
      ADD_SERVICE_TRANSACTION,
      LIST_SERVICES_TRANSACTION,
  };

而 Android 11 增加到9個,Android 12 又增加到 13 個

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/BnServiceManager.h
class BnServiceManager : public ::android::BnInterface<IServiceManager> {public:
 static constexpr uint32_t TRANSACTION_getService = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
 static constexpr uint32_t TRANSACTION_checkService = ::android::IBinder::FIRST_CALL_TRANSACTION + 1;
 static constexpr uint32_t TRANSACTION_addService = ::android::IBinder::FIRST_CALL_TRANSACTION + 2;
 static constexpr uint32_t TRANSACTION_listServices = ::android::IBinder::FIRST_CALL_TRANSACTION + 3;
 static constexpr uint32_t TRANSACTION_registerForNotifications = ::android::IBinder::FIRST_CALL_TRANSACTION + 4;
 static constexpr uint32_t TRANSACTION_unregisterForNotifications = ::android::IBinder::FIRST_CALL_TRANSACTION + 5;
 static constexpr uint32_t TRANSACTION_isDeclared = ::android::IBinder::FIRST_CALL_TRANSACTION + 6;
 static constexpr uint32_t TRANSACTION_getDeclaredInstances = ::android::IBinder::FIRST_CALL_TRANSACTION + 7;
 static constexpr uint32_t TRANSACTION_updatableViaApex = ::android::IBinder::FIRST_CALL_TRANSACTION + 8;
 static constexpr uint32_t TRANSACTION_getConnectionInfo = ::android::IBinder::FIRST_CALL_TRANSACTION + 9;
 static constexpr uint32_t TRANSACTION_registerClientCallback = ::android::IBinder::FIRST_CALL_TRANSACTION + 10;
 static constexpr uint32_t TRANSACTION_tryUnregisterService = ::android::IBinder::FIRST_CALL_TRANSACTION + 11;
 static constexpr uint32_t TRANSACTION_getServiceDebugInfo = ::android::IBinder::FIRST_CALL_TRANSACTION + 12;

從這些接口的變動我們也可以很清晰地把握住 servicemanager 的前進(jìn)方向

5.2 DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE

frameworks/native/libs/binder/include/binder/IInterface.h
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                          static_assert(internal::allowedManualInterface(NAME),                                "b/64223827: Manually written binder interfaces are "                  "considered error prone and frequently have bugs. "                    "The preferred way to add interfaces is to define "                    "an .aidl file to auto-generate the interface. If "                    "an interface must be manually written, add its "                      "name to the whitelist.");                              DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)   \-----------------------------constexpr const char* const kManualInterfaces[] = {
 "android.app.IActivityManager",
 "android.app.IUidObserver",
 "android.drm.IDrm",
 "android.dvr.IVsyncCallback",
 "android.dvr.IVsyncService",
 "android.gfx.tests.ICallback",
 "android.gfx.tests.IIPCTest",......

以后手寫的 native 服務(wù)需要關(guān)注下這個宏,做了限制。谷歌建議是現(xiàn)在的 native服務(wù)都用 aidl,別手寫

5.3 String16、String8 與 name

aidl 改造之前,都是一路 String16 從客戶端傳到服務(wù)端,而現(xiàn)在需要繞一些路了。還是以 addService 為例

status_t ServiceManagerShim::addService(const String16& name,){
   Status status = mTheRealServiceManager->addService(
       String8(name).c_str(), );在這里轉(zhuǎn)一次,16轉(zhuǎn)成8
       ------------------------------------------
       _aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name);
       在BpServiceManager里又轉(zhuǎn)了一次,8轉(zhuǎn)16
       ------------------------------------------
       _aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);
       現(xiàn)在來到BnServiceManager繼續(xù)轉(zhuǎn),16轉(zhuǎn)8

轉(zhuǎn)來轉(zhuǎn)去快暈了。總結(jié)就是,SM 服務(wù)端都是操作的 utf8,而 libbinder 客戶端都是 utf16。有修改的話需要注意下編碼問題

也可能是由于這個轉(zhuǎn)換問題,在服務(wù)端加了個服務(wù)名檢查

bool isValidServiceName(const std::string& name) {
   if (name.size() == 0) return false;
   if (name.size() > 127) return false;

   for (char c : name) {
       if (c == '_' || c == '-' || c == '.' || c == '/') continue;
       if (c >= 'a' && c <= 'z') continue;
       if (c >= 'A' && c <= 'Z') continue;
       if (c >= '0' && c <= '9') continue;
       return false;
  }

   return true;}

5.4 服務(wù)保存的數(shù)據(jù)結(jié)構(gòu)

SM 需要保存服務(wù)及其對應(yīng)的信息,Android 11 前用的鏈表 svc_list,成員是 svc_info 結(jié)構(gòu)體;Android 11 后用的 map,成員也是結(jié)構(gòu)體

frameworks/native/cmds/servicemanager/ServiceManager.h
struct Service {
       sp<IBinder> binder; // not null       bool allowIsolated;
       int32_t dumpPriority;
       bool hasClients = false; // notifications sent on true -> false.       bool guaranteeClient = false; // forces the client check to true       pid_t debugPid = 0; // the process in which this service runs
       // the number of clients of the service, including servicemanager itself       ssize_t getNodeStrongRefCount();
  };
   using ServiceMap = std::map<std::string, Service>;
   ServiceMap mNameToService;

這個 Service 結(jié)構(gòu)體有了更多的信息和能力,getNodeStrongRefCount() 方法可以獲取該服務(wù)有多少個客戶端

5.5 listServices 返回值

Android 11 之前的實現(xiàn)是客戶端循環(huán) checkService,Android 11 之后是直接返回的是 std::vector

  • 客戶端

frameworks/native/libs/binder/IServiceManager.cpp
Vector<String16> ServiceManagerShim::listServices(int dumpsysPriority){
   std::vector<std::string> ret;
   if (!mTheRealServiceManager->listServices(dumpsysPriority, &ret).isOk()) {
       return {};
  }

   Vector<String16> res;
   res.setCapacity(ret.size());
   for (const std::string& name : ret) {
       res.push(String16(name.c_str()));
  }
   return res;}
  • 服務(wù)端

frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::listServices(int32_t dumpPriority, std::vector<std::string>* outList) {
   size_t toReserve = 0;
   for (auto const& [name, service] : mNameToService) {
      (void) name;

       if (service.dumpPriority & dumpPriority) ++toReserve;
  }

   outList->reserve(toReserve);
   for (auto const& [name, service] : mNameToService) {
      (void) service;

       if (service.dumpPriority & dumpPriority) {
           outList->push_back(name);
      }
  }

這里也可以看到字符編碼的問題,客戶端用的是 utf16,而服務(wù)端用的是 utf8

  • 順便提一嘴 dumpsys 的畫蛇添足的修改

frameworks/native/cmds/dumpsys/dumpsys.cpp
if (services.empty() || showListOnly) {
        services = listServices(priorityFlags, asProto);                                                                        ......
    if (N > 1) {
        for (size_t i=0; i<N; i++) {
            sp<IBinder> service = sm_->checkService(services[i]);

獲取到服務(wù)列表后為什么再循環(huán) check 一遍呢?我感覺是沒有必要的。

5.6 waitForService 與 IServiceCallback.aidl

利用了匿名 binder 來傳遞回調(diào),有興趣可以自己看看

  • 回調(diào)注冊

frameworks/native/libs/binder/IServiceManager.cpp
sp<IBinder> ServiceManagerShim::waitForService(const String16& name16){
 class Waiter : public android::os::BnServiceCallback {
       Status onRegistration(const std::string& /*name*/,
                             const sp<IBinder>& binder) override {
 ......
    sp<Waiter> waiter = sp<Waiter>::make();
    if (Status status = mTheRealServiceManager->registerForNotifications(name, waiter);
  • 回調(diào)響應(yīng)

frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {auto it = mNameToRegistrationCallback.find(name);
   if (it != mNameToRegistrationCallback.end()) {
       for (const sp<IServiceCallback>& cb : it->second) {
           mNameToService[name].guaranteeClient = true;
           // permission checked in registerForNotifications           
           cb->onRegistration(name, binder);
      }
  }
  • aidl 及其生成的代碼位置

frameworks/native/libs/binder/aidl/android/os/IServiceCallback.aidl
out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/IServiceCallback.cpp

5.7 IClientCallback.aidl

IServiceManager.aidl 中定義的接口,都是在#include <binder/IServiceManager.h>嗎?答案為否。IClientCallback 就是這樣一個例子

想用 registerClientCallback 方法注冊回調(diào),需要直接使用#include <android/os/IServiceManager.h>拿到 BpServiceManager 實例,來通信

這個接口沒有暴露在 libbinder 的 IServiceManager 中

這個回調(diào)用于監(jiān)聽某個服務(wù)有 client,和 IServiceCallback.aidl 一樣是匿名 binder服務(wù),一個例子 LazyServiceRegistrar.cpp,可自行了解。

代碼路徑

frameworks/native/libs/binder/aidl/android/os/IClientCallback.aidl
frameworks/native/libs/binder/LazyServiceRegistrar.cpp
out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm_armv8-a_shared/gen/aidl/android/os/IClientCallback.cpp
frameworks/native/cmds/servicemanager/ServiceManager.cpp

六、總結(jié)

  • SM 經(jīng)過 aidl 和 libbinder 改造后,對于開發(fā)者來說,修改會更加規(guī)范和省心

  • 新引入的特性展示了 SM 功能更多的可能性,可為特定需求提供思路,native aidl和匿名 binder 回調(diào)值得學(xué)習(xí)

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产女性精品一区二区三区| 精品一区二区三区免费看| 欧美精品亚洲精品日韩专区| 久久99精品国产麻豆婷婷洗澡| 樱井知香黑人一区二区| 色丁香一区二区黑人巨大| 国产精品人妻熟女毛片av久 | 日本99精品在线观看| 亚洲国产一区精品一区二区三区色| 欧美尤物在线视频91| 欧美日韩最近中国黄片| 国产免费黄片一区二区| 国产精品一区二区不卡中文| 日本福利写真在线观看| 偷自拍亚洲欧美一区二页| 麻豆果冻传媒一二三区| 亚洲综合日韩精品欧美综合区| 国产精品激情对白一区二区| 清纯少妇被捅到高潮免费观看| 日本和亚洲的香蕉视频| 91亚洲精品亚洲国产| 欧美午夜一级特黄大片| 五月婷婷六月丁香亚洲| 日本一本在线免费福利| 国产女优视频一区二区| 日韩高清中文字幕亚洲| 黄色三级日本在线观看| 91精品视频全国免费| 欧美成人一区二区三区在线| 国产丝袜美女诱惑一区二区| 国自产拍偷拍福利精品图片| 欧美性欧美一区二区三区| 中文字幕91在线观看| 欧美日韩中黄片免费看| 男女一进一出午夜视频| 国产av一区二区三区麻豆| 亚洲一区二区三在线播放| 亚洲欧美日韩国产成人| 大香蕉网国产在线观看av| 少妇被粗大进猛进出处故事| 久热99中文字幕视频在线|