Android Binder详解【5】 ServiceManager

Android 系统的 Binder 通信体系中,ServiceManager(简称 SM)是无可替代的核心枢纽 ------ 它是所有 Binder 服务的 "注册表",负责系统 / 应用服务的注册(addService)、查询(getService)、删除等核心操作。与普通 Android 服务不同,SM 的设计极度精简且特殊:摒弃了常规的 Binder 线程池,仅通过单线程 + Looper 的方式完成与 Binder 驱动的交互。本文将基于 Android 原生源码,深度解析 SM 的核心实现逻辑,并通过 SurfaceFlinger(SF)注册到 SM 的完整链路,直观展示 Binder 通信的全过程。

一、SM 的核心定位与设计特点

1. 核心定位

SM 是 Android 系统级的 "服务注册表",所有想要通过 Binder 提供服务的组件(如 ActivityManagerService、WindowManagerService、SurfaceFlinger)都必须先向 SM 注册;而想要使用服务的客户端,也必须先通过 SM 查询到对应的服务 Binder 对象,才能发起跨进程调用。

2. 关键设计特点

  • 功能单一性:仅聚焦服务注册 / 查询 / 删除核心逻辑,无多余业务逻辑;
  • 无 Binder 线程池:普通 Android 服务通过 Binder 线程池处理多客户端请求,而 SM 仅用 1 个主线程;
  • Looper 驱动交互:直接监听 Binder 驱动的文件描述符(FD),通过 Looper 事件循环处理驱动命令;
  • Binder 上下文管理器:向 Binder 驱动声明自己是 "上下文管理器",成为 Binder 通信的根节点。

二、SM 的启动流程(main.cpp 核心逻辑)

SM 的入口位于native\cmds\servicemanager\main.cpp,其启动流程是理解 SM 的关键,核心步骤如下:

复制代码
int main(int argc, char** argv) {
    // 1. 初始化Binder驱动关联,禁用线程池
    const char* driver = "/dev/binder";
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    ps->setThreadPoolMaxThreadCount(0); // 核心:禁用Binder线程池
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

    // 2. 创建SM实例并自注册(将自己注册为"manager"服务)
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
    if (!manager->addService("manager", manager, false, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }

    // 3. 设置为Binder上下文管理器(SM专属标识)
    IPCThreadState::self()->setTheContextObject(manager);
    ps->becomeContextManager();

    // 4. 初始化Looper,注册Binder驱动FD和定时器FD
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
    BinderCallback::setupTo(looper); // 注册Binder驱动FD
    ClientCallbackCallback::setupTo(looper, manager); // 注册定时器FD

    // 5. 进入Looper无限循环,监听并处理事件
    while(true) {
        looper->pollAll(-1);
    }

    return EXIT_FAILURE;
}

关键步骤解析

  1. 禁用 Binder 线程池setThreadPoolMaxThreadCount(0)通过ioctl告知 Binder 驱动,SM 不需要线程池,所有请求由主线程处理;
  2. 自注册:SM 将自身注册为名为 "manager" 的服务,确保其他组件能查询到 SM 本身;
  3. 成为上下文管理器becomeContextManager()通过ioctl(BINDER_SET_CONTEXT_MGR_EXT)向驱动声明身份,SM 的 Binder 句柄固定为 0,是 Binder 通信的根;
  4. Looper 事件循环 :SM 的主线程通过looper->pollAll(-1)进入无限循环,等待 Binder 驱动或定时器的事件触发。

三、Binder 驱动事件处理:BinderCallback

SM 通过BinderCallback将 Binder 驱动的 FD 注册到 Looper,实现 "驱动有命令时主动回调" 的机制,核心代码如下:

复制代码
class BinderCallback : public LooperCallback {
public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = sp<BinderCallback>::make();

        // 1. 获取Binder驱动FD,并设置为轮询模式
        int binder_fd = -1;
        IPCThreadState::self()->setupPolling(&binder_fd);

        // 2. 将FD注册到Looper,监听EVENT_INPUT(驱动有数据/命令时触发)
        int ret = looper->addFd(binder_fd,
                                Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT,
                                cb,
                                nullptr);
        LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");

        return cb;
    }

    // 3. 驱动事件回调:处理Binder命令
    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        IPCThreadState::self()->handlePolledCommands(); // 核心:处理驱动命令
        return 1;  // 持续监听
    }
};
特殊逻辑:SM 的 Binder 调用路由

