Android Binder通信原理(三):service注册

源码基于:Android R

0. 前言

上一文中详细分析了servicemanger 的启动流程,我们知道 servicemanager 作为 binder 机制中的一个特殊service,利用service map管理所有service,也是所有binder 通信的入口。

本文着重分析 service 的注册流程,下一文着重分析service 的获取流程。

1. 概念

1.1 ProcessState

Binder 中每个进程都会有且只有一个 ProcessState 用来记录 “进程状态”,初始化驱动设备,记录了驱动的名称、FD,记录进程线程数量的上限,记录binder 的 context obj,产生 binder 的线程名称,启动 binder 线程等等。

ProcessState 使用 self() 函数获取对象,因为有 vndbinder 和binder共用一份代码,所以,如果需要使用vndbinder ,需要在调用 self() 函数前调用 intWithDriver() 来指定驱动设备。

详细代码可以查看上一文的第 4 节。

1.2 IPCThreadState

同 ProcessState,每个进程有很多的线程用来记录 “线程状态”,在每次binder 的BINDER_WRITE_READ 调用后,驱动都会根据情况确定是否需要 spawn 线程,而创建一个PoolThread(详见ProcessState) 都会伴随一个IPCThreadState进行管理。

1.3 BpBinder

BpBinder 展开后就是Binder Proxy,也就是 Binder 代理的含义。BpBinder 是客户端用来与服务交互的代理类,负责实现跨进程传输的传输机制,不关心具体的传输内容。通信功能由其它类和函数实现,但由于这些类和函数被BpBinder代理,所以客户端需要通过BpBinder来发送Binder通信数据。 

1.4 BBinder

BBinder代表服务端,可以理解为服务的 Binder 实体,当服务端从 Binder 驱动中读取到数据后,由BBinder类进行处理。

2. defaultServiceManager()

servicemanger 作为binder 的特殊service,如果需要与其进行通信,需要获取到 binder 的代理端,而这个入口就是使用 defaultServiceManager。

Android R 的代码与之前很大的不同,下面列一下对比的代码。

Android R 之前:

sp<IServiceManager> defaultServiceManager()
{if (gDefaultServiceManager != NULL) return gDefaultServiceManager;{AutoMutex _l(gDefaultServiceManagerLock);while (gDefaultServiceManager == NULL) {gDefaultServiceManager = interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL));if (gDefaultServiceManager == NULL)sleep(1);}}return gDefaultServiceManager;
}

Android R 之后:

frameworks/native/libs/binder/IServiceManager.cppsp<IServiceManager> defaultServiceManager()
{std::call_once(gSmOnce, []() {sp<AidlServiceManager> sm = nullptr;while (sm == nullptr) {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);}}gDefaultServiceManager = new ServiceManagerShim(sm);});return gDefaultServiceManager;
}

这是一个全局的接口函数,维护两个全局的变量 gSmOnce 和 gDefaultServiceManager。

代码中使用了 c++11 的特性 call_once(),保证在多线程中 call_once() 中指定的函数只会被调用一次。这里指定的函数是 lambda 函数。

该函数分三个部分剖析:

  • AidlServiceManager 是什么?
  • ProcessState::self()->getContextObject(nullprt) 获取的是什么?
  • ServiceManagerShim 是什么?

之所以采用这种方式,应该是为了兼容 aidl 的native 调用和native 本身的调用。

另外,不同于R 之前,通过 defaultServiceManager() 接口获取到的 ServcieManager 的代理其实都是 ServiceManagerShim 对象。详细见下文。

2.1 头文件

#include <binder/IServiceManager.h>#include <android/os/BnServiceCallback.h>
#include <android/os/IServiceManager.h>

IServiceManager.cpp 依赖的直接头文件应该是 binder/IServiceManager.h,文件位于frameworks/native/libs/binder/include/binder/

另外两个头文件是通过编译器编译出来的,之所以会出现两个 IServiceManager.h ,是因为binder/IServiceManager.h 还是作为 native 开发的入口,而 android/os/IServcieManager.h 则作为其impl,主要为了兼容aidl 通信。

详细可以查看:

./soong/.intermediates/frameworks/native/libs/binder/libbinder/android_arm64_armv8-a_cortex-a55_shared/gen/aidl/android/os/IServiceManager.h

2.2 AidlServcieManager

frameworks/native/libs/binder/IServiceManager.cppusing AidlServiceManager = android::os::IServiceManager;

可以看出 AidlServiceManager 就是指的 android::os::IServiceManager,这里使用 AidlServcieManager 作为别名,也为了区分源生的 IServiceManager 类。

2.3 getContextObject(nullptr)

frameworks/native/libs/binder/ProcessState.cppsp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{sp<IBinder> context = getStrongProxyForHandle(0);if (context == nullptr) {ALOGW("Not able to get context object on %s.", mDriverName.c_str());}// The root object is special since we get it directly from the driver, it is never// written by Parcell::writeStrongBinder.internal::Stability::tryMarkCompilationUnit(context.get());return context;
}

主要就是获取 handle 为0 的 IBinder,ServiceManager 作为一个特殊的 service,其特殊性就是handle 为0。

2.3.1 getStrongProxyForHandle()

frameworks/native/libs/binder/ProcessState.cppsp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{sp<IBinder> result;AutoMutex _l(mLock);//通过lookupHandleLocked() 获取handle对应的handle_entry,这里封装了binderhandle_entry* e = lookupHandleLocked(handle);if (e != nullptr) { //这里的entry基本都存在的IBinder* b = e->binder;//但有可能entry是新建的,此时binder为nullptrif (b == nullptr || !e->refs->attemptIncWeak(this)) {//对于ServiceManager本身,需要通过transact()进行PING 处理if (handle == 0) {Parcel data;status_t status = IPCThreadState::self()->transact(0, IBinder::PING_TRANSACTION, data, nullptr, 0);if (status == DEAD_OBJECT)return nullptr;}//通过BpBinder::create()创建 BpBinder,并添加到handle_entry中b = BpBinder::create(handle);e->binder = b;if (b) e->refs = b->getWeakRefs();result = b;} else {...}}return result;
}

如代码注释,重要逻辑有两个地方:

  • 在lookupHandleLocked() 中会获取 handle 对应binder 的 handle_entry,对于新的 handle 会创建新的 handle_entry;
  • 利用 transact() 确认handle 通信是否正常,如果状态正常,则会创建一个ServiceManager 的 BpBinder 返回,后面 addService()、getService() 等操作都是通过该BpBinder 来操作。 

下面第 3 节,将 transact() 单独拿出来分析,后面的binder 通信都是通过这里进行。

在了解完 transact() 函数之后,继续来看下这里,此处transact() 的参数中 code 传入的是 PING_TRANSACTION,最终在 Binder.cpp 中会进行拦截处理,并返回 NO_ERROR。client 端在收到该返回后会通过 BpBinder::create() 创建出ServiceManager 在client 的代理BpServiceManager,其中 binder handle 会存放在代理中, 对于client 端都是通过这个handle 才能与 server 端通信。

注意的是,整个过程中 Interface 使用的是android.os.IServcieManager:

/out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/android/os/IServiceManager.hnamespace android {namespace os {class IServiceManager : public ::android::IInterface {DECLARE_META_INTERFACE(ServiceManager)...
}; }}

BpServiceManager.h:

/out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/android/os/BpServiceManager.hnamespace android {namespace os {class BpServiceManager : public ::android::BpInterface<IServiceManager> {...    
}; }}

BnServiceManager.h:

/out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/android/os/BnServiceManager.hnamespace android {namespace os {
class BnServiceManager : public ::android::BnInterface<IServiceManager> {...
}; }}

ServcieManager.h:

frameworks/native/cmds/servicemanager/ServiceManager.hnamespace android {using os::IClientCallback;
using os::IServiceCallback;class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {

2.4 interface_cast<AidlServiceManager>

sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));

在 getContextObject() 拿到 IServiceManager 的 BpBinder 之后,通过 interface_cast<INTERFACE>:

frameworks/native/libs/binder/include/binder/IInterface.htemplate<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{return INTERFACE::asInterface(obj);
}

