1 概述
学习 Binder 机制,我们先从注册服务开始。所谓注册服务,就是指 Server 将自己的 Binder 实体通过一次 IPC 通信,在 ServiceManager 那里完成登记。
以 Media 服务注册进行说明。
1.1 Media 服务注册
Media 的入口函数是 main_mediaserver.cpp 中的 main() 方法。在 Android 早期,路径是:/frameworks/base/media/mediaserver/main_mediaserver.cpp。
从 Android 7 开始路径迁移至 /frameworks/av/media/mediaserver/main_mediaserver.cpp。
namespace {
constexpr int kCodecThreadPoolCount = 16;
// This is the default thread count for binder thread pool
// if the thread count is not configured.
constexpr int kDefaultBinderThreadPoolCount = 15;
}; // anonymous
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
// 注册前准备 和 获取 ServiceManager 代理。
// 打开 /dev/binder 驱动,完成 Binder 通信的初始化
sp<ProcessState> proc(ProcessState::self());
// 通过 Binder 驱动获取到 ServiceManager 的代理对象
sp<IServiceManager> sm(defaultServiceManager());
ALOGI("ServiceManager: %p", sm.get());
// 服务注册 的核心调用
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
// 设置 Binder 线程池
bool aidl = ::android::IsCodec2AidlHalSelected();
if (!aidl) {
::android::hardware::configureRpcThreadpool(kCodecThreadPoolCount, false);
} else {
ABinderProcess_setThreadPoolMaxThreadCount(
kCodecThreadPoolCount + kDefaultBinderThreadPoolCount);
}
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
流程说明:
- 打开 /dev/binder 驱动,获取 ProcessState 对象
- 获取 ServiceManager 的代理对象
- 注册服务,(Android 6 的时候,需要注册多种服务,而 Android 16 只需要注册两个即可)
- 设置 Binder 线程池
本文的重点是讲解 Native 层服务注册的过程。
1.2 类图
在 Native 层的服务,以 Media 为例,来讲解服务注册过程,下面是 Media 的整个类关系图。
- 蓝色代表的是注册 MediaPlayerService 服务所涉及的类
- 绿色代表的是 Binder 架构中与 Binder 驱动通信过程中的最为核心的两个类;
- 紫色代表的是注册服务和获取服务的公共接口/父类;
理解这个类图:
- 首先 RefBase 相关的先忽略,这个是引用计数管理器,BBinder 和各类具体服务都继承自它,Android 的智能指针 sp 和 wp 才能自动管理对象的生命周期。但是对分析流程无用,只要知道这个是干啥的即可。
- 然后从 Interface 来看,这个是接口层,下面的 IMediaPlayerService 就是具体的 Media 的服务接口。后续分成了两个接口,一个是客户端接口(客户端代理),一个是服务端接口(服务端骨架)。
- BpInterface 客户端模板类,负责实现代理功能,下面的 BpMediaPlayerService 就是具体的客户端代理实现。里面是持有 BpBinder 的。
- BnInterface 服务端模板类,负责实现骨架功能,类似的,BnMediaPlayerService 就是具体的服务端骨架实现。里面是继承 BBinder 的。
- 接下来看右边部分,IBinder 是 Android Binder IPC 机制的核心接口。
- 下面分为两个部分,服务端与客户端,都继承了 IBinder,分别是 BBinder 和 BpBinder。BBinder 是真正的 Binder 实体,为本地对象。BpBinder 是 Binder 的代理,为远程句柄。
- ProcessState 进程级单例,管理与驱动的连接,每个进程一个,负责“连上 Binder 驱动”。IPCThreadState 线程级单例,管理 IPC 收发与线程池,每个线程一个,负责“真正收发 Binder 数据”。几乎所有 Binder 调用最终都会经过它们。
在新架构中,其实增加了 CppBackendShim 兼容层,这个层的引入并没有废除这套基础设计,而是叠加在它之上,暂时不做分析。
1.3 时序图
接下来看看时序图吧,来说明一下 Media 服务启动过程是如何向 ServiceManager 注册服务的。
2 ProcessState
从 1.1 可以看出,是先获取的 ProcessState 对象,所以我们从这里先看起。
涉及到的文件是 ProcessState.cpp,路径在 frameworks/native/libs/binder
2.1 ProcessState::self
sp<ProcessState> ProcessState::self()
{
return init(kDefaultDriver, false /*requireDefault*/);
}
首先,使用的是 self 方法,self 又调用了私有的 init 方法,并传递了参数 kDefaultDriver,通常是 /dev/binder)和 false 作为 requireDefault 参数。
sp<ProcessState> ProcessState::init(const char* driver, bool requireDefault) {
ALOGI("ProcessState::init called with driver=%s, requireDefault=%d",
driver ? driver : "nullptr", requireDefault);
// 分支1:传入 driver 为 nullptr,直接返回已有的单例(如果有)
if (driver == nullptr) {
ALOGI("ProcessState::init: driver is null, attempting to return existing instance");
std::lock_guard<std::mutex> l(gProcessMutex);
if (gProcess) {
ALOGI("ProcessState::init: existing gProcess found (%p), verifying fork status", gProcess.get());
verifyNotForked(gProcess->mForked);
} else {
ALOGI("ProcessState::init: no existing gProcess, returning nullptr");
}
return gProcess;
}
// 分支2:首次初始化,使用 std::call_once 确保只执行一次
[[clang::no_destroy]] static std::once_flag gProcessOnce;
std::call_once(gProcessOnce, [&](){
ALOGI("ProcessState::init: first time initialization for driver=%s", driver);
// 2.1 检查驱动文件是否可访问
if (access(driver, R_OK) == -1) {
ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
driver = "/dev/binder";
} else {
ALOGI("ProcessState::init: driver %s is accessible", driver);
}
// 2.2 检查 vndbinder 相关的服务是否启用
if (0 == strcmp(driver, "/dev/vndbinder") && !isVndservicemanagerEnabled()) {
ALOGE("vndservicemanager is not started on this device, you can save resources/threads "
"by not initializing ProcessState with /dev/vndbinder.");
}
// 2.3 注册 fork 处理函数
int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork,
ProcessState::childPostFork);
if (ret != 0) {
ALOGE("pthread_atfork error %s", strerror(ret));
LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret));
} else {
ALOGI("ProcessState::init: pthread_atfork handlers installed successfully");
}
// 2.4 加锁创建 gProcess 实例
{
std::lock_guard<std::mutex> l(gProcessMutex);
gProcess = sp<ProcessState>::make(driver);
ALOGI("ProcessState::init: gProcess created (%p) with driver=%s",
gProcess.get(), driver);
}
});
// 分支3:requireDefault 检查
if (requireDefault) {
ALOGI("ProcessState::init: requireDefault is true, checking driver consistency");
if (gProcess->getDriverName() != driver) {
ALOGE("ProcessState was already initialized with %s, can't initialize with %s.",
gProcess->getDriverName().c_str(), driver);
LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
"ProcessState was already initialized with %s,"
" can't initialize with %s.",
gProcess->getDriverName().c_str(), driver);
}
}
// 最终检查 fork 状态
verifyNotForked(gProcess->mForked);
ALOGI("ProcessState::init: returning gProcess (%p) with driver=%s",
gProcess.get(), gProcess->getDriverName().c_str());
return gProcess;
}
init 方法中涉及到的东西就很多了,Android 6 逻辑会简单很多,Android 16 在安全、容错和灵活性上做了大量增强。核心目标是一致的:确保每个进程只创建一个 ProcessState 单例。
2.2 ProcessState 初始化
我们来看下是怎么进行初始化的,也就是 gProcess = sp::make(driver) 这个方法。这里的 make 并不是 ProcessState 的方法,而是 C++ 智能指针 sp 提供的一个静态工厂方法。这个方法的最终动作就是调用 ProcessState 的构造方法,我们暂时不关心是怎么实现的。
来看 ProcessState 的构造方法:
ProcessState::ProcessState(const char* driver)
// ---- 初始化列表:为所有成员变量赋予安全的初始值 ----
: mDriverName(String8(driver)), // 保存驱动名称(如 "/dev/binder")
mDriverFD(-1), // 驱动文件描述符先设为 -1(无效值)
mVMStart(MAP_FAILED), // 共享内存映射起始地址先设为 MAP_FAILED(无效)
mExecutingThreadsCount(0), // 当前正在执行 binder 事务的线程数,初始为 0
mMaxThreads(DEFAULT_MAX_BINDER_THREADS), // 向驱动申请的最大 binder 线程数(默认 15)
mCurrentThreads(0), // 当前进程中的 binder 线程总数,初始 0
mKernelStartedThreads(0), // 由内核启动的 binder 线程计数,初始 0
mStarvationStartTime(never()), // 线程饥饿计时起点,初始为“永不”表示未饥饿
mForked(false), // 标记进程是否经历过 fork,初始为 false
mThreadPoolStarted(false), // 标记线程池是否已启动,初始为 false
mThreadPoolSeq(1), // 线程池编号,用于生成线程名
mCallRestriction(CallRestriction::NONE) // 调用限制策略,初始为“无限制”
{
String8 error; // 用于保存 open_driver 失败时的错误信息
// 1. 尝试打开 Binder 驱动,并进行协议协商与配置
unique_fd opened = open_driver(driver, &error);
// 2. 如果驱动打开成功,立即建立内存映射(mmap)
if (opened.ok()) {
// mmap 用于在进程的虚拟地址空间中预留一块区域,
// 让 Binder 驱动可以直接将其他进程发来的数据写入此处,减少拷贝。
mVMStart = mmap(nullptr,
BINDER_VM_SIZE, // 映射大小(约 1MB - 2页)
PROT_READ, // 只允许进程读取(驱动拥有写入权限)
MAP_PRIVATE | MAP_NORESERVE, // 私有映射,不保留 swap 空间
opened.get(), // 驱动文件描述符
0);
if (mVMStart == MAP_FAILED) {
// 如果映射失败,记录错误日志,并且关闭已打开的驱动文件描述符
ALOGE("Using %s failed: unable to mmap transaction memory.", driver);
opened.reset(); // 关闭 fd 并置为无效
mDriverName.clear(); // 清除驱动名称,表示初始化失败
}
}
// 3. 根据平台宏,决定驱动打开失败时的处理策略
#if defined(EXPECT_BINDER_OPEN_SUCCESS)
// Android / Fuchsia 等平台:驱动必须打开成功,否则视为致命错误,直接终止进程。
LOG_ALWAYS_FATAL_IF(!opened.ok(),
"Binder driver '%s' could not be opened. Error: %s. Terminating.",
driver, error.c_str());
#else
// 其他平台:驱动打开失败仅记录错误,进程可能降级运行(后续功能可能异常)。
if (!opened.ok()) {
ALOGE("Binder driver '%s' could not be opened. Error: %s. There may be future issues.",
driver, error.c_str());
}
#endif
// 4. 保存可用的驱动文件描述符,供后续所有 Binder 通信使用
if (opened.ok()) {
// 从 unique_fd 中释放所有权,将原始的 fd 值赋给 mDriverFD
mDriverFD = opened.release();
}
// 5. 如果需要 Binder 事件观察者(调试用),则创建它
#ifdef BINDER_WITH_OBSERVERS
mBinderObserver = std::make_unique<BinderObserver>();
#endif
}
2.3 open_driver
open_driver 负责打开 Binder 驱动并完成所有必要的初始化协商。
static unique_fd open_driver(const char* driver, String8* error) {
// 1. 打开 Binder 驱动设备文件
// O_RDWR : 可读可写,用于收发 Binder 事务
// O_CLOEXEC: 进程执行新程序时自动关闭该 fd,防止泄露
auto fd = unique_fd(open(driver, O_RDWR | O_CLOEXEC));
if (!fd.ok()) {
// 打开失败,记录详细错误信息到 error 中,并返回空 unique_fd
error->appendFormat("%d (%s) Opening '%s' failed", errno, strerror(errno), driver);
return {};
}
// 2. 协商 Binder 协议版本
int vers = 0;
int result = ioctl(fd.get(), BINDER_VERSION, &vers);
if (result == -1) {
// ioctl 调用本身失败(比如驱动不支持此命令)
error->appendFormat("%d (%s) Binder ioctl to obtain version failed", errno,
strerror(errno));
return {};
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
// 用户空间库与内核驱动的协议版本不匹配,无法协同工作
error->appendFormat("Binder driver protocol(%d) does not match user space protocol(%d)! "
"ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
return {};
}
// 3. 设置进程允许的最大 Binder 线程数
// 告诉驱动本进程最多能有多少个线程同时处理 Binder 事务
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd.get(), BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
// 4. 开启单向(oneway)调用垃圾检测
// 该功能用于检测是否有进程滥用 oneway 调用导致事务堆积
uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
result = ioctl(fd.get(), BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
if (result == -1) {
ALOGE_IF(ProcessState::isDriverFeatureEnabled(
ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION),
"Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
}
// 返回已配置好的文件描述符
return fd;
}
open_driver 作用是打开 /dev/binder 设备,设定 binder 支持的最大线程数。关于 binder 驱动的相应方法之后会再看。
ProcessState 采用单例模式,保证每一个进程都只打开一次 Binder Driver。
2.4 小结
通过上面的分析,ProcessState 的初始化过程调用链就可以梳理出来了。
main()
→ ProcessState::self()
→ ProcessState::init(kDefaultDriver, false)
→ sp<ProcessState>::make(driver)
→ ProcessState::ProcessState(driver)
→ open_driver(driver, &error)
→ mmap(nullptr, BINDER_VM_SIZE, ...)
→ mDriverFD = opened.release()
main() 作为进程入口,首先调用 ProcessState::self() 来初始化 Binder 通信基础设施。
self() 是获取进程单例的标准入口,它不做实际工作,直接把请求委托给 ProcessState::init(kDefaultDriver, false),其中 kDefaultDriver 通常是 /dev/binder。
init 是初始化的逻辑核心,它使用 std::call_once 机制确保无论多少线程同时调用,真正的构造逻辑只执行一次,同时它还负责检查进程是否经历过 fork 以确保安全。在确认可以创建实例后,init 调用 sp::make(driver),这是智能指针 sp 提供的工厂方法,相当于在堆上执行 new ProcessState(driver) 并立即用 sp 接管其生命周期。
接下来进入 ProcessState 的构造函数 ProcessState::ProcessState(driver),它先将所有成员变量初始化为安全的默认值,然后调用 open_driver(driver, &error) 打开 Binder 驱动设备文件,依次完成文件打开、协议版本协商、最大线程数设置以及 oneway 调用检测开启这四个关键步骤。
驱动打开成功后,构造函数接着调用 mmap(nullptr, BINDER_VM_SIZE, ...) 在进程的虚拟地址空间中预留一块共享内存区域,让 Binder 驱动能够直接将跨进程事务数据写入此处,从而避免数据拷贝、提升通信效率。
最后,构造函数执行 mDriverFD = opened.release(),将临时对象中已打开的驱动文件描述符转移到成员变量 mDriverFD 中永久保存,供后续所有 Binder 操作使用。
至此,ProcessState 初始化完成,返回一个指向进程唯一实例的智能指针,进程已经具备完整的 Binder 通信能力,可以开始向 ServiceManager 注册服务或与其他进程进行 IPC 通信了。
3 服务注册
如何获取 ServiceManager 的之后再讲解。
- [X] 获取 ServiceManager
接下来进入到服务注册的流程,也就是下面这些
MediaPlayerService::instantiate();
ResourceManagerService::instantiate();
registerExtensions();
3.1 instantiate
这个就是一个静态方法嘛,例如 MediaPlayerService 的,路径在 frameworks/av/media/libmediaplayerservice 下。
MediaPlayerService.cpp
void MediaPlayerService::instantiate() {
defaultServiceManager()->addService(
String16("media.player"), new MediaPlayerService());
}
它首先通过 defaultServiceManager() 返回 ServiceManager 的代理对象,这个代理对象实现了 IServiceManager 接口,内部使用 CppBackendShim 作为兼容层。
在这个方法的执行过程中,会触发创建 ProcessState 对象和 BpBinder 对象(如果已经存在,则不创建,直接复用)。代理对象继承自 BpInterface,而 BpInterface 又继承自 BpRefBase。BpRefBase 在构造时需要持有一个 BpBinder 对象,要拿到这个 BpBinder,最终会调用到 ProcessState::self()。
然后代理对象调用 addService 方法,把服务名和服务对象传进去。在内部,这个调用被 CppBackendShim 拦截并转发给新的统一服务管理器完成注册。
3.2 addService
继续往下看,addService 是怎么实现的。路径在 frameworks/native/libs/binder/IServiceManager.cpp
为啥知道是这里?和 defaultServiceManager() 的实现有关,返回的就是 IServiceManager 对象,具体类型就是 CppBackendShim。
status_t CppBackendShim::addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated, int dumpsysPriority) {
Status status = mUnifiedServiceManager->addService(String8(name).c_str(), service,
allowIsolated, dumpsysPriority);
return status.exceptionCode();
}
这里就是通过 CppBackendShim 将老接口的调用,原封不动地转发给新架构的“统一服务管理器”。
在 Android 11 之前,是通过 BpServiceManager 直接进行 IPC 的。
现在的逻辑和 3.1 类似,调用的是 BackendUnifiedServiceManager 的方法。
接下来这个 addService 是在,frameworks/native/libs/binder/BackendUnifiedServiceManager.cpp
Status BackendUnifiedServiceManager::addService(const ::std::string& name,
const sp<IBinder>& service,
bool allowIsolated,
int32_t dumpPriority) {
// 检查真正的 ServiceManager 代理是否存在
// 如果系统正常启动,servicemanager 进程会初始化这个指针
if (mTheRealServiceManager) {
// 将注册请求转发给真正的 ServiceManager 进程
// 这一调用会通过 Binder 跨进程到达 ServiceManager.cpp 中的 addService 方法
Status status =
mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority);
// 检查是否满足缓存条件:
// 1. 全局缓存开关 kUseCacheInAddService 为 true(默认开启)
// 2. 实例级缓存开关 mEnableAddServiceCache 为 true(默认 true)
// 3. 注册操作成功(status.isOk())
if (kUseCacheInAddService && mEnableAddServiceCache && status.isOk()) {
// 将新注册的服务信息写入本地缓存,方便后续 getService 查询时直接返回,
// 避免再次跨进程调用,提升性能
return updateCache(name, service,
dumpPriority & android::os::IServiceManager::FLAG_IS_LAZY_SERVICE);
}
// 不满足缓存条件时,直接返回来自 servicemanager 的注册结果
return status;
}
// 如果 mTheRealServiceManager 为空(servicemanager 未就绪),
// 则返回“不支持的操作”错误,并附带错误信息
return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
kUnsupportedOpNoServiceManager);
}
这里有调用了 mTheRealServiceManager->addService 了,又一个 addService,这里使用的是 AIDL,会调用代理方法,被转发给自动生成的 BpServiceManager 代理类。最终就是调用到 ServiceManager.cpp 里的 addService 方法。
- [ ] AIDL 讲解
路径在:frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder,
bool allowIsolated, int32_t dumpPriority) {
// 性能追踪宏,用于 systrace/perfetto 抓取
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
// 获取调用者的身份上下文(UID、PID、SID 等)
auto ctx = mAccess->getCallingContext();
// --- 安全检查 1:应用 UID 不允许注册系统服务 ---
if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
return Status::fromExceptionCode(Status::EX_SECURITY, "App UIDs cannot add services.");
}
// --- 安全检查 2:检查调用者是否有权限添加此服务 ---
// 会校验 SELinux 权限以及 allowed 列表等
std::optional<std::string> accessorName;
if (auto status = canAddService(ctx, name, &accessorName); !status.isOk()) {
return status;
}
// --- 参数校验:binder 对象不能为空 ---
if (binder == nullptr) {
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Null binder.");
}
// --- 参数校验:服务名必须是合法格式 ---
if (!isValidServiceName(name)) {
ALOGE("%s Invalid service name: %s", ctx.toDebugString().c_str(), name.c_str());
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name.");
}
#ifndef VENDORSERVICEMANAGER
// --- VINTF 兼容性检查(仅系统 servicemanager)---
// 确保服务在 VINTF manifest 中正确声明
if (!meetsDeclarationRequirements(ctx, binder, name)) {
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "VINTF declaration error.");
}
#endif // !VENDORSERVICEMANAGER
// 如果 dump 优先级没有设置任何有效位,打一个警告
if ((dumpPriority & DUMP_FLAG_PRIORITY_ALL) == 0) {
ALOGW("%s Dump flag priority is not set when adding %s", ctx.toDebugString().c_str(),
name.c_str());
}
// --- 注册死亡通知 ---
// 当服务端 binder 死亡时,servicemanager 会收到回调以便自动清理
if (binder->remoteBinder() != nullptr &&
binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
ALOGE("%s Could not linkToDeath when adding %s", ctx.toDebugString().c_str(), name.c_str());
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't linkToDeath.");
}
// --- 处理重复注册 ---
auto it = mNameToService.find(name);
bool prevClients = false;
if (it != mNameToService.end()) {
const Service& existing = it->second;
prevClients = existing.hasClients;
// 如果前后两次注册的 UID 不同,可能是多个服务实例冲突
if (existing.ctx.uid != ctx.uid) {
ALOGW("Service '%s' originally registered from UID %u but it is now being registered "
"from UID %u. Multiple instances installed?",
name.c_str(), existing.ctx.uid, ctx.uid);
}
// 如果前后两次注册的 SELinux SID 不同,同样警告
if (existing.ctx.sid != ctx.sid) {
ALOGW("Service '%s' originally registered from SID %s but it is now being registered "
"from SID %s. Multiple instances installed?",
name.c_str(), existing.ctx.sid.c_str(), ctx.sid.c_str());
}
ALOGI("Service '%s' originally registered from PID %d but it is being registered again "
"from PID %d. Bad state? Late death notification? Multiple instances installed?",
name.c_str(), existing.ctx.debugPid, ctx.debugPid);
}
// --- 核心操作:将服务信息写入全局列表 ---
// 同名服务会被直接覆盖,新服务替换旧服务
mNameToService[name] = Service{
.binder = binder, // 服务的 Binder 实体对象
.allowIsolated = allowIsolated, // 是否允许沙箱应用访问
.dumpPriority = dumpPriority, // dumpsys 优先级
.hasClients = prevClients, // 保留旧的客户端状态
.guaranteeClient = false, // 是否需要通知等待中的客户端
.ctx = ctx, // 注册者的身份上下文
};
// --- 通知正在等待此服务的客户端 ---
// 如果有客户端先调用了 getService 但服务尚未注册,它们会注册回调在此等待
if (auto it = mNameToRegistrationCallback.find(name);
it != mNameToRegistrationCallback.end()) {
// 标记该服务有客户端正在等待
mNameToService[name].guaranteeClient = true;
// 处理服务客户端回调,通知等待者
CHECK(handleServiceClientCallback(2 /* sm + transaction */, name, false));
mNameToService[name].guaranteeClient = true;
// 逐个通知所有注册了回调的客户端
for (const sp<IServiceCallback>& cb : it->second) {
cb->onRegistration(name, binder);
}
}
// 返回成功
return Status::ok();
}
主要看核心的注册操作
mNameToService[name] = Service{
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.hasClients = prevClients,
.guaranteeClient = false,
.ctx = ctx,
};
它把服务名 name(如 "media.player")作为键,将包含服务 Binder 实体、访问权限、优先级等信息的 Service 结构体作为值,存入 servicemanager 进程的全局 map mNameToService 中。
这样就算是登记了,其他进程就可以通过服务名查询到这个 Binder 引用,从而发起远程调用。
3.3 小结
新架构的的路径经过了多层的包装
BpServiceManager::addService()
→ CppBackendShim::addService()
→ BackendUnifiedServiceManager::addService()
→ mTheRealServiceManager->addService() // AIDL 代理
→ Binder 驱动
→ ServiceManager::addService() // 真正的注册
旧架构就直接很多
BpServiceManager::addService()
→ 手动打包 Parcel
→ BpBinder(0)->transact(ADD_SERVICE_TRANSACTION)
→ Binder 驱动
→ servicemanager 进程
可以这么记忆,
- Android 6:服务注册 → 插入全局链表 svclist
- Android 16:服务注册 → 写入全局 map mNameToService