Android(安卓)Context.getSystemService() 与 ServiceManager 的理解和使用
文章目录
- 背景
- 分析
- ServiceManager
- 总结
- ServiceManager作用
- Context.bindService() 跟ServiceManager获取对应的binder方式
- 除了bindService(),其他方式获取binder
- PS:
背景
这几天在天天在写Context.getSystemService()获取系统服务,例如在获取窗口服务的时候都会这样写:
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
突然有人问我说,就是getSystemService() 每次获取的对应的WindowManager是否是同一个,还是每次生成新的?
直接翻看了下源码,事实上还是比较简单的,以下做一下记录:
分析
直接看一下Context源码:
// Contextpublic abstract Object getSystemService(@ServiceName @NonNull String name);
Context只是一个抽象类,具体看下实现类ContextWrapper
@Overridepublic Object getSystemService(String name) { return mBase.getSystemService(name);}
ContextWrapper使用了代理模式,mBase是Context的具体实现。
在Activity启动的时候,ActivityThread的performLaunchActivity中会创建ContextImpl,同时会调用了Activity的attach(),将Context设置给了activity
// ActivityThreadprivate Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { // 创建了ContextImpl ContextImpl appContext = createBaseContextForActivity(r); Activity activity = null; // 反射创建了activity java.lang.ClassLoader cl = appContext.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); // 创建applicaiton Application app = r.packageInfo.makeApplication(false, mInstrumentation); appContext.setOuterContext(activity); // 将appContext传入 activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); return activity; }
ContextImpl才是Context的真正实现。
// ContextImpl@Overridepublic Object getSystemService(String name) { return SystemServiceRegistry.getSystemService(this, name);}
SystemServiceRegistry是一个负责注册系统服务的类,内部有一个静态的HashMap,静态加载了各种系统服务在里面,其中就包括了window_service。
// ContextImpl private static final HashMap<Class<?>, String> SYSTEM_SERVICE_NAMES = new HashMap<Class<?>, String>(); private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS = new HashMap<String, ServiceFetcher<?>>(); private static int sServiceCacheSize; static { ... registerService(Context.WINDOW_SERVICE, WindowManager.class, new CachedServiceFetcher<WindowManager>() { @Override public WindowManager createService(ContextImpl ctx) { return new WindowManagerImpl(ctx); }}); ... } static abstract class CachedServiceFetcher<T> implements ServiceFetcher<T> { private final int mCacheIndex; public CachedServiceFetcher() { mCacheIndex = sServiceCacheSize++; } @Override @SuppressWarnings("unchecked") public final T getService(ContextImpl ctx) { final Object[] cache = ctx.mServiceCache; synchronized (cache) { // Fetch or create the service. 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; }
可见,我们获取的window_service对应的就是静态hashmap存储的WindowManagerImpl,也就是一个进程只会创建一个WindowManagerImpl。
ServiceManager
WindowManagerImpl比较特别,我们再来看一个:
registerService(Context.POWER_SERVICE, PowerManager.class, new CachedServiceFetcher<PowerManager>() { @Override public PowerManager createService(ContextImpl ctx) throws ServiceNotFoundException { IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE); IPowerManager service = IPowerManager.Stub.asInterface(b); return new PowerManager(ctx.getOuterContext(), service, ctx.mMainThread.getHandler()); }});
其中,从ServiceManager获取对应的服务的binder
IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
ServiceManager提供获取服务的接口
// ServiceManager public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException { final IBinder binder = getService(name); if (binder != null) { return binder; } else { throw new ServiceNotFoundException(name); } } // 通过服务名字获取binder public static IBinder getService(String name) { try { IBinder service = sCache.get(name); if (service != null) { return service; } else { // 重点:获取对应服务的Binder return Binder.allowBlocking(getIServiceManager().getService(name)); } } catch (RemoteException e) { Log.e(TAG, "error in getService", e); } return null; }
上面的代码很简单,其中sCache是一个hashMap,缓存了已经加载过的服务的binder,避免二次获取。
private static IServiceManager sServiceManager;private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
最后我们的关注点就是:
-
IServiceManager是对应什么?
-
getIServiceManager().getService(name)
如何获取到具体的服务的binder?
先看下IServiceManager接口的定义:
public interface IServiceManager extends IInterface{ public IBinder getService(String name) throws RemoteException; public IBinder checkService(String name) throws RemoteException; public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException; public String[] listServices() throws RemoteException; public void setPermissionController(IPermissionController controller) throws RemoteException; }
IServiceManager接口提供了getService
,addService
,checkService
,listService
接口,对应的就是binder机制里面的ServiceManager,负责跟Binder打交道,注册binder、获取binder等服务。
再看下getIServiceManager()
,他也是一个获取binder转化成对应的服务接口的方法
private static IServiceManager getIServiceManager() { if (sServiceManager != null) { return sServiceManager; } // Find the service manager sServiceManager = ServiceManagerNative .asInterface(Binder.allowBlocking(BinderInternal.getContextObject())); return sServiceManager;}
ServiceManagerNative是一个类似AIDL为我们自动生成的类的方法,他对应了服务端和客户端的实现。在我们客户端的进程中,打交道的就是ServiceManagerProxy,他是一个BpBinder。
// ServiceManagerNativepublic abstract class ServiceManagerNative extends Binder implements IServiceManager{ static public IServiceManager asInterface(IBinder obj) { ... IServiceManager in = (IServiceManager)obj.queryLocalInterface(descriptor); ... return new ServiceManagerProxy(obj); } public ServiceManagerNative() { attachInterface(this, descriptor); } public boolean onTransact(int code, Parcel data, Parcel reply, int flags) { try { switch (code) { case IServiceManager.GET_SERVICE_TRANSACTION: { data.enforceInterface(IServiceManager.descriptor); String name = data.readString(); IBinder service = getService(name); reply.writeStrongBinder(service); return true; } ... } return false; } public IBinder asBinder() { return this; }}class ServiceManagerProxy implements IServiceManager { public ServiceManagerProxy(IBinder remote) { mRemote = remote; } public IBinder asBinder() { return mRemote; } public IBinder getService(String name) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IServiceManager.descriptor); data.writeString(name); mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0); IBinder binder = reply.readStrongBinder(); reply.recycle(); data.recycle(); return binder; } ....}
很明显,ServiceManagerNative就是对应了binder服务端BBinder的实现,类似aidl帮助自动生成的Stub类。ServiceManagerProxy则对应客户端BpBinder的实现,类似对应aidl帮助自动生成的Stub.Proxy代理类。
最后的问题,BinderInternal.getContextObject()
获取的是什么服务的binder?
// BinderInternal/** * Return the global "context object" of the system. This is usually * an implementation of IServiceManager, which you can use to find * other services. */public static final native IBinder getContextObject();
getContextObject是一个native方法,根据注释,它是整个系统的Context对象,一般情况下,IServiceManager通过它去获取其他服务。
总结
由上面总结的信息可以得到
ServiceManager作用
-
通过BinderInternal.getContextObject()可以得到ServiceManager的binder,获取得到ServiceManager服务接口,借用ServiceManager服务接口可以去注册、获取我们需要的系统服务。
-
ServiceManager用于系统服务的注册添加和获取,在AMS都可以看到他的身影,通过它来注册系统服务:
// ActivityManagerService.java public void setSystemProcess() {try { ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats); ServiceManager.addService("meminfo", new MemBinder(this)); ServiceManager.addService("gfxinfo", new GraphicsBinder(this)); ServiceManager.addService("dbinfo", new DbBinder(this)); if (MONITOR_CPU_USAGE) { ServiceManager.addService("cpuinfo", new CpuBinder(this)); } ServiceManager.addService("permission", new PermissionController(this)); ServiceManager.addService("processinfo", new ProcessInfoService(this)); ... }
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是同一个。
发布文章的时候,系统提示说:该文章不是原创。
才发现原来这部分网上有好多文章分析过了,看来自己不能浅显的只学习这些简单的知识点,还得继续努力,往深度发展
更多相关文章
- Android获取View的宽高与View.measure详解
- Android端上传文件到Web服务器
- android获取周围WIFI热点
- Android系统剪贴板(ClipboardManager)的简单使用
- 利用power_profile.xml获取Android运行时的能耗
- android andbase 线程池
- Android原生GPS和网络定位工具类
- Android(安卓)开机自动启动服务
- android 模拟器上查看shareperference文件内容