普通服务的 Binder 调用会通过tr.target.ptr找到对应的 BBinder,但 SM 作为上下文管理器,tr.target.ptr为 0,直接调用预先设置的the_context_object(即 SM 自身):

复制代码
// IPCThreadState::executeCommand 中 BR_TRANSACTION 分支
if (tr.target.ptr) {
    // 普通服务:通过ptr找到BBinder
    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(...);
} else {
    // SM专属:直接调用上下文对象(SM)的transact
    error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}

四、客户端连接状态检测:ClientCallbackCallback

SM 通过 5 秒定时器周期性检测服务的客户端连接状态,核心功能由ClientCallbackCallback实现:

复制代码
class ClientCallbackCallback : public LooperCallback {
public:
    static sp<ClientCallbackCallback> setupTo(const sp<Looper>& looper, const sp<ServiceManager>& manager) {
        sp<ClientCallbackCallback> cb = sp<ClientCallbackCallback>::make(manager);

        // 1. 创建定时器FD(5秒周期)
        int fdTimer = timerfd_create(CLOCK_MONOTONIC, 0);
        itimerspec timespec {
            .it_interval = {5, 0}, // 周期:5秒
            .it_value = {5, 0},    // 首次触发:5秒后
        };
        timerfd_settime(fdTimer, 0, &timespec, nullptr);

        // 2. 将定时器FD注册到Looper
        looper->addFd(fdTimer, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb, nullptr);
        return cb;
    }

    // 3. 定时器回调:检测客户端连接状态
    int handleEvent(int fd, int /*events*/, void* /*data*/) override {
        uint64_t expirations;
        read(fd, &expirations, sizeof(expirations)); // 读取定时器事件
        mManager->handleClientCallbacks(); // 核心:检测客户端连接状态
        return 1;
    }
};

核心作用

handleClientCallbacks()会遍历 SM 中注册的所有服务,检测每个服务的客户端连接是否活跃,若状态发生变化(如客户端断开),会主动通知服务端,保证服务能及时清理无效连接。

五、SM 的核心功能实现:AIDL 与 ServiceManager 类

SM 的核心功能(addService/getService 等)通过 AIDL 定义,并由ServiceManager类实现具体逻辑。

1. AIDL 生成的 BnServiceManager

IServiceManager.aidl经编译后生成BnServiceManager(服务端)和BpServiceManager(客户端),其中BnServiceManager负责将 Binder 命令转换为具体方法调用:

复制代码
// BnServiceManager::onTransact 核心逻辑
status_t BnServiceManager::onTransact(uint32_t _aidl_code, const Parcel& _aidl_data, Parcel* _aidl_reply, uint32_t _aidl_flags) {
    switch (_aidl_code) {
    case TRANSACTION_getService: // getService命令
        ::std::string in_name;
        _aidl_data.readUtf8FromUtf16(&in_name);
        // 调用SM的getService方法
        binder::Status _aidl_status(getService(in_name, &_aidl_return));
        _aidl_reply->writeStrongBinder(_aidl_return); // 返回服务Binder对象
        break;
    case TRANSACTION_addService: // addService命令
        // 同理:解析参数,调用addService方法
        break;
    }
    return OK;
}

2. 具体功能实现:ServiceManager 类

ServiceManager类是 SM 核心功能的真正执行者,继承自IServiceManager,实现了所有服务管理逻辑:

复制代码
// ServiceManager::getService 核心实现
Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
    *outBinder = tryGetService(name, true); // 查询服务注册表,返回Binder对象
    return Status::ok();
}

