美文网首页
Android系统服务调用分析

Android系统服务调用分析

作者: 雷涛赛文 | 来源:发表于2020-09-16 18:31 被阅读0次

          在Android系统中,framework向应用层提供了很多系统服务,例如InputManager、ActivityManager、WindowManager等,方便的实现软件需求的开发。

    一.系统服务使用

          一般而言,在使用时,通过以下方式来获取对应的系统服务管理者:

    WindowManager mWindowManager;
    mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
    mWindowManager.addView();
    

          即:调用 Context 类的 getSystemService(String name) 方法,通过一步一步调用,该方法的最终实现是在 ContextImpl 类中,通过查看 ContextImpl 的源码,发现对应的实现如下:

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

          从ContextImpl里面的实现来看,会调用到SystemServiceRegistry类里面的getSystemService方法,再进去看一下SystemServiceRegistry.java的内部实现:

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

          从以上方法可以看到:从SYSTEM_SERVICE_FETCHERS 中获取对应名称的系统服务管理者提取器,然后从中得到对应的服务器管理者。看一下SYSTEM_SERVICE_FETCHERS:

    private static final HashMap<String, SystemServiceRegistry.ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap();
    

          SYSTEM_SERVICE_FETCHERS是一个HashMap,存放着String为key,ServiceFetcher为value的键值对:

    private static <T> void registerService(String serviceName, Class<T> serviceClass, SystemServiceRegistry.ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }
    

          在执行registerService方法时,将serviceName对应的serviceFetcher存入HashMap,接着看一下ServiceFetcher的实现:

    abstract static class CachedServiceFetcher<T> implements SystemServiceRegistry.ServiceFetcher<T> {
        private final int mCacheIndex;
    
        public CachedServiceFetcher() {
            mCacheIndex = SystemServiceRegistry.sServiceCacheSize++;
        }
    
        public final T getService(ContextImpl ctx) {
            final Object[] cache = ctx.mServiceCache;
            synchronized(cache) {
                Object service = cache[mCacheIndex];
                if (service == null) {
                    try {
                        service = createService(ctx);
                        cache[mCacheIndex] = service;
                    } catch (ServiceNotFoundException e) {
                        onServiceNotFound(e);
                   }
                }
    
                return (T)service;
            }
        }
    
        public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
    }
    
    interface ServiceFetcher<T> {
        T getService(ContextImpl var1);
    }
    

          从以上可以看到,ServiceFetcher是一个接口,通过CachedServiceFetcher来实现,里面有一个抽象方法createService()需要实现,在getService()方法里面有调用到createService(),接下来看一下系统服务是如何注册的:

    二.系统服务注册

          要想使用系统服务,肯定是需要系统服务先注册后使用,看一下系统服务是什么时候注册的:

    static {
        ....
        registerService("rttmanager", RttManager.class, new SystemServiceRegistry.CachedServiceFetcher<RttManager>() {
            public RttManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                IBinder b = ServiceManager.getServiceOrThrow("rttmanager");
                IRttManager service = android.net.wifi.IRttManager.Stub.asInterface(b);
                return new RttManager(ctx.getOuterContext(), service, ConnectivityThread.getInstanceLooper());
            }
        });
    
        registerService("ethernet", EthernetManager.class, new SystemServiceRegistry.CachedServiceFetcher<EthernetManager>() {
            public EthernetManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                IBinder b = ServiceManager.getServiceOrThrow("ethernet");
                IEthernetManager service = android.net.IEthernetManager.Stub.asInterface(b);
                return new EthernetManager(ctx.getOuterContext(), service);
            }
        });
    
        registerService("window", WindowManager.class, new SystemServiceRegistry.CachedServiceFetcher<WindowManager>() {
            public WindowManager createService(ContextImpl ctx) {
                return new WindowManagerImpl(ctx);
            }
        });
    }
    ....
    

          registerService()是在static代码块里面,createService()会返回对应的Manager,那么在getSystemService()内部执行fetcher.getService(ctx)就获取到了manager,在返回前有以下逻辑:

    IBinder b = ServiceManager.getServiceOrThrow("ethernet");
    IEthernetManager service = android.net.IEthernetManager.Stub.asInterface(b);
    

          先通过ServiceManager获取了“ethernet”对应的IBinder,然后获取到service,最后把service作为参数传递给EthernetManager。看一下EthernetManager的实现:

    public class EthernetManager {
        private final IEthernetManager mService;
        public EthernetManager(Context context, IEthernetManager service) {
            mContext = context;
            mService = service;
        }
    
        public IpConfiguration getConfiguration() {
            try {
                return mService.getConfiguration();
            }
            .....
        }
    
        public void setConfiguration(IpConfiguration config) {
            try {
                mService.setConfiguration(config);
            } 
            .....
        }
    
        public boolean isAvailable() {
            try {
                return mService.isAvailable();
            }
            ......
        }
    
        public void addListener(Listener listener) {
            mListeners.add(listener);
            if (mListeners.size() == 1) {
                try {
                    mService.addListener(mServiceListener);
                }
                ......
            }
        }
    
        public void removeListener(Listener listener) {
            mListeners.remove(listener);
            if (mListeners.isEmpty()) {
                try {
                    mService.removeListener(mServiceListener);
                }
                ......
            }
        }
    

          通过以上看到,通过EthernetManager来调用framework接口,其实是通过IEthernetManager来执行的,IEthernetManager是aidl接口,而前面看到,IEthernetManager是通过Stub.asInterface()来获取的,肯定有对应Binder实现,接下来看一下该Binder的实现及Binder是如何暴露出来的:

    三.系统服务实现

          本文拿EthernetManager来举例,看一下对应的EthernetService的内部逻辑是如何实现的:

    public final class EthernetService extends SystemService {
    
        private static final String TAG = "EthernetService";
        final EthernetServiceImpl mImpl;
    
        public EthernetService(Context context) {
            super(context);
            mImpl = new EthernetServiceImpl(context);
        }
    
        @Override
        public void onStart() {
            Log.i(TAG, "Registering service " + Context.ETHERNET_SERVICE);
            //公开Binder
            publishBinderService(Context.ETHERNET_SERVICE, mImpl);
        }
    }
    

          在构造方法中创建EthernetServiceImpl()实例,然后在onStart()中执行publishBinderService(),该方法是父类SystemService.java的方法,实现如下:

    protected final void publishBinderService(String name, IBinder service) {
        publishBinderService(name, service, false);
    }
    
    protected final void publishBinderService(String name, IBinder service,
                boolean allowIsolated) {
        //最终会通过ServiceManager.addService来注册Binder
        ServiceManager.addService(name, service, allowIsolated);
    }
    

          通过以上可以看到,在EthernetService启动时,会执行publishBinderService()来将EthernetServiceImpl来作为实名的Binder来暴露出来,在publishBinderService()内部会通过ServiceManager.addService()将实名Binder统一给ServiceManager来管理。

    public class EthernetServiceImpl extends IEthernetManager.Stub {
        //实现IEthernetManager里面的方法
        IpConfiguration getConfiguration() {
        }
    
        void setConfiguration(in IpConfiguration config) {
        }
    
        boolean isAvailable(){
        }
    
        void addListener(in IEthernetServiceListener listener){
       }
    }
    

          EthernetServiceImpl继承IEthernetManager.Stub,来实现IEthernetManager.aidl的方法,供远端的Client来最终调用。

    interface IEthernetManager
    {
        IpConfiguration getConfiguration();
        void setConfiguration(in IpConfiguration config);
        boolean isAvailable();
        void addListener(in IEthernetServiceListener listener);
    }
    

    四.系统服务启动

          要想获取IEthernetManager的Binder,必须要先把Binder公开出来,该Binder公开是在EthernetService启动后执行的,那么需要有个地方来启动EthernetService,该启动入口是在哪的?在SystemServer.java中:

        private void run() {
            // Start services.
            try {
                traceBeginAndSlog("StartServices");
                startBootstrapServices();
                startCoreServices();
                startOtherServices();
                SystemServerInitThreadPool.shutdown();
            }
            ......
        }
    

          在SystemServer启动的时候,去在main()中调用run()方法,然后在run()中会去启动系统的一些公共service,该service在startOtherServices()中启动的:

    private static final String ETHERNET_SERVICE_CLASS ="com.android.server.ethernet.EthernetService";
    private void startOtherServices() {
        ......
        //其他service
        ......
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
            mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
            traceBeginAndSlog("StartEthernet");
            mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
            traceEnd();
         }
        ....
        //其他service
        ......
    }
    

          EthernetService是在startOtherServices()通过SystemServiceManager.startService()去启动的,传入对应的系统服务类名,看一下SystemServiceManager内部startService的实现逻辑:

        public SystemService startService(String className) {
            final Class<SystemService> serviceClass;
            try {
                serviceClass = (Class<SystemService>)Class.forName(className);
            } 
            ......
            return startService(serviceClass);
        }
    

          先通过传入的字符串找到对应的类,然后传入类名调用startService():

        public <T extends SystemService> T startService(Class<T> serviceClass) {
            try {
                final String name = serviceClass.getName();
                .......
                final T service;
                try {
                    Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                    service = constructor.newInstance(mContext);
                } 
                .......
                startService(service);
                return service;
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }
        }
    

          通过反射找到构造方法,然后通过newInstance()来创造了实例,然后传入该实例调用startService():

        public void startService(@NonNull final SystemService service) {
            // Register it.
            mServices.add(service);
            // Start it.
            long time = SystemClock.elapsedRealtime();
            try {
                service.onStart();
            }
            ......
        }
    

          调用service的onStart()方法,即调用了EthernetService的onStart()方法,将Binder暴露出来供调用;注意:SystemService是一个抽象类,不是Service。
          简单总结一下:系统服务首先通过SystemServer内部调用SystemServiceManager来进行启动,启动后会将自己注册到ServiceManager作为实名服务,系统服务对应的Manager在SystemServiceRegistry内部注册时就通过ServiceManager来获取到该服务,从而供上层应用使用;当使用系统服务时,首先通过 Context 类的 getSystemService方法获取到服务对应的Manager,Manager会通过对应服务公开的Binder最终与服务进行通信,然后来执行上层的逻辑。

    五.系统服务实现及使用流程

          1.创建xx.aidl文件,加入系统服务能提供的方法;
          2.创建类文件来实现xx.Stub,来实现服务提供的方法;
          3.将实现xx.Stub的类对象Binder通过ServiceManager.addService()注册【SystemServer作为入口触发】;
          4.创建服务对应的Manager,封装对应服务提供方法的方法来供app调用;
          5.SystemServiceProxy通过registerService来注册对应的服务【Manager与对应的服务建立联系】;
          6.app通过getSystemService()来获取对应服务的Manager,然后调用方法;

    六.其他

          系统服务是供上层app来使用的,在rom定制化开发时,如果使用某个服务的应用很多时,比如数据上报,那么可以将数据上报作为一个系统服务来跟后台进行交互;
          系统服务暴露对应的门面类Manager供应用来调用,这样的话系统服务只跟Manager打交道就行了,不需要跟所有的应用来维持关系。

    相关文章

      网友评论

          本文标题:Android系统服务调用分析

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