美文网首页Android进阶之路Android开发Android技术知识
简单明了 | 一图摸清Android系统服务

简单明了 | 一图摸清Android系统服务

作者: 木木玩Android | 来源:发表于2020-10-21 21:38 被阅读0次

    一图摸清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
    }
    复制代码
    

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

    1. 应用程序进程调用getSystemService
    2. 通过binder跨进程通信,拿到ServiceManager进程的BpServiceManager对象
    3. 通过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;
    }
    复制代码
    

    梳理一下:

    1. init进程解析init.rc配置fork出新的进程启动多项独立进程的系统服务,如SurfaceFlinger
    2. 执行SurfaceFlinger的可执行程序,找到ServiceManager进程的BpServiceManager对象
    3. 通过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,所以他的内部细节就暂时不深入了,后面抽时间再看。

    再回顾一下~


    最后说下,我自己平时在写bug还有学习的过程中,习惯将一些学习笔记、资料整理收集下来,放在自己的githup里面,需要的同学可以点击这里自取,共同学习进步,不要嫌弃哈~

    原文链接:https://juejin.im/post/6885640823484973064

    相关文章

      网友评论

        本文标题:简单明了 | 一图摸清Android系统服务

        本文链接:https://www.haomeiwen.com/subject/ywqymktx.html