六、完整 Binder 链路实例:SurfaceFlinger 注册到 SM 的过程

为了更直观理解 SM 的工作机制,我们以SurfaceFlinger(SF)注册到 SM 的完整流程为例,梳理从客户端发起请求到 SM 完成服务注册的全 Binder 链路,保留关键代码和文件路径:

步骤 1:SF 发起注册请求(客户端入口)

SurfaceFlinger 在启动时,会调用 SM 的addService方法将自身注册到 SM,

复制代码
// main_surfaceflinger.cpp
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false,
               IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL | IServiceManager::DUMP_FLAG_PROTO);

步骤 2:ServiceManagerShim 层封装(适配层)

请求先经过ServiceManagerShim做参数适配

复制代码
// 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();
}

步骤 3:BpServiceManager 发起 Binder 跨进程调用

AIDL 工具生成的BpServiceManager(客户端代理)会通过remote()->transact发起跨进程调用

BnServiceManager 和BpServiceManager 不是在framework 源码里的, 是aidl工具编译的时候生成的

frameworks\native\libs\binder\aidl\android\os\IServiceManager.aidl

复制代码
// android/os/IServiceManager.cpp (AIDL工具生成)
::android::binder::Status BpServiceManager::addService(const ::std::string& name, const ::android::sp<::android::IBinder>& service, bool allowIsolated, int32_t dumpPriority) {
  _aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_addService, _aidl_data, &_aidl_reply, 0);
}

步骤 4:BpBinder 封装 Binder 调用参数

BpBinder作为客户端 Binder 代理的核心,会将调用参数封装并交给IPCThreadState处理,代码位于native\libs\binder\BpBinder.cpp

复制代码
// native\libs\binder\BpBinder.cpp
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // SM的Binder句柄固定为0,驱动会根据handle转发数据到SM进程
    status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
}

步骤 5:IPCThreadState 与 Binder 驱动交互

IPCThreadState负责将调用数据写入 Binder 驱动,并等待响应,代码位于native\libs\binder\IPCThreadState.cpp

复制代码
// native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
    waitForResponse(reply);
}

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;

        cmd = (uint32_t)mIn.readInt32();
        switch (cmd) {
        case BR_REPLY: // 接收SM的响应
            {
                binder_transaction_data tr;
                err = mIn.read(&tr, sizeof(tr));
                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);
                    } 
                }      
        }
    }
}

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    binder_write_read bwr;
    bwr.write_size = outAvail;
    bwr.write_buffer = (uintptr_t)mOut.data();
    do {
        // 通过ioctl将数据写入Binder驱动
        ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);
    } while (err == -EINTR);
}

步骤 6:Binder 驱动转发请求到 SM 进程

Binder 驱动接收到 SF 进程的BC_TRANSACTION命令后,根据 handle=0 识别出目标是 SM 进程,唤醒 SM 的主线程,并将请求数据转发给 SM。

步骤 7:SM 主线程处理 Binder 请求(Looper 回调)

SM 的主线程通过 Looper 监听 Binder 驱动 FD 的EVENT_INPUT事件,触发回调处理请求,代码位于native\cmds\servicemanager\main.cpp

复制代码
// native\cmds\servicemanager\main.cpp
int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
    IPCThreadState::self()->handlePolledCommands(); // 处理驱动转发的请求
    return 1;  // 持续监听
}

步骤 8:SM 解析并执行 Binder 命令

SM 的IPCThreadState读取驱动数据并执行命令,最终调用 SM 自身的transact方法,代码位于native\libs\binder\IPCThreadState.cpp

复制代码
// native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::handlePolledCommands()
{
    do {
        result = getAndExecuteCommand();
    } while (mIn.dataPosition() < mIn.dataSize());
    return result;
}

