ServiceManager是binder服务的管理者,服务端注册Binder,客户端获取binder都要通过ServiceManager,充当了一个binder路由转发的角色。
ServiceManager是一个独立的进程,在Java层提供了一个ServiceManager的接口类,真正的实现是在ServiceManager进程中
源码位置:frameworks/native/cmds/servicemanager/
主要逻辑实现:main.cpp和ServiceManager.cpp
进程初始化
进程的初始化都在main函数里边,我们逐行分析
frameworks/native/cmds/servicemanager/main.cpp
int main(int argc, char** argv) {
android::base::InitLogging(argv, android::base::KernelLogger);
//binder驱动设备
const char* driver = argc == 2 ? argv[1] : "/dev/binder";
//生成ProcessState
sp<ProcessState> ps = ProcessState::initWithDriver(driver);
//禁用binder线程池,线程池数量设置为0
ps->setThreadPoolMaxThreadCount(0);
//初始化ServiceManager对象
sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
//将manager设置为contextObject,contextObject就是特指ServiceManager为全局管理对象
IPCThreadState::self()->setTheContextObject(manager);
//创建Looper对象,绑定线程,和java层的Looper原理一样
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
//设置Callback
sp<BinderCallback> binderCallback = BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager, binderCallback);
//开启无限循环监听binder驱动的事件消息
while(true) {
looper->pollAll(-1);
}
// should not be reached
return EXIT_FAILURE;
}进程模型
ServiceManager是一个单线程模型,所以没有开启binder线程池
监听binder驱动事件
普通进程开启了binder线程池,然后binder线程通过talkWithDriver陷入binder驱动中,等待binder驱动消息的到来再唤醒,那么serviceManager如何收到binder消息的呢?关键看BinderCallback
class BinderCallback : public LooperCallback {
public:
static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
sp<BinderCallback> cb = sp<BinderCallback>::make();
cb->mLooper = looper;
//将binderfd注册到epoll
int ret = looper->addFd(cb->mBinderFd, Looper::POLL_CALLBACK, Looper::EVENT_INPUT, cb,
nullptr /*data*/);
return cb;
}
......
}addFd函数内部调用的核心函数是
epoll_ctl(mEpollFd.get(), EPOLL_CTL_ADD, fd, &eventItem);当进程调用looper->pollAll(-1);的时候就会发生休眠,pollAll函数内部调用的核心函数是
int Looper::pollInner(int timeoutMillis) {
......
int eventCount = epoll_wait(mEpollFd.get(), eventItems, EPOLL_MAX_EVENTS, timeoutMillis);
......
}
epoll_wait发生阻塞
当有进程发起addService/getService请后,当驱动会写数据到binderFd,epoll_wait 检测到可读事件,唤醒Looper线程
读取binder事件
ServiceMnager线程唤醒
Looper线程被唤醒后,调用handleEvent
int Looper::pollInner(int timeoutMillis) {
......
int callbackResult = response.request.callback->handleEvent(fd, events, data);
......
}然后回到我们上面的callback对象中
class BinderCallback : public LooperCallback {
public:
......
int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
IPCThreadState::self()->handlePolledCommands();
return 1; // Continue receiving callbacks.
}
}handlePolledCommands函数简单调用IPCThreadState::getAndExecuteCommand, 后续的逻辑就和普通进程中的binder线程池读取binder数据一样了
对比Binder线程池的处理方式
所以,Looper的作用是监听Binder驱动的读写事件,如果binder收到对于ServiceManager的事务请求,比如addService,那么looper线程将被唤醒,然后调用IPCThreadState::talkWithDriver去读取驱动的todo队列来处理addService事务,而普通的binder线程池则是先调用talkWithDriver陷入内核休眠,然后todo队列有了事务直接唤醒线程,事情处理完后通过while(true)陷入无限循环中的下一次talkWithDriver等待事务的到来。
Java对外接口
ServiceManager是单独的进程,其他进程要查询/注册binder服务也要发起跨进程通信,他们的接口是什么呢?
以addService为例子在Java层的ServiceManager接口中有这样的调用
public static void addService(String name, IBinder service, boolean allowIsolated,
int dumpPriority) {
try {
getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
} catch (RemoteException e) {
Log.e(TAG, "error in addService", e);
}
}getIServiceManager会返回一个C++层的ServiceManager的binder代理对象
ServiceManager代理对象的获取
private static IServiceManager getIServiceManager() {
// Find the service manager
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
public static IServiceManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
// ServiceManager is never local
return new ServiceManagerProxy(obj);
}
class ServiceManagerProxy implements IServiceManager {
public ServiceManagerProxy(IBinder remote) {
mRemote = remote;
mServiceManager = IServiceManager.Stub.asInterface(this.getNativeServiceManager());
}
public IBinder asBinder() {
return mRemote;
}
public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
throws RemoteException {
mServiceManager.addService(name, service, allowIsolated, dumpPriority);
}
}
从上面的调用链来看,核心函数应该是ServiceManagerProxy构造函数中的
mServiceManager = IServiceManager.Stub.asInterface(this.getNativeServiceManager());那个mRemote对象没用,将来会被删除,这里是基于Android 15的源码,所以看起来还有冗余的代码
getNativeServiceManager返回的就是ServiceManager代理对象,jni将其封装成了BInderProxy
jobject JNICALL Java_android_os_ServiceManagerProxy_getNativeServiceManager(JNIEnv *env,
jobject obj) {
sp<IBinder> service = IInterface::asBinder(
impl::getJavaServicemanagerImplPrivateDoNotUseExceptInTheOnePlaceItIsUsed());
return javaObjectForIBinder(env, service);
}getJavaServicemanagerImplPrivateDoNotUseExceptInTheOnePlaceItIsUsed返回的是一个BackendUnifiedServiceManager对象,而BackendUnifiedServiceManager封装的是BpServiceManager
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
std::call_once(gUSmOnce, []() {
sp<AidlServiceManager> sm = nullptr;
......
// 获取到BpServiceManager
sm = interface_cast<AidlServiceManager>(
ProcessState::self()->getContextObject(nullptr));
gUnifiedServiceManager = sp<BackendUnifiedServiceManager>::make(sm);
});
return gUnifiedServiceManager;
}
AidlServiceManager就是BpServiceManager,getContextObject函数内部直接new BpBinder(0),这个BpBinder作为成员变量mRemote保存到了BpServiceManager。
回到getNativeServiceManager函数中,其中的转换函数IInterface::asBinder(BpServiceManager) 得到的是其成员函数 mRemote即BpBInder(0)对象。
所以,java层拿到了一个指向BpBinder(0)的BinderProxy 代理对象。
BpServiceManager是什么?这得看看C++层的AIDL接口了,它类似java层AIDL生成的Binder.Stub.Proxy类
C++对外接口
ServiceManager作为一个binder来使用,必定有binder代理和binder实体,先看看类图
在Native中,也有一套类似Java层的AIDL接口标准,编译器会自动生成IServiceManager.cpp文件,包含两个类,BpServiceManager和BnServiceManager
main函数中初始化的ServiceManager为binder实体对象,继承自BnServiceManager,定义如下
class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
public:
ServiceManager(std::unique_ptr<Access>&& access);
~ServiceManager();
}客户端的调用栈
从Java层的ServiceManager::addService函数开始
ServiceManager::addService
ServiceManagerProxy::addService
IServiceManager.Stub.Proxy::addService
BinderProxy::transact
//jin调用进入native
android_util_Binder::android_os_BinderProxy_transact
BpBinder::transact
IPCThreadState::transact
IPCThreadState::waitForResponse
//陷入内核调用
IPCThreadState::talkWithDriver
服务端的调用栈
当驱动的指令下来,经过下面的调用栈,最终走到ServiceManager类
IPCThreadState::handlePolledCommands()
IPCThreadState::getAndExecuteCommand()
IPCThreadState::talkWithDriver(bool doReceive)
IPCThreadState::executeCommand(int32_t cmd)
BBinder::transact()
BnServiceManager::onTransact
ServiceManager::addService()
//如果指令是getService,则需要返回,transact走完之后
IPCThreadState::sendReply
IPCThreadState::waitForResponse
IPCThreadState::talkWithDriver
//驱动返回BR_TRANSACTION_COMPLETE结束本次事务
Java的AIDL也有上面类似的调用链,区别是java是从binder线程池开始的,而servicemanager是从主线程looper发起的
服务注册与获取
上面分析了服务的注册/获取的调用栈,接下来看看内部细节
注册
函数定义
ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority)name:binder服务名称
binder:BpBinder对象,内部有一个handle指向Binder实体, handle和binder实体的映射关系是在binder驱动里边完成的
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
......
// Overwrite the old service if it exists
mNameToService[name] = Service{
.binder = binder,
.allowIsolated = allowIsolated,
.dumpPriority = dumpPriority,
.hasClients = prevClients, // see b/279898063, matters if existing callbacks
.guaranteeClient = false,
.ctx = ctx,
};
......
}mNameToService是一个std::map<std::string, Service>键值映射
获取
java层调用的是ServiceManager::getService,内部做了一个缓存sCache,如果缓存没有的话就会跨进程向serviceManager进程查找binder
private static IBinder rawGetService(String name) throws RemoteException {
final IBinder binder =
getIServiceManager().getService2(name).getServiceWithMetadata().service;
}IPC接口调用的是getService2,从ServiceManager.cpp中来看应该是做了一些兼容的新函数
os::ServiceWithMetadata ServiceManager::tryGetBinder(const std::string& name,
bool startIfNotFound) {
sp<IBinder> out;
Service* service = nullptr;
if (auto it = mNameToService.find(name); it != mNameToService.end()) {
service = &(it->second);
out = service->binder;
}
}ServiceManager进程中在mNameToService中查找对应的BpBinder