在 IServiceManager.h 中已经 DECLARE_META_INTERFACE

namespace android {namespace os {class IServiceManager : public ::android::IInterface {DECLARE_META_INTERFACE(ServiceManager)...
}; }}

说白了,就是通过 interface_case<> 将 IBinder 对象转换成 INTERFACE 对象,这里指的是将从 IServiceManager 中获取的 BpBinder 转换成 AidlServiceManager 对象。

2.5 ServiceManagerShim

当通过上面获取到 sm之后,会通过 ServiceManagerShim 进行构造:

frameworks/native/libs/binder/IServiceManager.cppclass ServiceManagerShim : public IServiceManager
{
public:explicit ServiceManagerShim (const sp<AidlServiceManager>& impl);sp<IBinder> getService(const String16& name) const override;sp<IBinder> checkService(const String16& name) const override;status_t addService(const String16& name, const sp<IBinder>& service,bool allowIsolated, int dumpsysPriority) override;Vector<String16> listServices(int dumpsysPriority) override;sp<IBinder> waitForService(const String16& name16) override;bool isDeclared(const String16& name) override;// for legacy ABIconst String16& getInterfaceDescriptor() const override {return mTheRealServiceManager->getInterfaceDescriptor();}IBinder* onAsBinder() override {return IInterface::asBinder(mTheRealServiceManager).get();}
private:sp<AidlServiceManager> mTheRealServiceManager;
};ServiceManagerShim::ServiceManagerShim(const sp<AidlServiceManager>& impl): mTheRealServiceManager(impl)
{}

从构造函数中得知,ServiceManagerShim 就是 AidlServiceManager 的native 端封装。

后面开发过程中都会通过 defaultServiceManager() 接口获取ServiceManager 的代理 BpServiceManager,为了方便记忆,下面通过框架图进一步的说明:

图中共有 4 条调用线路:

第一条:Client 端通过 defaultServiceManager() 接口调用获取到 sp<IServiceManager> 实例,而这个实例是全局变量 gDefaultServiceManager,其实就是 ServiceManagerShim 类型的对象;

第二条:在第一条中已经提到了,通过defaultServiceManager() 获取到的其实就是ServiceManagerShim 类型的对象,使用 ServiceManagerShim 类型的目的其实就是为了封装 AidlServiceManager,即该类中的成员变量 mTheRealServiceManager;

第三条:如第二条所述,ServiceManagerShim 中的 mTheRealServiceManager 就是封装AidlServiceManager 所在,而 mTheRealServiceManager 也就是BpServiceManager 实例;

第四条:经过 mTheRealServiceManager 调用后进行binder 通信,会调用到ServiceManager,因为 BnServiceManager 被 ServiceManager 继承,BBinder 的onTransact() 是在BnServiceManager 中,所以最终处理会指向 BnServiceManager 的onTransact();

3. IPCThreadState::transact()

frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{status_t err;flags |= TF_ACCEPT_FDS;err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);...if ((flags & TF_ONE_WAY) == 0) {......if (reply) {err = waitForResponse(reply);} else {Parcel fakeReply;err = waitForResponse(&fakeReply);}...} else {err = waitForResponse(nullptr, nullptr);}return err;
}

transact 参数有5 个:

  • handle, 每个BpBinder 都有handle,在创建的时候会传入,当要跟 servicemanager 通信时,需要拿到 servicemanager 的代理,即 handle 为0 的 BpBinder;
  • code, BC_TRANSACTION 操作的详细命令码;
  • data,传送携带的数据;
  • replay,从server 端返回的数据;
  • flags,传送配套的flags;

3.1 writeTransactionData()

frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{binder_transaction_data tr;tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */tr.target.handle = handle;tr.code = code;tr.flags = binderFlags;tr.cookie = 0;tr.sender_pid = 0;tr.sender_euid = 0;const status_t err = data.errorCheck();if (err == NO_ERROR) {tr.data_size = data.ipcDataSize();tr.data.ptr.buffer = data.ipcData();tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);tr.data.ptr.offsets = data.ipcObjects();} else if (statusBuffer) {tr.flags |= TF_STATUS_CODE;*statusBuffer = err;tr.data_size = sizeof(status_t);tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);tr.offsets_size = 0;tr.data.ptr.offsets = 0;} else {return (mLastError = err);}mOut.writeInt32(cmd);mOut.write(&tr, sizeof(tr));return NO_ERROR;
}