status_t IPCThreadState::getAndExecuteCommand()
{
    talkWithDriver();  // 从Binder驱动读取SF的注册请求
    cmd = mIn.readInt32();   
    result = executeCommand(cmd);  // 执行ADD_SERVICE命令
}

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    // 调用SM的BBinder处理ADD_SERVICE请求
    the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}

步骤 9:BBinder 转发到 onTransact 方法

SM 的BBinder基类将请求转发到onTransact方法,代码位于native\libs\binder\Binder.cpp

复制代码
// native\libs\binder\Binder.cpp
status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    onTransact(code, data, reply, flags);  // 转发到AIDL生成的onTransact
}

步骤 10:AIDL 生成的 onTransact 解析参数

AIDL 工具生成的BnServiceManager::onTransact解析请求参数,并调用 SM 的addService方法,代码位于android/os/IServiceManager.cpp(AIDL 生成):

复制代码
// android/os/IServiceManager.cpp (AIDL工具生成)
BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
    switch (_aidl_code) {
          case BnServiceManager::TRANSACTION_addService:
             android::binder::Status _aidl_status(addService(in_name, in_service, in_allowIsolated, in_dumpPriority));
            _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
            break;
    }
}

步骤 11:SM 完成 SF 服务注册(最终落地)

SM 的addService方法将 SurfaceFlinger 写入服务注册表(mNameToService),完成注册,代码位于native\cmds\servicemanager\ServiceManager.cpp

复制代码
// native\cmds\servicemanager\ServiceManager.cpp
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
    // 覆盖已有服务(如果存在),将SF写入SM的服务注册表
    mNameToService[name] = Service {
        .binder = binder,  
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    };
    return Status::ok();
}

七、总结

Android ServiceManager 作为 Binder 通信的核心枢纽,其设计和实现有以下关键特点:

  1. 极简的线程模型:摒弃 Binder 线程池,仅通过单线程 + Looper 监听 FD 事件,保证轻量和高效;
  2. Binder 上下文管理器:作为 Binder 通信的根节点,句柄固定为 0,所有服务查询 / 注册都从 SM 开始;
  3. 双 FD 监听机制:通过 Binder 驱动 FD 处理服务注册 / 查询命令,通过定时器 FD 检测客户端连接状态;
  4. AIDL 驱动的功能映射:基于 AIDL 生成的 Bn/BpServiceManager,将 Binder 命令转换为具体的服务管理操作;
  5. 完整的 Binder 链路:以 SurfaceFlinger 注册为例,客户端请求经 Binder 驱动转发到 SM,最终落地到服务注册表,形成闭环。

SM 的设计充分体现了 Android 系统 "核心组件极简、高效" 的原则,作为系统服务的 "注册表",它的稳定性和高效性直接决定了整个 Android 系统 Binder 通信的正常运行。

Android Binder 详解

Android Binder 详解(2)

Android Binder 详解(3)

Android Binder 详解(4) Binder 线程池

Android Binder详解【5】 ServiceManager

Android Binder 详解(6) Binder 客户端的创建

相关推荐
Ya-Jun1 天前
Android 扫雷游戏项目设计报告
android·游戏
_李小白1 天前
【Android 性能分析】第五天:Perfetto UI分析CPU
android·ui
MindCareers1 天前
Beta Sprint Day 1-2: Alpha Issue Fixes Initiated + Mobile Project Setup
android·c语言·数据库·c++·qt·sprint·issue
龚礼鹏1 天前
Android应用程序 c/c++ 崩溃排查流程三——ndk-stack工具使用
android
zhengfei6111 天前
CVE-2025-13156 - Vitepos WooCommerce 的销售(POS) 系统漏洞
android
奥陌陌1 天前
自定义view, 图片右上角显示数字
android
TheNextByte11 天前
将照片从Mac传输到Android 7 种可行方法
android·macos·gitee
青莲8431 天前
Java并发编程基础与进阶(线程·锁·原子类·通信)
android·前端·面试
2509_940880221 天前
MySQL Workbench菜单汉化为中文
android·数据库·mysql