系统服务分析
1 获取系统服务
@Override
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
内部是调用了SystemServiceRegistry.getSystemService(this, name);,那我们进入其getSystemService查看
/**
* Gets a system service from a given context.
*/
public static Object getSystemService(ContextImpl ctx, String name) {
ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
return fetcher != null ? fetcher.getService(ctx) : null;
}
通过SYSTEM_SERVICE_FETCHERS获取ServiceFetcher,再使用fetcher.getService(ctx)获取服务。那SYSTEM_SERVICE_FETCHERS是什么,又是在什么时候初始化的呢?
在SystemServiceRegistry中我们看到
1 类型:PSYSTEM_SERVICE_FETCHERS是一个map,key为Service的名字,value为ServiceFetcher
2 初始化:
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);
}});
……………
……………
// 省略部分代码
}
SystemServiceRegistry在一个静态代码块创建并注册各种服务,再进入到registerService方法中,查看是如何注册的(当类被加载时,静态代码块被执行,且只被执行一次,静态块常用来执行类属性的初始化)
/**
* Statically registers a system service with the context.
* This method must be called during static initialization only.
*/
private static <T> void registerService(String serviceName, Class<T> serviceClass,
ServiceFetcher<T> serviceFetcher) {
SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
}
registerService方法只是将各种服务添加到SYSTEM_SERVICE_FETCHERS中,就是在类被加载时,SYSTEM_SERVICE_FETCHERS被初始化,各种服务被添加到其中去
2 服务的创建(以AlarmManagerService为例)
registerService(Context.ALARM_SERVICE, AlarmManager.class,
new CachedServiceFetcher<AlarmManager>() {
@Override
public AlarmManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.ALARM_SERVICE);
IAlarmManager service = IAlarmManager.Stub.asInterface(b);
return new AlarmManager(service, ctx);
}});
这里有两个步骤:
通过ServiceManager.getService(Context.ALARM_SERVICE);获取到AlarmManagerService服务对应的Binder对象
IAlarmManager.Stub.asInterface()方法返回一个IAlarmManager的统一接口
那ServiceManager.getService(Context.ALARM_SERVICE)是如何获取服务对应的Binder对象的呢?我们进入这个方法:
/**
* Returns a reference to a service with the given name.
*
* @param name the name of the service to get
* @return a reference to the service, or <code>null</code> if the service doesn't exist
*/
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
这里也有两个步骤:
通过sCache.get(name)查看缓存中是否有该服务对应的Binder对象,有则返回
如果缓存没有,则通过getIServiceManager().getService(name);获取
3 ServiceManager分析
ServiceManager本身也是一个Service,那它的Binder引用是怎么获取的呢?
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
}
// Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
在getIServiceManager()方法中可以看到,可以通过BinderInternal.getContextObject()获取该Service对应的Binder引用
4 理解Manager
ServiceManager所管理的所有Service都是以相应的Manager返回给客户端
客户端一般不直接通过Binder引用去访问具体的服务,而是经过一个Manager,相应的Manager对客户端是可见的,而远程的服务类对客户端是隐藏的
这些Manager内部会有一个远程服务的Binder变量,一般情况下,会通过够走啊函数初始化这个Bind而变量:即先通过ServiceManager获取远程服务的Binder引用,然后使用这个Bindre引用构造一个客户端本地可以访问的Manager,然后客户端就通过这个Manager访问远程的服务