图解 | 一图摸清Android系统服务

it2023-08-19  88

一图摸清Android系统服务的获取和注册流程~

大纲:

获取系统服务注册系统服务 独立进程的服务非独立进程的服务 总结参考资料

本文约1.9k字,阅读大约8分钟。

Android源码基于8.0。

先预览下整体流程~

开始分析!

获取系统服务

在日常开发中,可以通过Context.getSystemService()在自己的应用程序里获取到系统服务:

//ContextImpl.java public Object getSystemService(String name) { //SystemServiceRegistry是系统服务的注册表,用来集中管理系统服务 return SystemServiceRegistry.getSystemService(this, name); } //SystemServiceRegistry.java public static Object getSystemService(ContextImpl ctx, String name) { //根据服务名字从HashMap中取出ServiceFetcher ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name); //传入上下文,借助ServiceFetcher来获取系统服务 return fetcher != null ? fetcher.getService(ctx) : null; }

ServiceFetcher是一个抽象接口,抽象类CachedServiceFetcher实现了他,

//CachedServiceFetcher.java public final T getService(ContextImpl ctx) { //每个上下文ctx都有一份系统服务缓存 final Object[] cache = ctx.mServiceCache; synchronized (cache) { //从缓存里获取系统服务 Object service = cache[mCacheIndex]; if (service == null) { //缓存里没有,则创建 service = createService(ctx); //存入缓存 cache[mCacheIndex] = service; } return (T)service; } } //createService是个抽象方法 public abstract T createService(ContextImpl ctx);

在SystemServiceRegistry里有个静态代码块static{}会“注册服务”,从中实现抽象方法createService()的逻辑,以电源服务PowerManager为例,

//SystemServiceRegistry.java registerService( Context.POWER_SERVICE, PowerManager.class, new CachedServiceFetcher<PowerManager>() { @Override public PowerManager createService(ContextImpl ctx){ //ServiceManager根据服务名字获取系统服务的Binder对象 IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE); //将服务端的Binder转成客户端所需的AIDL接口类型的对象IPowerManager IPowerManager service = IPowerManager.Stub.asInterface(b); //再用PowerManager类包一层,方便外部使用 return new PowerManager(ctx.getOuterContext(), service, ctx.mMainThread.getHandler()); }});

AIDL可以辅助生成用于binder通信的类,IPowerManager就是定义在IPowerManager.aidl里的,binder内部细节本文不做讨论。

ServiceManager的getServiceOrThrow()函数会调用getService(),

//ServiceManager.java public static IBinder getService(String name) { //取缓存 IBinder service = sCache.get(name); if (service != null) { return service; } else { //取不到就继续,这里创建完并没有存入sCache,即sCache只是预置了一些启动阶段存入的服务 //getService()获取系统服务的Binder对象,用allowBlocking包了一下,允许阻塞 return Binder.allowBlocking(getIServiceManager().getService(name)); } return null; } private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } //binder跨进程通信: //BinderInternal.getContextObject()得到系统级别上下文的IBinder,可用来查找服务 //asInterface将IBinder转成IServiceManager(本质是BpServiceManager) sServiceManager = ServiceManagerNative .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager; }

可见,我们的应用程序进程会通过binder跨进程通信,拿到ServiceManager进程的IServiceManager对象(本质是BpServiceManager),然后就可以通过IServiceManager对象的getService来获取系统服务了。

