同样以 Media 为例,讲解如何获取服务。
类图在注册服务那一节已经讲解,不再过多赘述。
1 获取 Media 服务
路径在 frameworks/av/media/libmedia/IMediaDeathNotifier.cpp,这个是 Android 媒体框架中获取 MediaPlayerService 的统一入口。
例如一个媒体客户端想获取到 Media 服务,那么就要这样:sp<IMediaPlayerService> service = IMediaDeathNotifier::getMediaPlayerService();
如下:
// 获取 MediaPlayerService 的静态成员函数
// 这是客户端获取媒体播放服务的统一入口点
IMediaDeathNotifier::getMediaPlayerService()
{
// 输出 verbose 级别日志,用于调试跟踪
ALOGV("getMediaPlayerService");
// 创建线程安全锁,使用 RAII 模式确保锁在作用域结束时自动释放
// sServiceLock 是静态互斥锁,保护共享资源 sMediaPlayerService
Mutex::Autolock _l(sServiceLock);
// 单例模式:检查服务代理是否已经创建
// sMediaPlayerService 是静态成员变量,存储创建的服务代理
if (sMediaPlayerService == 0) {
// 获取 ServiceManager 的代理对象
// ServiceManager 是 Android 系统的"服务管家",管理所有系统服务的注册表
sp<IServiceManager> sm = defaultServiceManager();
// 从 ServiceManager 获取 MediaPlayerService 的 Binder 代理
// waitForService 是同步调用,会阻塞直到服务可用
// "media.player" 是 MediaPlayerService 注册时使用的服务名称
sp<IBinder> binder = sm->waitForService(String16("media.player"));
// 检查是否成功获取服务代理
// 如果服务不可用或获取失败,返回空指针
if (binder == nullptr) {
return nullptr;
}
// 创建死亡通知器(DeathNotifier)的单例实例
// DeathNotifier 继承自 IBinder::DeathRecipient,用于监听服务进程的死亡事件
// 只在首次调用时创建,所有客户端共享同一个实例
if (sDeathNotifier == NULL) {
sDeathNotifier = new DeathNotifier();
}
// 将死亡通知器绑定到服务的 Binder 对象
// 当 MediaPlayerService 进程异常退出时:
// 1. Binder 驱动会检测到死亡事件
// 2. 触发 DeathNotifier::binderDied() 回调
// 3. 清理失效的服务代理并通知所有客户端
binder->linkToDeath(sDeathNotifier);
// 使用 interface_cast 将通用的 IBinder 转换为具体的 IMediaPlayerService 接口
// 实际创建的是 BpMediaPlayerService(代理类),提供类型安全的方法调用
// 转换后可以像调用本地方法一样调用远程服务方法
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);
}
// 错误检查:如果服务代理仍然为空,输出错误日志
ALOGE_IF(sMediaPlayerService == 0, "no media player service!?");
// 返回 IMediaPlayerService 的智能指针
// 调用者可以使用它调用服务方法,如 create(), setDataSource() 等
// 智能指针自动管理引用计数,防止内存泄漏
return sMediaPlayerService;
}
首先就还是获取到 ServiceManager,然后通过 ServiceManager 获取到我们需要的 "media.player" 服务。
2 waitForService
接下来看看 sm->waitForService(String16("media.player")) 这个是怎么获取到的。
路径是在 frameworks/native/libs/binder/IServiceManager.cpp。
sp<IBinder> CppBackendShim::waitForService(const String16& name16) {
// 内部 Waiter 类,服务注册成功之后的回调,用于唤醒等待的进程。
class Waiter : public android::os::BnServiceCallback {
Status onRegistration(const std::string& /*name*/,
const sp<IBinder>& binder) override {
std::unique_lock<std::mutex> lock(mMutex);
mBinder = binder;
lock.unlock();
// Flushing here helps ensure the service's ref count remains accurate
IPCThreadState::self()->flushCommands();
mCv.notify_one();
return Status::ok();
}
public:
sp<IBinder> mBinder;
std::mutex mMutex;
std::condition_variable mCv;
};
// Simple RAII object to ensure a function call immediately before going out of scope
class Defer {
public:
explicit Defer(std::function<void()>&& f) : mF(std::move(f)) {}
~Defer() { mF(); }
private:
std::function<void()> mF;
};
const std::string name = String8(name16).c_str();
// 首次尝试获取服务
sp<IBinder> out;
if (Status status = realGetService(name, &out); !status.isOk()) {
// status nok,代表 sm 有问题。返回 null
ALOGW("Failed to getService in waitForService for %s: %s", name.c_str(),
status.toString8().c_str());
sp<ProcessState> self = ProcessState::selfOrNull();
if (self && 0 == self->getThreadPoolMaxTotalThreadCount()) {
ALOGW("Got service, but may be racey because we could not wait efficiently for it. "
"Threadpool has 0 guaranteed threads. "
"Is the threadpool configured properly? "
"See ProcessState::startThreadPool and "
"ProcessState::setThreadPoolMaxThreadCount.");
}
return nullptr;
}
if (out != nullptr) return out; // 服务已存在
// 创建 Waiter 对象,用于接收回调,然后注册通知
sp<Waiter> waiter = sp<Waiter>::make();
if (Status status = mUnifiedServiceManager->registerForNotifications(name, waiter);
!status.isOk()) {
ALOGW("Failed to registerForNotifications in waitForService for %s: %s", name.c_str(),
status.toString8().c_str());
return nullptr;
}
Defer unregister([&] { mUnifiedServiceManager->unregisterForNotifications(name, waiter); });
// 无限循环,获取服务
while(true) {
{
// It would be really nice if we could read binder commands on this
// thread instead of needing a threadpool to be started, but for
// instance, if we call getAndExecuteCommand, it might be the case
// that another thread serves the callback, and we never get a
// command, so we hang indefinitely.
// 等待通知,直到获得了有效的 Binder 对象或者超时
std::unique_lock<std::mutex> lock(waiter->mMutex);
waiter->mCv.wait_for(lock, 1s, [&] {
return waiter->mBinder != nullptr;
});
if (waiter->mBinder != nullptr) return waiter->mBinder;
}
sp<ProcessState> self = ProcessState::selfOrNull();
ALOGW("Waited one second for %s (is service started? Number of threads started in the "
"threadpool: %zu. Are binder threads started and available?)",
name.c_str(), self ? self->getThreadPoolMaxTotalThreadCount() : 0);
// Handle race condition for lazy services. Here is what can happen:
// - the service dies (not processed by init yet).
// - sm processes death notification.
// - sm gets getService and calls init to start service.
// - init gets the start signal, but the service already appears
// started, so it does nothing.
// - init gets death signal, but doesn't know it needs to restart
// the service
// - we need to request service again to get it to start
if (Status status = realGetService(name, &out); !status.isOk()) {
ALOGW("Failed to getService in waitForService on later try for %s: %s", name.c_str(),
status.toString8().c_str());
return nullptr;
}
if (out != nullptr) return out;
}
}
这个代码是怎么获取通知的呢,主要流程是这样的。
首先定义一个 Waiter 类,他就是一个回调接收器,用来接收需要等待的那个服务是否已经注册的通知。然后向 sm 注册监听,就是让 sm 检测需要的服务是否已经注册,如果已经注册则回调 Waiter 对象。然后通过参数将服务 IBinder 传递了过来。最后通过 mCv.wait_for 来返回获得的服务。
如果等待超时,会使用 realGetService 来主动获取一次。
流程图如下:

