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
ServiceManager代理对象BinderProxy在native层做了几次封装,最初始的对象是BpServiceManager,然后封装成BackendUnifiedServiceManager,最后java对象BinderProxy包含了指向native对象的指针。
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();
}当驱动的指令下来,经过下面的调用栈,最终走到ServiceManager类
IPCThreadState::handlePolledCommands()
IPCThreadState::getAndExecuteCommand()
IPCThreadState::talkWithDriver(bool doReceive)
IPCThreadState::executeCommand(int32_t cmd)
BBinder::transact()
BnServiceManager::onTransact
ServiceManager::addService()Java的AIDL也有上面类似的调用链,区别是java是从binder线程池开始的,而servicemanager是从主线程looper发起的