public interface IServiceManager extends IInterface{ //从IServiceManager获取系统服务,如果服务不存在,会阻塞最多5秒,直到服务被发布注册 public IBinder getService(String name); }

看下IServiceManager的具体实现,在IServiceManager.cpp文件里,有个BpServiceManager类,

//class BpServiceManager : public BpInterface<IServiceManager> //这里的BpInterface是binder内部的细节了,不是很理解,后面抽时间看看 virtual sp<IBinder> getService(const String16& name) const { unsigned n; //如果获取不到,则休眠1秒再取,最多阻塞5秒 for (n = 0; n < 5; n++){ if (n > 0) { //休眠1秒,待会再取 sleep(1); } sp<IBinder> svc = checkService(name); //获取到系统服务,则返回 if (svc != NULL) return svc; } return NULL; } //返回系统服务的binder,暂不深究 virtual sp<IBinder> checkService( const String16& name) const { //binder使用Parcelable来序列化数据 Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); //remote()得到BpBinder,transact发送请求 remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); return reply.readStrongBinder();//Binder }

再梳理一下系统服务的获取过程:

应用程序进程调用getSystemService通过binder跨进程通信,拿到ServiceManager进程的BpServiceManager对象通过BpServiceManager获取到系统服务

注册系统服务

系统服务可以分成两大类:

一是有独立进程的ServiceManager、SurfaceFlinger等,他们在init进程启动时就会被fork创建;

二是非独立进程的AMS、PMS、WMS等,他们在init进程fork出Zygote进程,Zygote进程fork出的SystemServer进程创建。

独立进程的服务

独立进程的系统服务在init进程解析init.rc时启动,比如SurfaceFlinger,看下他的启动配置文件surfaceflinger.rc,

注:frameworks/native/services下列出了一系列服务,不过ServiceManager服务放在了frameworks/native/cmds/servicemanager目录下。

//frameworks/native/services/surfaceflinger/surfaceflinger.rc service surfaceflinger /system/bin/surfaceflinger class core animation user system group graphics drmrpc readproc onrestart restart zygote

service以服务的形式来启动进程,surfaceflinger是进程名字,/system/bin/surfaceflinger是可执行程序的路径,该程序的入口函数main在main_surfaceflinger.cpp,

int main(int, char**) { //ProcessState会启动binder机制(打开binder驱动、映射内存、分配缓冲区) sp<ProcessState> ps(ProcessState::self()); //启动binder线程 ps->startThreadPool(); //初始化surfaceflinger sp<SurfaceFlinger> flinger = new SurfaceFlinger(); flinger->init(); //发布注册surfaceflinger sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); //在当前线程运行surfaceflinger flinger->run(); return 0; }

看下defaultServiceManager()的实现,在IServiceManager.cpp,

sp<IServiceManager> defaultServiceManager() { //有值,直接返回 if (gDefaultServiceManager != NULL) return gDefaultServiceManager; { AutoMutex _l(gDefaultServiceManagerLock); while (gDefaultServiceManager == NULL) { //查找ServiceManager,强转为IServiceManager(本质是BpServiceManager) gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL)); //如果IServiceManager还是null,则休眠1秒再取,直至取到才结束循环 if (gDefaultServiceManager == NULL) sleep(1); } } return gDefaultServiceManager; }

因为SurfaceFlinger进程和ServiceManager进程都是init进程启动的,有可能SurfaceFlinger在获取IServiceManager时,ServiceManager还没来得及注册,所以这里会边取边休眠,取到才结束循环。

得到IServiceManager后,执行sm->addService,在IServiceManager.cpp文件里有个BpServiceManager类,

//class BpServiceManager : public BpInterface<IServiceManager> //这里的BpInterface是binder内部的细节了,不是很理解,后面抽时间看看 //注册系统服务(的binder),暂不深究 virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated) { //binder使用Parcelable来序列化数据 Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); data.writeStrongBinder(service);//Binder data.writeInt32(allowIsolated ? 1 : 0); //remote()得到BpBinder,transact发送请求 status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; }

梳理一下:

init进程解析init.rc配置fork出新的进程,启动多项独立进程的系统服务,如SurfaceFlinger执行SurfaceFlinger的可执行程序,找到ServiceManager进程的BpServiceManager对象通过BpServiceManager执行addService注册服务

非独立进程的服务

非独立进程的系统服务由SystemServer进程启动,从图解Android系统的启动一文可知,SystemServer借助SystemServiceManager类(SSM)来启动系统服务,比如AMS,

//SystemServer.java private void startBootstrapServices() { //AMS由SSM创建启动 mActivityManagerService = mSystemServiceManager //创建并启动AMS服务 .startService(ActivityManagerService.Lifecycle.class) //通过binder获取AMS服务 .getService(); //注册AMS mActivityManagerService.setSystemProcess(); }

看到ActivityManagerService,

//ActivityManagerService.java public void setSystemProcess() { //注册AMS ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true); }

调用了ServiceManager.addService()进行注册,

//ServiceManager.java public static void addService(String name, IBinder service, boolean allowIsolated) { //跟前边一样,通过binder跨进程通信,拿到ServiceManager进程的BpServiceManager对象 //调用BpServiceManager的addService getIServiceManager().addService(name, service, allowIsolated); }

可见,无论是SystemServer进程启动的服务,还是init进程启动的运行在独立进程里的服务,最终都是走ServiceManager进程的BpServiceManager.addService进行集中注册。

总结

综上,不管是由init进程启动的独立进程的系统服务如SurfaceFlinger,还是由SystemServer进程启动的非独立进程的系统服务如AMS,都是在ServiceManager进程中完成注册和获取的,在跨进程通信上使用了Android的binder机制。

不过哈迪在工作中没怎么用过binder,所以他的内部细节就暂时不深入了,后面抽时间再看。

再回顾一下~

系列文章:

图解 | Android系统的启动

参考资料

csdn - servicemanager的客户端代理: BpServiceManager

更多性感文章,关注原创技术公众号:哈利迪ei

最新回复(0)