Binder机制和Handler机制是Android中的两大核心机制,是理解Android系统的基础和关键。本文以AMS为例,简单分析下实名Binder的工作过程。
在Android中的Binder机制中,主要涉及四部分系统组件,分别是ServiceManager、Binder驱动、Client、Server,其中Client、Server、ServiceManager运行在各自的用户空间中,Binder驱动运行在内核空间中。
这里需要说明一点,并不是所有的Binder服务都会注册到SM中的,像AMS、WMS、PMS这些系统的Binder服务是会注册到SM中并受SM管理的,而像我们开发者平常通过binderService的方式创建的Binder服务是不会注册到SM中的。这些需要注册到SM中的Binder服务称之为实名Binder,不需要注册到SM中的Binder服务称之为匿名Binder,匿名Binder的传递和使用是需要依赖于实名Binder的。本文以AMS为例,来学习下实名Binder,匿名Binder会在下篇文章中结合通过Aidl和binderService创建的Binder服务来具体分析。
上图描述了应用程序客户端调用AMS进行Binder进程间通信的一个大概流程,要注意一点,AMS和SM的通信也是进程间通信的一个过程,服务的注册过程是一次IPC调用,这里图中就忽略了该过程:
Android系统启动的时候会启动SyetemServer进程,该进程的程序执行入口是SystemServer类的main方法,源码如下:
public static void main(String[] args) {
new SystemServer().run();
}
上述方法中调用了SystemServer的run方法,看下run方法的关键代码:
private void run() {
..................
try {
traceBeginAndSlog("StartServices");
//注释1 开启系统服务
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
..................
}
在注释1处会开启系统服务,跟进去startBootstrapServices()方法:
private void startBootstrapServices() {
//注释2 创建ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
traceBeginAndSlog("SetSystemProcess");
//注释3 调用了AMS的setSystemProcess方法
mActivityManagerService.setSystemProcess();
traceEnd();
}
在注释2处创建了AMS对象,在注释3处调用了AMS的setSystemProcess方法,下面跟到AMS里看下setSystemProcess方法:
public void setSystemProcess() {
//注释4
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
}
在注释4处,通过ServiceManager.addService方法将AMS注册到了ServiceManager中,第一个参数是SM注册表里对应的字符串key,Context.ACTIVITY_SERVICE的值是"activity",第二个参数this是AMS对象本身,由于AMS向SM的注册过程也是跨进程的,所以SM的注册表里存储的value是AMS的信息而不是AMS对象本身,这样当客户端需要使用AMS的时候,就可以从SM的注册表里通过字符串key(“activity”)查询到相对应的AMS服务信息了,然后在经过Binder驱动为客户端创建一个AMS的代理对象返回给客户端,这样客户端就可以通过这个代理对象去调用AMS中的方法了,其他Binder服务的通信过程同理。
在平常开发的应用程序中,有很多地方都会跟AMS打交道,其中四大组件的运行就需要依赖于AMS服务,平时通过ActivityManager调用的方法其内部都是通过调用AMS的服务来具体实现的,由于应用程序和AMS是在两个不同的进程中,所以应用程序调用AMS服务的过程是跨进程的,这里以获取应用程序运行的任务栈为例,来学习一下应用程序客户端是如何调用AMS服务的:
ActivityManager activityManager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List listInfos = activityManager.getRunningTasks(20);
上面这段代码应该很熟悉,通过context的getSystemService方法获取到ActivityManager对象,然后调用ActivityManager的getRunningTasks方法,ActivityManager就是一个壳,它的存在避免了AMS直接暴露给应用程序,而是通过对外提供的ActivityManager来操作AMS,这样更安全,下面看下ActivityManager的getRunningTasks方法:
@Deprecated
public List getRunningTasks(int maxNum)
throws SecurityException {
try {
//注释5
return getService().getTasks(maxNum);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在注释5处调用了getService()的getTasks方法,那么这个getService是什么呢?跟下这个方法的代码:
public static IActivityManager getService() {
//注释6
return IActivityManagerSingleton.get();
}
private static final Singleton IActivityManagerSingleton =
new Singleton() {
@Override
protected IActivityManager create() {
//注释7
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
在注释6处可以看到,getService方法的返回值就是IActivityManagerSingleton.get()方法的返回值,结合注释7处可以知道这个返回值就是am对象,在注释7处通过调用ServiceManager的getService方法查询出AMS的信息并转换为代理对象am。这个am对象是IActivityManager类型的,而IActivityManager是个aidl,根据aidl的规则和原理,可以知道远程服务的具体实现一定是IActivityManager.Stub的实现类,而AMS实现了IActivityManager.Stub,所以AMS是远程服务的具体实现。这里需要说明一点,Binder服务并不是我们Android中四大组件中的Service,而是能被客户端访问并具有Binder通信能力的一个功能类(比如AMS/WMS/PMS这些)。下面是AMS的继承关系源码:
//AMS继承并实现了IActivityManager.Stub
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
..................................
}
我们可以类比自己写的aidl,当我们的应用程序需要向AMS发起通信的时候,会通过IActivityManager的Proxy的transact方法发起binder通信,然后IActivityManager的Stub的onTransact方法会接收到客户端发送的远程通信请求,最终会调用到Stub的具体实现类AMS中相对应的方法进行处理,这样整个进程间通信过程就完成了,具体aidl内部的工作流程在下篇匿名Binder中,结合自己定义的aidl进行学习和梳理。