最近重温了Binder机制,在此把看到的一些心得,写一写。
在这里需要先说明的一点是Client端和Server端以及后面提到的ServiceManager都处于用户空间、Binder驱动处于内核空间。
Binder是进程间通讯的一种方式。进程间的通讯方式有很多,比如Socket、管道。而Socket、管道这些需要数据的两次拷贝(Client把数据从自己的进程空间拷贝到内核空间,然后再从内核空间拷贝到Server端的进程空间,这样Server就能客户端传递的数据,这个过程经历过了两次数据拷贝)。而Binder方式只需要一次数据拷贝:只需要Client把数据拷贝到内核空间,然后将拷贝到内核空间的数据同时映射到Server进程虚拟地址空间和内核虚拟地址空间,这样经过一次数据拷贝,客户端和服务端就能进行通讯了。
注意:并不是所有的Binder服务都会注册到ServiceManager中的,像AMS、WMS、PMS这些系统的Binder服务是会注册到SM中并受SM管理的,而像bindService方式创建的Binder服务不会注册到ServiceManager中,这些注册到SM中的Binder服务称为实名Binder,不需要注册到ServiceManager中的Binder服务称之为匿名Binder,匿名Binder的传递和使用需要依赖于实名Binder。
借用网上某位大佬一张图,如图所示:
Android启动的时候会启动SystemServer进程,SystemServer进程的入口是里面的main方法:
public static void main(String[] args) {
new SystemServer().run();
}
这里又调用了SystemServer里面的run方法:
private void run() {
...
// Start services.
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
...
}
我们看这里面的startBootstrapServices()方法:
private void startBootstrapServices() {
....
// Activity manager runs the show.
traceBeginAndSlog("StartActivityManager");
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
traceEnd();
...
traceBeginAndSlog("SetSystemProcess");
mActivityManagerService.setSystemProcess();
traceEnd();
...
}
在这里,我们看到创建了ActivityManagerService对象,并通过下面的mActivityManagerService.setSystemProcess();启动了这个ActivityManagerService。
看下ActivityManagerService中的setSystemProcess()这个方法:
public void setSystemProcess() {
...
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
...
}
在这里也就是执行了ServiceManager把创建的这个ActivityManagerService对象加入了ServiceManager中创建的映射表里。
Context.ACTIVITY_SERVICE其实就是“activity”字符串。到时候我们可以通过getService(Context.ACTIVITY_SERVICE),通过这个获取到存储在映射表里面的ActivityManagerService变量。例如:
ActivityManager activityManager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager就是一个壳,它的存在避免了AMS直接暴露给应用程序,而是通过对外提供的ActivityManager来操作AMS,这样更安全,下面我们看一下ActivityManger里面的getService方法:
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
看到这里面调用了IActivityManagerSingleton的get方法,看一下IActivityManagerSingleton:
private static final Singleton IActivityManagerSingleton =
new Singleton() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
首先看下Singleton类的定义:
package android.util;
/**
* Singleton helper class for lazily initialization.
*
* Modeled after frameworks/base/include/utils/Singleton.h
*
* @hide
*/
public abstract class Singleton {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
其中get是final的方法,不可以覆盖,create是可以覆盖的。
主要看这里的两行代码:
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
这个地方是使用了AIDL的方式(Android7.0及之前,AMS通过代理模式来完成Binder通信,8.0之后,AMS通过AIDL完成Binder通信。),通过调用ServiceManager的getService方法查询出AMS的信息并转换为代理对象am。这个am对象是IActivityManager类型的,而IActivityManager是个aidl,根据aidl的规则和原理,可以知道远程服务的具体实现一定是IActivityManager.Stub的实现类,而AMS实现了IActivityManager.Stub,所以AMS是远程服务的具体实现。