Framework基础:应用是如何跟系统服务打交道的
Android有许多系统服务,例如ActivityManagerService,PowerManagerService等,这些系统服务都跑在SystemServer进程之中。而普通的应用跑在自己的进程里面。那普通应用要怎样才能使用到系统服务呢?这个就相当于普通应用进程跟SystemServer进程进行通行,不同进程进行通信,就是跨进程的通信啦。Android中特有的跨进程通信的方式是binder通信。下面说下应用与系统ActivityManagerService交互的过程。
应用是如何获取到ActivityManager的呢?###
下图是获取ActivityManager的内部时序图
获取ActivityManager内部时序图.png应用层调用Context的getSystemService方法获取到ActivityManager
ActivityManager mActivityManager;
mActivityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
下面调用到ContextImpl的getSystemService
public Object getSystemService(String name) {
return SystemServiceRegistry.getSystemService(this, name);
}
进入SystemServiceRegistry.getSystemService(this, name)方法,可以看到首先通过SYSTEM_SERVICE_FETCHERS的get方法返回一个ServiceFetcher,然后通过ServiceFetcher的getService方法返回一个ActivityManager。
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是一个HashMap,key是服务名称,内容是ServiceFetcher对象。
private static final HashMap<String, ServiceFetcher<?>> SYSTEM_SERVICE_FETCHERS =
new HashMap<String, ServiceFetcher<?>>();
SYSTEM_SERVICE_FETCHERS是保存着所有ServiceFetcher的全局变量,我们看看这个全局变量是怎么填充的。通过静态块中的registerService方法填充。
registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
new CachedServiceFetcher<ActivityManager>() {
@Override
public ActivityManager createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
看看这个registerService函数,可以看到SYSTEM_SERVICE_FETCHERS通过put把系统服务填充到自己里面。
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);
}
ServiceFetcher是一个接口,他的实现是CachedServiceFetcher。
static abstract interface ServiceFetcher<T> {
T getService(ContextImpl ctx);
}
就是说一个CachedServiceFetcher是跟一个系统服务相关联的,其通过createService创建关联的系统服务,通过getService获取关联的系统服务。看createService方法,可以看到new了一个ActivityManager对象,所以返回的就是一个ActivityManager对象啦。
registerService(Context.ACTIVITY_SERVICE, ActivityManager.class,
new CachedServiceFetcher<ActivityManager>() {
@Override
public ActivityManager createService(ContextImpl ctx) {
return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
}});
系统服务数据结构图.png
那ActivityManager是怎么跟ActivityManagerService通信的呢?###
我们以ActivityManager的一个方法为例子看一下就行了,例如获取最近任务的方法ActivityManager.getRecentTasks
public List<RecentTaskInfo> getRecentTasks(int maxNum, int flags)
throws SecurityException {
try {
return ActivityManagerNative.getDefault().getRecentTasks(maxNum,
flags, UserHandle.myUserId());
} catch (RemoteException e) {
// System dead, we will be dead too soon!
return null;
}
}
进入ActivityManagerNative的getDefault()方法,方法返回一个IActivityManager的单例,IActivityManager是一个接口,继承于Interface接口。IActivityManager 的实现是ActivityManagerProxy,所以方法其实是返回一个 ActivityManagerProxy的单例对象。这是一个代理对象,用于跟ActivityManagerService进行binder通信。
套路差不多都这样
1.ServiceManager.getService获取到Ibinder
2.通过asInterface获取到远程服务的本地代理。
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
}
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
ActivityManagerNative相当于aidl通信中的stub的角色,stub继承于binder,专门用于binder通信。ActivityManagerService会继承于这个stub。
很多地方都可以看到这个stub,这个stub可以看作一个中间者的角色吧。这个中间者里面包含着本地代理的类定义,同时这个中间者被远端服务所继承。
IActivityManager是本地代理和远端服务都要实现的接口,就是说本地代理里面的方法要和远端服务的方法一一对应。
首先ActivityManagerService会发布本地的接口,通过ActivityManagerNative的构造方法发布了,接口用descriptor标示,在IActivityManager定义,String descriptor = "android.app.IActivityManager";
public ActivityManagerNative() {
attachInterface(this, descriptor);
}
然后通过Binder的queryLocalInterface可以找到本地对应的接口,这个接口的引用被代理所持有,所以代理就可以使用这个本地接口跟远端服务通信了。
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
代理每次调用方法,都会调用到这个本地接口transact方法,把参数跨进程发送到远端服务,远端服务通过onTransact方法,调用到实际的方法。
上面的说法有些逆向,为了正向理解,我们想想基于binder通信你会怎么写呢?
首先整个架构要有两个要素
1.远端服务
2.本地代理
所以有了两个类,远端服务ActivityManagerService,本地代理ActivityManagerProxy。
远端服务和本地代理肯定要实现同样的方法嘛,所有最好设计一个接口给两者实现。所以设计一个接口IActivityManager。
ActivityManagerService为了能够远程被调用到,必须继承于Binder类。所以这时ActivityManagerService既要继承binder,也要实现IActivityManager。因为有binder发布本地接口等操作,把这些东西写到ActivityManagerService会让文件很难看。所以干脆新建立一个stub类ActivityManagerNative类好了,里面包含一些发布本地接口的操作。顺便在这个stub类定义代理类好了,节省一个文件。
几个类的关系图
类关系.png参考文章:
http://blog.csdn.net/u012950099/article/details/51987036
android的aidl-手动实现aidl自动生成的Java文件