将transact 传输携带的 data,转换成驱动所需要的数据类型 binder_transaction_data,并携带cmd 一同存入到 mOut,等待下一次的 execute。

其中 tr.data.ptr.buffer 记录了Parcel传输的数据,tr.data.ptr.offsets记录下 “待传数据” 中所有binder对象的具体位置。

3.2 waitForResponse()

当writeTransactionData() 完成之后线程就处于等待 server 端处理,调用 waitForResponse() 进入等待。

frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{uint32_t cmd;int32_t err;while (1) {if ((err=talkWithDriver()) < NO_ERROR) break;err = mIn.errorCheck();if (err < NO_ERROR) break;if (mIn.dataAvail() == 0) continue;cmd = (uint32_t)mIn.readInt32();switch (cmd) {case BR_TRANSACTION_COMPLETE:...case BR_DEAD_REPLY:...case BR_FAILED_REPLY:...case BR_ACQUIRE_RESULT:...case BR_REPLY:{binder_transaction_data tr;err = mIn.read(&tr, sizeof(tr));ALOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY");if (err != NO_ERROR) goto finish;if (reply) {if ((tr.flags & TF_STATUS_CODE) == 0) {reply->ipcSetDataReference(reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),tr.data_size,reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t),freeBuffer, this);} else {err = *reinterpret_cast<const status_t*>(tr.data.ptr.buffer);freeBuffer(nullptr,reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),tr.data_size,reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t), this);}} else {freeBuffer(nullptr,reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),tr.data_size,reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),tr.offsets_size/sizeof(binder_size_t), this);continue;}}goto finish;default:err = executeCommand(cmd);if (err != NO_ERROR) goto finish;break;}}...return err;
}

waitForResponse() 是client 进程通过 binder 驱动与 server 通信的核心处理部分。

通过 talkWithDriver() 在上一篇博文中已经分析过:

  • 主要通过 BINDER_WRITE_READ 通知驱动;
  • 如果是事务处理 client 端会在 mOut 中携带 cmd BC_TRANSACTION
  • 驱动 ioctl 收到 BINDER_WRITE_READ 会进入 binder_ioctl_write_read() 进行进一步处理;
    • 如果驱动发现收到的 binder_write_read 有write 的数据(即client需要传输数据),认为client 端携带了data 过来,会进行 binder_thread_write() 处理;
    • 如果驱动发现收到的 binder_write_read 有read 数据(即client需要从server 回收数据),认为client 需要接收server 数据,会进行 binder_thread_read() 处理;
  • 调用 binder_thread_read() 时,驱动会根据 proc 相关的信息,找到 server 的cookie,根据需求确定执行 BR_TRANSACTION 还是 BR_REPLY,最终通过 binder_stat_br 执行;
    • client 端 BC_TRANSACTION 过来,驱动转换成 BR_TRANSACTION 通知到server;
    • server端也有个 waitForResponse(),在收到 BR_TRANSACTION 时,进入executeCommand(),在处理完后会发出 BC_REPLY 并通过 BINDER_WRITE_READ 通知回驱动,驱动转换成 BR_REPLY 通知回client;
  • client 端调用的 talkWithDriver() 返回后,会处理 BR_REPLY 的 case,将 mIn 中的数据读出来并存储到 Parcel *reply 中;

3.2.1 executeCommand()

来看下server 端在收到 BR_TRANSACTION 后的处理

frameworks/native/libs/binder/IPCThreadState.cppstatus_t IPCThreadState::executeCommand(int32_t cmd)
{...case BR_TRANSACTION_SEC_CTX:case BR_TRANSACTION:{binder_transaction_data_secctx tr_secctx;binder_transaction_data& tr = tr_secctx.transaction_data;...Parcel buffer;...Parcel reply;status_t error;...if (tr.target.ptr) {// We only have a weak reference on the target object, so we must first try to// safely acquire a strong reference before doing anything else with it.if (reinterpret_cast<RefBase::weakref_type*>(tr.target.ptr)->attemptIncStrong(this)) {error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);} else {error = UNKNOWN_TRANSACTION;}} else {error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);}if ((tr.flags & TF_ONE_WAY) == 0) {...sendReply(reply, 0);} else {...}...}break;
}

对于handle不为0 的,会通过 BBinder 的 transact() 进行处理,对于handle 为0,也就是servicemanager 中收到 BR_TRANSACTION,即用 the_conext_object(servicemanger在运行时已经将context obj 保存到全局变量 the_context_object)调用 transact()。

其实不管 handle 为多少,最终都是通过BBinder 调用的transact()。

在 transact() 成功返回后如果是 TF_ONE_WAY 方式通信,server 会通过sendReply() 将返回值通过给client 端。

4. addService()

frameworks/native/libs/binder/IServiceManager.cppstatus_t ServiceManagerShim::addService(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();
}

终于拿到了ServiceManager 的BpInterface,后面的调用都是通过ServiceManagerShim 对象,但这里只是做了下封装,实际上还是要通过BpInterface,即BpServiceManager 来调用:

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/frameworks/native/libs/binder/aidl/android/os/IServiceManager.cpp::android::binder::Status BpServiceManager::addService(const ::std::string& name, const ::android::sp<::android::IBinder>& service, bool allowIsolated, int32_t dumpPriority) {::android::Parcel _aidl_data;::android::Parcel _aidl_reply;::android::status_t _aidl_ret_status = ::android::OK;::android::binder::Status _aidl_status;_aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor()); //写入descriptorif (((_aidl_ret_status) != (::android::OK))) {goto _aidl_error;}_aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name); //写入service nameif (((_aidl_ret_status) != (::android::OK))) {goto _aidl_error;}_aidl_ret_status = _aidl_data.writeStrongBinder(service); //写入BBinderif (((_aidl_ret_status) != (::android::OK))) {goto _aidl_error;}_aidl_ret_status = _aidl_data.writeBool(allowIsolated); //写入allowIsolatedif (((_aidl_ret_status) != (::android::OK))) {goto _aidl_error;}_aidl_ret_status = _aidl_data.writeInt32(dumpPriority); //写入dumpPriorityif (((_aidl_ret_status) != (::android::OK))) {goto _aidl_error;}//带入code、_aidl_data,以及用来回复的_aidl_reply_aidl_ret_status = remote()->transact(::android::IBinder::FIRST_CALL_TRANSACTION + 2 /* addService */, _aidl_data, &_aidl_reply);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;}//_aidl_reply 中存放的是addService 的返回值_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;
}

这里主要有两点:

  • BBinder 是通过 writeStrongBinder()接口存放到 _aidl_data 中,后面会单独分析该函数;
  • 使用 BpBinder->transact() 进行binder 通信;

4.1 BpBinder::transact()

remote() 就是 IServcieManager 的 BpBinder,在 getContextObject() 的时候create 出来的,来看下 BpBinder 的 transact()

frameworks/native/libs/binder/BpBinder.cppstatus_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{...status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);...
}

这里调用到 3.2.1 节,最终通过 BBinder的 transact():

frameworks/native/libs/binder/Binder.cppstatus_t BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{data.setDataPosition(0);status_t err = NO_ERROR;switch (code) {case PING_TRANSACTION:err = pingBinder();break;case EXTENSION_TRANSACTION:err = reply->writeStrongBinder(getExtension());break;case DEBUG_PID_TRANSACTION:err = reply->writeInt32(getDebugPid());break;default:err = onTransact(code, data, reply, flags);break;}// In case this is being transacted on in the same process.if (reply != nullptr) {reply->setDataPosition(0);}return err;
}

BBinder 的 onTransact() 会在Bn 端被覆盖,这里指的是BnServiceManager:

out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/frameworks/native/libs/binder/aidl/android/os/IServiceManager.cppcase ::android::IBinder::FIRST_CALL_TRANSACTION + 2 /* addService */:{::std::string in_name;::android::sp<::android::IBinder> in_service;bool in_allowIsolated;int32_t in_dumpPriority;if (!(_aidl_data.checkInterface(this))) {_aidl_ret_status = ::android::BAD_TYPE;break;}_aidl_ret_status = _aidl_data.readUtf8FromUtf16(&in_name);if (((_aidl_ret_status) != (::android::OK))) {break;}_aidl_ret_status = _aidl_data.readStrongBinder(&in_service);if (((_aidl_ret_status) != (::android::OK))) {break;}_aidl_ret_status = _aidl_data.readBool(&in_allowIsolated);if (((_aidl_ret_status) != (::android::OK))) {break;}_aidl_ret_status = _aidl_data.readInt32(&in_dumpPriority);if (((_aidl_ret_status) != (::android::OK))) {break;}::android::binder::Status _aidl_status(addService(in_name, in_service, in_allowIsolated, in_dumpPriority));_aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);if (((_aidl_ret_status) != (::android::OK))) {break;}if (!_aidl_status.isOk()) {break;}}break;

addServcie() 最终会调用到真正实现 BnServiceManager 的地方,也就是ServcieManager 中的addService():

frameworks/native/cmds/servicemanager/ServiceManager.cppStatus ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {auto ctx = mAccess->getCallingContext();//应用进程没有权限注册服务if (multiuser_get_app_id(ctx.uid) >= AID_APP) {return Status::fromExceptionCode(Status::EX_SECURITY);}// selinux 曲线是否允许注册为SELABEL_CTX_ANDROID_SERVICEif (!mAccess->canAdd(ctx, name)) {return Status::fromExceptionCode(Status::EX_SECURITY);}//传入的IBinder 不能为nullptrif (binder == nullptr) {return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);}//service name 需要符合要求,由0-9、a-z、A-Z、下划线、短线、点号、斜杠组成,name 长度不能超过127if (!isValidServiceName(name)) {LOG(ERROR) << "Invalid service name: " << name;return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);}//这里应该是需要普通的vnd service 进行vintf 声明
#ifndef VENDORSERVICEMANAGERif (!meetsDeclarationRequirements(binder, name)) {// already loggedreturn Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);}
#endif  // !VENDORSERVICEMANAGER//注册linkToDeath,监听service 状态if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {LOG(ERROR) << "Could not linkToDeath when adding " << name;return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);}//添加到map 中auto entry = mNameToService.emplace(name, Service {.binder = binder,.allowIsolated = allowIsolated,.dumpPriority = dumpPriority,.debugPid = ctx.debugPid,});//确认是否注册了service callback,如果注册调用回调auto it = mNameToRegistrationCallback.find(name);if (it != mNameToRegistrationCallback.end()) {for (const sp<IServiceCallback>& cb : it->second) {entry.first->second.guaranteeClient = true;// permission checked in registerForNotificationscb->onRegistration(name, binder);}}return Status::ok();
}

addServcie() 实现部分,之前在servicemanager 启动一文中已经有简单的分析过。

这里有两个注意点:

  • linkToDeath();
  • mNameToService;

4.1.1 mNameToService

先来看下这个变量。

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

在 ServiceManager 类中有这样的定义。

mNameToService 其实就是 name-Service 的map,当addService() 流程执行到 ServiceManager 中,最终会将新的 service 存放在该变量中,而之后 Client 端也可以通过 getService() 来从 mNameToService 中获取name 对应的 service。

getService() 详细可以查看《Android Binder通信原理(三):service获取》一文。

4.1.2 linkToDeath()

addService() 中有这一段逻辑:

if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {}

binder 在Bp 端传入的参数为 service,也就是 BBinder,在transact 之前需要将其存放到data 中,使用的是函数 writeStrongBinder(),详细看第 4 节。

frameworks/native/libs/binder/Parcel.cppstatus_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{return flattenBinder(val);
}status_t Parcel::flattenBinder(const sp<IBinder>& binder)
{flat_binder_object obj;if (IPCThreadState::self()->backgroundSchedulingDisabled()) {/* minimum priority for all nodes is nice 0 */obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;} else {/* minimum priority for all nodes is MAX_NICE(19) */obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;}if (binder != nullptr) {BBinder *local = binder->localBinder();if (!local) {BpBinder *proxy = binder->remoteBinder();if (proxy == nullptr) {ALOGE("null proxy");}const int32_t handle = proxy ? proxy->handle() : 0;obj.hdr.type = BINDER_TYPE_HANDLE;obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */obj.handle = handle;obj.cookie = 0;} else {if (local->isRequestingSid()) {obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;}obj.hdr.type = BINDER_TYPE_BINDER;obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());obj.cookie = reinterpret_cast<uintptr_t>(local);}} else {obj.hdr.type = BINDER_TYPE_BINDER;obj.binder = 0;obj.cookie = 0;}return finishFlattenBinder(binder, obj);
}

flattenBinder() 的目的是将 Binder 扁平化,把一个Binder实体“压扁”并写入Parcel。这里"压扁"的含义,其实就是把Binder对象整理成 flat_binder_object 变量。如果压扁的是 Binder实体,那么 flat_binder_object 用 cookie 域记录 binder 实体的指针,即BBinder指针,而如果打扁的是Binder代理,那么 flat_binder_object 用handle域记录的binder代理的句柄值。

接着 flatten_binder() 调用了一个关键的 finish_flatten_binder() 函数。这个函数内部会记录下刚刚被扁平化的 flat_binder_object 在parcel中的位置。说得更详细点儿就是,parcel 对象内部会有一个buffer,记录着parcel中所有扁平化的数据,有些扁平数据是普通数据,而另一些扁平数据则记录着binder对象。所以parcel中会构造另一个mObjects数组,专门记录那些binder扁平数据所在的位置。

Parcel 会随着transact 的 BC_TRANSACTION 传入 binder 驱动,在驱动中会根据特殊需求,将flat_binder_object 转换,例如:

ret = binder_translate_binder(fp, t, thread);
或
ret = binder_translate_handle(fp, t, thread);

如果是 BBinder 会将 flat_binder_object 中 hdr.type 从 BINDER_TYPE_BINDER转换为BINDER_TYPE_HANDLE。

这里暂时不详细分析了,后面会在驱动一节中重点分析数据传输的过程。

回来开始,BBinder 通过驱动后会通过 BR_TRANSACTION 传到服务端,会在 IPCThreadState 的executeCommand() 中重新转换成Parcel,并最终传入BBinder->transact(),这里会传入addService()。所以,这里binder->remoteBinder() != nullptr 是真。

至此,service 注册的流程分析完毕,总结如下:

  • servcie 作为servicemanager 的client 端,需要通过defaultServiceManager 获取servicemanager 的代理;
  • 将service 的Binder 作为参数,传入addService(),并通过Parcel.writeStrongBinder() 将 Binder 压缩为flat_binder_object;
  • 通过BpServiceManager 所对应的BpBinder->transact(),将data 和reply 传入,通过service 所在进程中的IPCThreadState->transact 进行talkWithDriver,通过 BC_TRANSACTION 将code和data 传入驱动, 经过驱动后将 flat_binder_object 做适当的 translate;
  • servicemanger 进程中IPCThreadState 收到 BR_TRANSACTION 后通过 the_context_object->transact 通知到 BnServiceManager;
  • BBinder->onTransact() 会对addService() 对应的code做对应处理,调用实现ServiceManager::addService();
  • 将 translate 后的Binder 存进mNameToService 中,用于get、check、list;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/3614.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

智能文档图像处理技术应用与实践

写在前面智能文档处理面临的技术难题智能文档处理的研究领域● 文档图像分析与预处理● 手写板反光擦除● 版面分析与文档还原 写在最后 写在前面 VALSE 2023 无锡视觉与学习青年学者研讨会近期在无锡国际博览中心举办&#xff0c;由江南大学和无锡新吴区联合承办。本次会议旨…

netty学习(1):多个客户端与服务器通信

1. 基于前面一节netty学习&#xff08;1&#xff09;:1个客户端与服务器通信 只需要把服务器的handler改造一下即可&#xff0c;通过ChannelGroup 找到所有的客户端channel&#xff0c;发送消息即可。 package server;import io.netty.channel.*; import io.netty.channel.gr…

陪诊小程序系统|陪诊软件开发|陪诊系统功能和特点

随着医疗服务的逐步改善和完善&#xff0c;越来越多的人群开始走向医院就诊&#xff0c;而其中不少人往往需要有人陪同前往&#xff0c;这就导致了许多矛盾与问题的发生&#xff0c;比如长时间等待、找不到合适的陪诊人员等。因此为人们提供一种方便快捷的陪诊服务成为了一种新…

成本降低60%至70%?中国展现顶级电池技术,锂电就是下一个铅酸

在3月份&#xff0c;宁德时代宣布加速推进钠离子电池产业化&#xff0c;以降低成本并提供差异化产品和技术&#xff0c;帮助客户提升产品竞争力和占据更大市场份额。孚能科技已在上半年开始批量生产钠离子电池&#xff0c;而拓邦股份也在最近的国际电池技术展上发布了自家的钠离…

vue下基于elementui自定义表单-后端数据设计篇

vue下基于elementui自定义表单-后端篇 自定义表单目前数据表单设计是基于数据量不大的信息单据场景&#xff0c;因为不考虑数据量带来的影响。 数据表有: 1.表单模版表&#xff0c;2.表单实例表&#xff0c;3.表单实例项明细表&#xff0c;4表单审批设计绑定表 以FormJson存…

【动态规划】LeetCode 583. 两个字符串的删除操作 Java

583. 两个字符串的删除操作 我的代码&#xff0c;错误代码&#xff0c;只考虑到了字母出现的次数&#xff0c;没有考虑到两个字符串中字母出现的顺序 class Solution {public int minDistance(String word1, String word2) {int[] arr1 new int[26];int[] arr2 new int[26];…

【数据结构】——常见排序算法(演示图+代码+算法分析)

目录 1. 常见排序算法 1.2 稳定性 2. 常见排序算法的实现 2.1 插入排序 2.1.1基本思想 2.1.2代码 2.1.4算法分析 2.2 希尔排序 2.2.1基本思想 2.2.2代码 2.2.3演示图 2.2.4算法分析 2.3 选择排序 2.3.1基本思想 2.3.2代码 2.3.3演示图 2.3.4算法分析 2.4 堆排…

npm启动,node.js版本过高

“dev_t”: “set NODE_OPTIONS”–openssl-legacy-provider" & npm run dev\n"

Quiz 12: Regular Expressions | Python for Everybody 配套练习_解题记录

文章目录 Python for Everybody课程简介Regular Expressions单选题&#xff08;1-8&#xff09;操作题Regular Expressions Python for Everybody 课程简介 Python for Everybody 零基础程序设计&#xff08;Python 入门&#xff09; This course aims to teach everyone the …

使用Nginx的反向代理来访问服务器例子——Nginx笔记

因为网站上的视频加载过慢&#xff0c;想使用nginx服务器实现HLS视频播放服务。顺便记录一下通过Nginx的方向代理来访问服务器。这里在原先的项目上进行改造。原先的项目已经部署在公网&#xff0c;使用tomcat服务器&#xff0c;可以直接用地址进行访问。 1.这里使用的8080端口…

springboot详细整合mybatisplus

SpringBoot详细整合mybatisPlus 文章目录 SpringBoot详细整合mybatisPlus一、引入mybatis_plus依赖二、修改mybatis_plus的yml配置三、添加mybatis_plus的其他配置以及包扫描四&#xff0c;修改mybatis的配置&#xff08;这一步根据实际情况修改&#xff09; 无奈&#xff0c;一…

stm32读取DHT11温湿度传感器

stm32读取DHT11温湿度传感器 一.序言二.DHT11响应数据格式三.DHT11通讯过程3.1 产生起始信号3.2 读取数据03.3 读取数据1DHT11停止信号 四.代码实例4.1读取DHT11源文件4.2 读取DHT11头文件 五.结语5.1 总结整体思路5.2 对读者的期望 一.序言 我们知道DHT11是单总线协议&#x…