当前位置:   article > 正文

Android Context.getSystemService() 与 ServiceManager 的理解和使用_android getsystemservice

android getsystemservice

背景
这几天在天天在写Context.getSystemService()获取系统服务,例如在获取窗口服务的时候都会这样写:

WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

突然有人问我说,就是getSystemService() 每次获取的对应的WindowManager是否是同一个,还是每次生成新的?

直接翻看了下源码,事实上还是比较简单的,以下做一下记录:

分析
直接看一下Context源码:

  1. // Context
  2. public abstract Object getSystemService(@ServiceName @NonNull String name);


Context只是一个抽象类,具体看下实现类ContextWrapper

  1. @Override
  2. public Object getSystemService(String name) {
  3.     return mBase.getSystemService(name);
  4. }


ContextWrapper使用了代理模式,mBase是Context的具体实现。

在Activity启动的时候,ActivityThread的performLaunchActivity中会创建ContextImpl,同时会调用了Activity的attach(),将Context设置给了activity

  1. // ActivityThread
  2. private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  3.         // 创建了ContextImpl
  4.         ContextImpl appContext = createBaseContextForActivity(r);
  5.         Activity activity = null;
  6.         // 反射创建了activity
  7.         java.lang.ClassLoader cl = appContext.getClassLoader();
  8.         activity = mInstrumentation.newActivity(
  9.                     cl, component.getClassName(), r.intent);
  10.         // 创建applicaiton
  11.         Application app = r.packageInfo.makeApplication(false, mInstrumentation);
  12.         
  13.         appContext.setOuterContext(activity);
  14.         // 将appContext传入
  15.         activity.attach(appContext, this, getInstrumentation(), r.token,
  16.                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
  17.                         r.embeddedID, r.lastNonConfigurationInstances, config,
  18.                         r.referrer, r.voiceInteractor, window, r.configCallback);
  19.         return activity;
  20.     }


ContextImpl才是Context的真正实现。

  1. // ContextImpl
  2. @Override
  3. public Object getSystemService(String name) {
  4.     return SystemServiceRegistry.getSystemService(this, name);
  5. }


SystemServiceRegistry是一个负责注册系统服务的类,内部有一个静态的HashMap,静态加载了各种系统服务在里面,其中就包括了window_service。

  1.     // ContextImpl
  2.     private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES =
  3.             new HashMap<Class<?>, String>();
  4.     private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
  5.             new HashMap<String, ServiceFetcher<?>>();
  6.     private static int sServiceCacheSize;
  7.     
  8.     static {
  9.         ...
  10.         registerService(Context.WINDOW_SERVICE, WindowManager.class,
  11.                 new CachedServiceFetcher<WindowManager>() {
  12.             @Override
  13.             public WindowManager createService(ContextImpl ctx) {
  14.                 return new WindowManagerImpl(ctx);
  15.             }});
  16.         ...
  17.     }
  18.     static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> {
  19.         private final int mCacheIndex;
  20.         public CachedServiceFetcher() {
  21.             mCacheIndex = sServiceCacheSize++;
  22.         }
  23.         @Override
  24.         @SuppressWarnings("unchecked")
  25.         public final T getService(ContextImpl ctx) {
  26.             final Object[] cache = ctx.mServiceCache;
  27.             synchronized (cache) {
  28.                 // Fetch or create the service.
  29.                 Object service = cache[mCacheIndex];
  30.                 if (service == null) {
  31.                     try {
  32.                         service = createService(ctx);
  33.                         cache[mCacheIndex] = service;
  34.                     } catch (ServiceNotFoundException e) {
  35.                         onServiceNotFound(e);
  36.                     }
  37.                 }
  38.                 return (T)service;
  39.             }
  40.         }
  41.         public abstract T createService(ContextImpl ctx) throws ServiceNotFoundException;
  42.     }



可见,我们获取的window_service对应的就是静态hashmap存储的WindowManagerImpl,也就是一个进程只会创建一个WindowManagerImpl。

