美文网首页SystemServer
Android系统服务管理者——ServiceManager

Android系统服务管理者——ServiceManager

作者: AndroidHint | 来源:发表于2018-05-01 18:37 被阅读0次

    Android系统给我们提供了上百个服务,每一个服务都有一个服务中介类,例如WindowManager、ActivityManager等。
    通常我们和系统服务进行交互都是通过服务中介来进行的。通过Context.getSystemService(String name)我们可以获取系统服务,并在客户端封装成中介类,然后通过该中介类去获取相关的系统服务。那么到底系统服务和中介类是怎么获取的呢?
    我们知道Context的实现类为ContextImpl,所以我们进入到ContextImpl的getSystemService(String name)方法中:

    @Override
    public Object getSystemService(String name) {
        return SystemServiceRegistry.getSystemService(this, name);
    }
    

    这里执行了SystemServiceRegistry.getSystemService(String name)方法,继续跟踪该方法:

    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }
    

    可以看到系统服务中介类是从ServiceFetcher.getService(ContextImpl ctx)方法获取的,而ServiceFetcher对象由SYSTEM_SERVICE_FETCHERS生成。SYSTEM_SERVICE_FETCHERS是一个HashMap,其Key为系统服务名,Value为ServiceFetcher对象。
    那我们找一下SYSTEM_SERVICE_FETCHERS是什么时候被赋值的?在SystemServiceRegistry的registerService(String serviceName, Class<T> serviceClass, ServiceFetcher<T> serviceFetcher)方法中我们找到了:

    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        //在这类SYSTEM_SERVICE_FETCHERS被赋值
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
    

    再看registerService方法是什么时候被调用的?可以找到在SystemServiceRegistry类的静态代码块中调用了registerService方法:

    static {
        registerService(Context.ACCESSIBILITY_SERVICE, AccessibilityManager.class,
                new CachedServiceFetcher<AccessibilityManager>() {
            @Override
            public AccessibilityManager createService(ContextImpl ctx) {
                return AccessibilityManager.getInstance(ctx);
            }});
    
        registerService(Context.CAPTIONING_SERVICE, CaptioningManager.class,
                new CachedServiceFetcher<CaptioningManager>() {
            @Override
            public CaptioningManager createService(ContextImpl ctx) {
                return new CaptioningManager(ctx);
            }});
    
        registerService(Context.ACCOUNT_SERVICE, AccountManager.class,
                new CachedServiceFetcher<AccountManager>() {
            @Override
            public AccountManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                IBinder b = ServiceManager.getServiceOrThrow(Context.ACCOUNT_SERVICE);
                IAccountManager service = IAccountManager.Stub.asInterface(b);
                return new AccountManager(ctx, service);
            }});
    
        registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
                new CachedServiceFetcher<ActivityManager>() {
            @Override
            public ActivityManager createService(ContextImpl ctx) {
                return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
            }});
    
        registerService(Context.ALARM_SERVICE, AlarmManager.class,
                new CachedServiceFetcher<AlarmManager>() {
            @Override
            public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);
                IAlarmManager service = IAlarmManager.Stub.asInterface(b);
                return new AlarmManager(service, ctx);
            }});
            ...省略
    }
    

    这里多次调用了registerService方法,每一个registerService方法的参数中都new了一个ServiceFetcher对象。还记得上面我们说到的系统服务中介类是怎么来的吗?没错,就是通过ServiceFetcher对象的getService(ContextImpl ctx)获取的。而ServiceFetcher是一个接口,其getService(ContextImpl ctx)方法由子类来实现。在子类的实现方法中getService(ContextImpl ctx)方法又调用了createService(ContextImpl ctx)方法并返回,所以createService(ContextImpl ctx)方法生成的对象就是我们需要获取的服务中介类。

    最开始的时候我们提到,服务中介类只是对系统服务的一个封装。那就表明在ServiceFetcher对象的createService(ContextImpl ctx)方法中肯定是能获取系统服务对象的。让我们看一个具体的例子:

    registerService(Context.ALARM_SERVICE, AlarmManager.class,
            new CachedServiceFetcher<AlarmManager>() {
        @Override
        public AlarmManager createService(ContextImpl ctx) throws ServiceNotFoundException {
            IBinder b = ServiceManager.getServiceOrThrow(Context.ALARM_SERVICE);
            IAlarmManager service = IAlarmManager.Stub.asInterface(b);
            return new AlarmManager(service, ctx);
        }});
    

    上面是获取闹钟系统服务的一个例子。
    第一步:
    通过ServiceManager.getServiceOrThrow(String name)获取了服务端的Binder对象,而getServiceOrThrow最终调用的还是getService(String name)方法:

    public static IBinder getService(String name) {
        try {
            IBinder service = sCache.get(name);
            if (service != null) {
                return service;
            } else {
                return Binder.allowBlocking(getIServiceManager().getService(name));
            }
        } catch (RemoteException e) {
            Log.e(TAG, "error in getService", e);
        }
        return null;
    }
    

    上面的代码告诉我们,如果有缓存则从缓存获取服务端的Binder对象,如果没有则调用getIServiceManager().getService(String name)获取服务端的Binder对象:

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }
    
        // Find the service manager
        sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
        return sServiceManager;
    }
    

    从上面的代码可以看到获取服务端Binder对象也是通过Binder对象进行跨进程通信获取的(IServiceManager是一个Binder对象)。

    第二步:
    通过调用IAlarmManager.Stub.asInterface(Binder binder)方法将第一步获取到的Binder对象转换成所需的系统服务对象。
    这里说明一下,这个方法是区分进程的,如果客户端和服务端位于同一个进程,则返回服务端的Stub对象本身,否则返回的是系统封装后的Stub.proxy对象(该对象作为代理对象,与服务端进行通信并将数据返回给客户端)。

    ServiceManager在这里起到的作用是对所有的系统服务进行管理,其提供了getService(String name)addService(String name)checkService(String name)listServices(String name)等方法。

    相关文章

      网友评论

        本文标题:Android系统服务管理者——ServiceManager

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