3 registerForNotifications
我们来继续看一下 mUnifiedServiceManager->registerForNotifications(name, waiter) 注册通知的方法。
路径在:frameworks/native/cmds/servicemanager/ServiceManager.cpp
中间其实还经过 IServiceManager.cpp → CppBackendShim::registerForNotifications(),客户端永远不能直接调用 ServiceManager 进程里的代码,必须经过一层代理中转,中间还经过 Binder 驱动,是通过 AIDL 实现的。不过此处不过多赘述了。
Status ServiceManager::registerForNotifications(
const std::string& name, const sp<IServiceCallback>& callback) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
// 获取调用者身份,并进行权限检查
auto ctx = mAccess->getCallingContext();
// TODO(b/338541373): Implement the notification mechanism for services accessed via
// IAccessor.
std::optional<std::string> accessorName;
if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
return status;
}
// 隔离应用检查
// note - we could allow isolated apps to get notifications if we
// keep track of isolated callbacks and non-isolated callbacks, but
// this is done since isolated apps shouldn't access lazy services
// so we should be able to use different APIs to keep things simple.
// Here, we disallow everything, because the service might not be
// registered yet.
if (is_multiuser_uid_isolated(ctx.uid)) {
return Status::fromExceptionCode(Status::EX_SECURITY, "isolated app");
}
// 服务名合法性检查
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.");
}
// 空指针检查
if (callback == nullptr) {
return Status::fromExceptionCode(Status::EX_NULL_POINTER, "Null callback.");
}
// 死亡通知注册
if (OK !=
IInterface::asBinder(callback)->linkToDeath(
sp<ServiceManager>::fromExisting(this))) {
ALOGE("%s Could not linkToDeath when adding %s", ctx.toDebugString().c_str(), name.c_str());
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "Couldn't link to death.");
}
// 存储 callback
mNameToRegistrationCallback[name].push_back(callback);
// 即时回调
if (auto it = mNameToService.find(name); it != mNameToService.end()) {
const sp<IBinder>& binder = it->second.binder;
// never null if an entry exists
CHECK(binder != nullptr) << name;
callback->onRegistration(name, binder);
}
return Status::ok();
}
重点在最后的即时回调部分,首先获取查找服务是否已存在,mNameToService 就是个 map,这个在注册服务的时候讲过,从这里获取服务。
如果存在,就取出 binder,然后检查一下 binder 是否为空,最后触发回调,也就是 onRegistration。
如果不存在,则什么都不做,等待 addService 那边进行通知。
4 realGetService
最后再来看一下 realGetService 是怎么实现的吧,这个在 waitForService 中出现了两次,第一次是快速路径,也就是先主动向 ServiceManager 查一次这个服务是否存在,如果服务已存在就直接返回,不需要再查询了。
另一次是出现在最后,也就是等待超时之后。再主动查询一次,是用来兜底的。
路径在 frameworks/native/libs/binder/IServiceManager.cpp
virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
Service service;
Status status = mUnifiedServiceManager->getService2(name, &service);
auto serviceWithMetadata = service.get<Service::Tag::serviceWithMetadata>();
*_aidl_return = serviceWithMetadata.service;
return status;
}
可以看到是通过 mUnifiedServiceManager->getService2(name, &service) 来发起的查询,其实和上面一样,也是通过 AIDL 来实现的,最终调用的是 frameworks/native/cmds/servicemanager/ServiceManager.cpp 路径的 getService2
Status ServiceManager::getService2(const std::string& name, os::Service* outService) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
*outService = tryGetService(name, true);
// returns ok regardless of result for legacy reasons
return Status::ok();
}
这个很简单就是通过 tryGetService 来查询服务是否存在,但是不管存不存在都会返回 ok。
服务不存在不是错误,结果保存在 outService 中了,如果为 null 就是不存在。
os::Service ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
// 检查是否有 accessor 代理
std::optional<std::string> accessorName;
#ifndef VENDORSERVICEMANAGER
accessorName = getVintfAccessorName(name);
#endif
if (accessorName.has_value()) {
// 通过 accessor 代理访问的服务
auto ctx = mAccess->getCallingContext();
if (!mAccess->canFind(ctx, name)) {
return os::Service::make<os::Service::Tag::accessor>(nullptr);
}
return os::Service::make<os::Service::Tag::accessor>(
tryGetBinder(*accessorName, startIfNotFound).service);
} else {
// 普通服务 —— 绝大多数情况走这里
return os::Service::make<os::Service::Tag::serviceWithMetadata>(
tryGetBinder(name, startIfNotFound));
}
}
再往下就是 tryGetBinder 了。
os::ServiceWithMetadata ServiceManager::tryGetBinder(const std::string& name,
bool startIfNotFound) {
SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));
auto ctx = mAccess->getCallingContext();
sp<IBinder> out;
Service* service = nullptr;
if (auto it = mNameToService.find(name); it != mNameToService.end()) {
service = &(it->second);
if (!service->allowIsolated && is_multiuser_uid_isolated(ctx.uid)) {
LOG(WARNING) << "Isolated app with UID " << ctx.uid << " requested '" << name
<< "', but the service is not allowed for isolated apps.";
return os::ServiceWithMetadata();
}
out = service->binder;
}
if (!mAccess->canFind(ctx, name)) {
return os::ServiceWithMetadata();
}
if (!out && startIfNotFound) {
tryStartService(ctx, name);
}
if (out) {
// Force onClients to get sent, and then make sure the timerfd won't clear it
// by setting guaranteeClient again. This logic could be simplified by using
// a time-based guarantee. However, forcing onClients(true) to get sent
// right here is always going to be important for processes serving multiple
// lazy interfaces.
service->guaranteeClient = true;
CHECK(handleServiceClientCallback(2 /* sm + transaction */, name, false));
service->guaranteeClient = true;
}
os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
serviceWithMetadata.service = out;
serviceWithMetadata.isLazyService =
service ? service->dumpPriority & FLAG_IS_LAZY_SERVICE : false;
return serviceWithMetadata;
}
太多了,先只看是怎么查找服务的吧
sp<IBinder> out;
Service* service = nullptr;
if (auto it = mNameToService.find(name); it != mNameToService.end()) {
service = &(it->second);
// allowIsolated 是否允许隔离应用访问,大多都不行
if (!service->allowIsolated && is_multiuser_uid_isolated(ctx.uid)) {
LOG(WARNING) << "Isolated app with UID " << ctx.uid << " requested '" << name
<< "', but the service is not allowed for isolated apps.";
return os::ServiceWithMetadata();
}
out = service->binder;
}
前面准备了两个变量,out 一个空指针,用来存放结果。service 一个指针,用来指向 mNameToService 中的 Service 条目。
有两个的原因是因为 out 是为了返回给客户端的结果,service 是后面需要用到,例如创建客户端回调。
可以看到其实就是 map 查询,还是 mNameToService,如果存在使用 out 来保存结果。
流程图:

5 总结
获取服务的流程不复杂,简单概括就是:客户端 -> SM 插 map -> 有就返回,没有就注册回调等通知 -> 回调或超时兜底再查一次。