ServiceManager
WindowManagerImpl比较特别,我们再来看一个:

  1. registerService(Context.POWER_SERVICE, PowerManager.class,
  2.             new CachedServiceFetcher<PowerManager>() {
  3.         @Override
  4.         public PowerManager createService(ContextImpl ctx) throws ServiceNotFoundException {
  5.             IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
  6.             IPowerManager service = IPowerManager.Stub.asInterface(b);
  7.             return new PowerManager(ctx.getOuterContext(),
  8.                     service, ctx.mMainThread.getHandler());
  9.         }});


其中,从ServiceManager获取对应的服务的binder

 IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
1
ServiceManager提供获取服务的接口

  1. // ServiceManager
  2.     public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
  3.         final IBinder binder = getService(name);
  4.         if (binder != null) {
  5.             return binder;
  6.         } else {
  7.             throw new ServiceNotFoundException(name);
  8.         }
  9.     }


    // 通过服务名字获取binder

  1. public static IBinder getService(String name) {
  2.         try {
  3.             IBinder service = sCache.get(name);
  4.             if (service != null) {
  5.                 return service;
  6.             } else {
  7.                 // 重点:获取对应服务的Binder
  8.                 return Binder.allowBlocking(getIServiceManager().getService(name));
  9.             }
  10.         } catch (RemoteException e) {
  11.             Log.e(TAG, "error in getService", e);
  12.         }
  13.         return null;
  14.     }


上面的代码很简单,其中sCache是一个hashMap,缓存了已经加载过的服务的binder,避免二次获取。

  1. private static IServiceManager sServiceManager;
  2. private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();


最后我们的关注点就是:

IServiceManager是对应什么?

getIServiceManager().getService(name)如何获取到具体的服务的binder?

先看下IServiceManager接口的定义:

  1. public interface IServiceManager extends IInterface
  2. {
  3.     public IBinder getService(String name) throws RemoteException;
  4.     
  5.     public IBinder checkService(String name) throws RemoteException;
  6.     public void addService(String name, IBinder service, boolean allowIsolated)
  7.                 throws RemoteException;
  8.     public String[] listServices() throws RemoteException;
  9.     public void setPermissionController(IPermissionController controller)
  10.             throws RemoteException; 
  11. }



IServiceManager接口提供了getService,addService,checkService,listService接口,对应的就是binder机制里面的ServiceManager,负责跟Binder打交道,注册binder、获取binder等服务。

再看下getIServiceManager(),他也是一个获取binder转化成对应的服务接口的方法

  1. private static IServiceManager getIServiceManager() {
  2.     if (sServiceManager != null) {
  3.         return sServiceManager;
  4.     }
  5.     // Find the service manager
  6.     sServiceManager = ServiceManagerNative
  7.            .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
  8.     return sServiceManager;
  9. }



