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 节。

扫描二维码关注公众号,回复: 15507749 查看本文章

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.cpp

sp<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.cpp

using AidlServiceManager = android::os::IServiceManager;

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

2.3 getContextObject(nullptr)

frameworks/native/libs/binder/ProcessState.cpp

sp<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.cpp

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    //通过lookupHandleLocked() 获取handle对应的handle_entry,这里封装了binder
    handle_entry* e = lookupHandleLocked(handle);

    if (e != nullptr) { //这里的entry基本都存在的
        IBinder* b = e->binder;

        //但有可能entry是新建的,此时binder为nullptr
        if (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.h

namespace 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.h

namespace android {

namespace os {

class BpServiceManager : public ::android::BpInterface<IServiceManager> {
    ...    
}; }}

BnServiceManager.h:

/out/soong/.intermediates/frameworks/native/libs/binder/libbinder/.../gen/aidl/android/os/BnServiceManager.h

namespace android {

namespace os {
class BnServiceManager : public ::android::BnInterface<IServiceManager> {
    ...
}; }}

ServcieManager.h:

frameworks/native/cmds/servicemanager/ServiceManager.h

namespace 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.h

template<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.cpp

class 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 ABI
    const 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.cpp

status_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.cpp

status_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.cpp

status_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.cpp

status_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.cpp

status_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()); //写入descriptor
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name); //写入service name
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeStrongBinder(service); //写入BBinder
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeBool(allowIsolated); //写入allowIsolated
  if (((_aidl_ret_status) != (::android::OK))) {
    goto _aidl_error;
  }
  _aidl_ret_status = _aidl_data.writeInt32(dumpPriority); //写入dumpPriority
  if (((_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.cpp

status_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.cpp

status_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.cpp

  case ::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.cpp

Status 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_SERVICE
    if (!mAccess->canAdd(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    //传入的IBinder 不能为nullptr
    if (binder == nullptr) {
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

    //service name 需要符合要求,由0-9、a-z、A-Z、下划线、短线、点号、斜杠组成,name 长度不能超过127
    if (!isValidServiceName(name)) {
        LOG(ERROR) << "Invalid service name: " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

    //这里应该是需要普通的vnd service 进行vintf 声明
#ifndef VENDORSERVICEMANAGER
    if (!meetsDeclarationRequirements(binder, name)) {
        // already logged
        return 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 registerForNotifications
            cb->onRegistration(name, binder);
        }
    }

    return Status::ok();
}

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

这里有两个注意点:

  • linkToDeath();
  • mNameToService;

4.1.1 mNameToService

先来看下这个变量。

frameworks/native/cmds/servciemanager/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;

在 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.cpp

status_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;

猜你喜欢

转载自blog.csdn.net/jingerppp/article/details/131397846
今日推荐