ServiceManagerNative是一个类似AIDL为我们自动生成的类的方法,他对应了服务端和客户端的实现。在我们客户端的进程中,打交道的就是ServiceManagerProxy,他是一个BpBinder。

  1. // ServiceManagerNative
  2. public abstract class ServiceManagerNative extends Binder implements IServiceManager
  3. {
  4.     static public IServiceManager asInterface(IBinder obj)
  5.     {
  6.         ...
  7.         IServiceManager in =
  8.             (IServiceManager)obj.queryLocalInterface(descriptor);
  9.         ...
  10.         return new ServiceManagerProxy(obj);
  11.     }
  12.     
  13.     public ServiceManagerNative()
  14.     {
  15.         attachInterface(this, descriptor);
  16.     }
  17.     
  18.     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
  19.     {
  20.         try {
  21.             switch (code) {
  22.             case IServiceManager.GET_SERVICE_TRANSACTION: {
  23.                 data.enforceInterface(IServiceManager.descriptor);
  24.                 String name = data.readString();
  25.                 IBinder service = getService(name);
  26.                 reply.writeStrongBinder(service);
  27.                 return true;
  28.             }
  29.             ...
  30.         } 
  31.         return false;
  32.     }
  33.     public IBinder asBinder()
  34.     {
  35.         return this;
  36.     }
  37. }
  38. class ServiceManagerProxy implements IServiceManager {
  39.     public ServiceManagerProxy(IBinder remote) {
  40.         mRemote = remote;
  41.     }
  42.     
  43.     public IBinder asBinder() {
  44.         return mRemote;
  45.     }
  46.     
  47.     public IBinder getService(String name) throws RemoteException {
  48.         Parcel data = Parcel.obtain();
  49.         Parcel reply = Parcel.obtain();
  50.         data.writeInterfaceToken(IServiceManager.descriptor);
  51.         data.writeString(name);
  52.         mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
  53.         IBinder binder = reply.readStrongBinder();
  54.         reply.recycle();
  55.         data.recycle();
  56.         return binder;
  57.     }
  58.     ....
  59. }



很明显,ServiceManagerNative就是对应了binder服务端BBinder的实现,类似aidl帮助自动生成的Stub类。ServiceManagerProxy则对应客户端BpBinder的实现,类似对应aidl帮助自动生成的Stub.Proxy代理类。

最后的问题,BinderInternal.getContextObject()获取的是什么服务的binder?

  1. // BinderInternal
  2. /**
  3.  * Return the global "context object" of the system.  This is usually
  4.  * an implementation of IServiceManager, which you can use to find
  5.  * other services.
  6.  */
  7. public static final native IBinder getContextObject();


getContextObject是一个native方法,根据注释,它是整个系统的Context对象,一般情况下,IServiceManager通过它去获取其他服务。

总结
由上面总结的信息可以得到

ServiceManager作用
通过BinderInternal.getContextObject()可以得到ServiceManager的binder,获取得到ServiceManager服务接口,借用ServiceManager服务接口可以去注册、获取我们需要的系统服务。

ServiceManager用于系统服务的注册添加和获取,在AMS都可以看到他的身影,通过它来注册系统服务:

  1.  // ActivityManagerService.java
  2.  public void setSystemProcess() {
  3.     try {
  4.         ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
  5.         ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
  6.         ServiceManager.addService("meminfo", new MemBinder(this));
  7.         ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
  8.         ServiceManager.addService("dbinfo", new DbBinder(this));
  9.         if (MONITOR_CPU_USAGE) {
  10.             ServiceManager.addService("cpuinfo", new CpuBinder(this));
  11.         }
  12.         ServiceManager.addService("permission", new PermissionController(this));
  13.         ServiceManager.addService("processinfo", new ProcessInfoService(this));
  14.         ...
  15.  }



Context.bindService() 跟ServiceManager获取对应的binder方式
Context.bindService() 跟ServiceManager获取对应的binder方式是不一样的

A 进程 Context.bindService()会将ServiceConnection封装成可IPC调用的IServiceConnection;

同时调用了AMS的bindService,AMS分发给了ActiveServices执行真正的任务;

ActiveServices做保存IServiceConnection工作,启动ActivityThread的handleBindService()去反射生成一个新的Service;

ActivityThread调用了Service的onBind()获取到了Service的binder,调用AMS的publishService(),AMS又让ActiveServices执行工作;

ActiveServices将这个binder通过IServiceConnection发给A进程。完成bindService工作,整个工作流程中,并没有去调用ServiceManager加载这个binder。

至于getContextObject()如何获取到ServiceManager的BpBinder,没有继续深究
service_manager进程是由是由init进程,通过解析init.rc文件来启动的进程。
根据底层0号可以获取到ServiceManager的binder

关于ServiceManager可以参考
https://www.cnblogs.com/lzlltmf/p/5906831.html

除了bindService(),其他方式获取binder
bindService通过ServiceConnection获取对应的binder
借助binder接口获取binder,比如说通过bindService获取binder A,而binder A提供获取binder B的接口
通过ServiceManager的addService,但ServiceManager是hide类,这种方式是SystemService注册的方式,适合系统应用的开发
PS:
同一个进程,getSystemService() 每次获取的对应的WindowManager是同一个。

发布文章的时候,系统提示说:该文章不是原创。

才发现原来这部分网上有好多文章分析过了,看来自己不能浅显的只学习这些简单的知识点,还得继续努力,往深度发展
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/311072
推荐阅读
相关标签
  

闽ICP备14008679号