Binder进程见通信是通过远程代理
来实现的,SystemServer进程
和APP用户进程
使用Binder进行通信,必须建立双向的代理绑定,即:一个进程即使客户端也是服务端,这样才能实现双工通道
:
只有持有对方进程的代理对象,才能通过代理对象控制真实对象做事情,代理对象必须是一个Binder接口,因为它要依赖Binder帮我们做底层的进程间的数据传递,下面从源码分析下,这个双向代理的建立过程:
App进程创建AMS代理 (APP作为客户端)
上一篇文章介绍了ams的创建的具体细节,在 startBootstrapServices ()
开启引导服务这个方法的分析4中:调用了AMS的setSystemProcess()
这个方法,在这个方法中,将我们的SystemServer进程(从APP进程的角度:远程进程,服务端进程)
的各种服务(包括AMS本身)
都添加到ServiceManager
这个类中:
public void setSystemProcess() {
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_HIGH);
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(this),
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
}
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
}
不知道大家在学习Bidner的时候也没有关注到ServiceManager这个东西,简单在过一下Binder吧:
Binder通信模型中有四个东西:
Binder驱动:谷歌在linux层面嵌入的一个插件/驱动,实现进程间通信的底层细节,比如调用mmap实现内存映射,调用copy_from_user实现内存拷贝;
ServiceManager:本质是一个进程,由Binder驱动控制,它的作用是维护了一张表service_manager表
,这张表里面存放了所有的服务端进程的记录(具体记录的是什么我忘了,类似具柄引用什么的)
客户端进程:进程通信的C端进程
服务端进程:进程通信的S端进程
首先服务端进程向Binder驱动申请成为服务端,那么服务端进程就会存放到ServiceManager这张表中,当客户端需要通信时,可以向Binder驱动申请查询对应的服务端,如果查询到,就会返回一个服务端的代理给客户端,那么客户端就可以通过这个代理去让服务端的真实对象做事情;
在这里的Servicemanager添加的各种服务,就会被添加到ServiceManager进程的service_manager
表中,这样就完成了服务端(SystemServer进程的服务)
的注册;
App创建AMS代理:
在AMS的setSystemProcess中想ServiceManager表中注册了之后,就可以通过ServiceManager.getService()向Binder驱动申请获取这个服务的IBinder对象:
IBinder b = ServiceManager.getService("activity");
在APP进程,AMS的代理是一个叫做iActivityManager
的对象,这个玩意儿在7.0和8.0还不一样,我们先看7.0的版本:
在7.0中又一个ActivityManagerNative
类,用户进程在startActivity的时候(具体是在Instrumentation.execStartActivity的时候,不清楚的可以看前面的文章)
,会调用AMN的getDefault()获取AMS的代理:ActivityManagerProxy对象;(这个ActivityManagerProxy是IActivityManager的子类)
Instrumentation.execStartActivity():
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
ActivityManagerNative.getDefault():
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
IActivityManager am = asInterface(b);
return am;
}
};
static public IActivityManager asInterface(IBinder obj) {
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
return new ActivityManagerProxy(obj);
}
这里的逻辑也非常简单,首先通过ServiceManager.getService()
向底层的Binder注册表service_manager
查询AMS的IBinder对象,然后将AMS的iBinder对象封装到ActivityManagerProxy中:
class ActivityManagerProxy implements IActivityManager{
public ActivityManagerProxy(IBinder remote)
{
mRemote = remote;
}
}
- AMN是服务端进程(SystemServer)的,它实现了Binder接口,iActivityManager接口,
AMS是其的子类
;AMN作为服务端被代理的对象,所有的实际功能都是尤其子类AMS实现的; - AMP是客户端进程的,拥有一个Binder成员变量(AMS的iBinder对象,从ServiceManager表中查询到的代理对象),AMP作为客户端的代理对象,它通过mRemote调用的方法都会代理到服务端的AMN中,而AMS继承了AMN,所以最终都是由AMS进程处理的;
Instrumentation.execStartActivity():
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
ActivityManager.getService():
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
这里的处理方式和7.0如出一辙,首先通过ServiceManager获取ams的iBinder对象,然后通过这个对象构造出一个iActivityManager对象;
-
IActivityManager是一个aidl接口,它编译后会生成一个对应的java类,这个类有一个内部类Stub,要实现跨进程通信只要服务端继承iActivityManager.Stub就好;
-
服务端的AMS继承iActivityManager.Stub后,就可以和客户端的ActivityManager实现跨进程通信
public class ActivityManagerService extends IActivityManager.Stub
SystemServer 进程创建App进程的代理 (SystemServer进程作为客户端)
回忆一下用户进程的入口ActivityThread的main中的初始化做了哪些事情:
public static void main(String[] args) {
Looper.prepareMainLooper();
thread.attach(false, startSeq);
Looper.loop();
}
重点关注ActivityThread的attach() :
ActivityThread.attach():
private void attach(boolean system, long startSeq) {
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
}
这里调用了AMS在用户进程的代理iActivityManager
的attachApplication(),会执行AMS的attachApplication():注意这里传入的参数,是当前ActivityThread的ApplicationThread对象,ApplicationThread是ActivityThread的内部类,继承了IApplicationThread.Stub
public final class ActivityThread extends ClientTransactionHandler {
final ApplicationThread mAppThread = new ApplicationThread();
private class ApplicationThread extends IApplicationThread.Stub { }
}
我们在看看传给AMS后,AMS做了什么事情:
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
}
}
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
// 分析1
app.makeActive(thread, mProcessStats);
// 分析2
thread.bindApplication(processName, appInfo, providers,
app.instr.mClass,
profilerInfo, app.instr.mArguments,
app.instr.mWatcher,
app.instr.mUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(getGlobalConfiguration()), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial);
}
-
app是一个ProcessRecord对象,ProcessRecord是AMS的一个内部类,是对一个进程的封装,包含了一个用户进程的所有信息;将用户进程传入的
ApplicationThread对象
通过makeActive()保存到ProcessRecord中,以后当AMS需要向APP发起Binder通信时,就可以直接通过app.thread发起一次Binder通信; -
这里就是发起了一次Binder,最终会调用服务端(APP进程)ApplicationThread的bindApplication(); 在这里App进程就知道刚刚发起的attach成功了;
整体梳理:
- 在AMS构造的时候,会调用ServiceManager.addService()将SystemServer进程的各种需要跨进程的服务保存起来,本质是保存到Binder驱动确定的ServiceManager进程的
service_manager
表中; - Binder通信的本质是通过客户端代理和服务端真实对象实现的,所以AMS进程和APP进程需要实现双工通信,必须同时是客户端和服务端(即有代理对象也有真实对象)
-
App进程作为客户端,AMS作为服务端:
首先通过ServiceManager.getService()获取AMS的Binder对象;然后对这个对象封装到ActivityManagerProxy中,这个AMP就是AMS在APP进程本地的代理; -
App进程作为服务端,AMS作为客户端:
在APP的入口main中通过AMS在本地的代理发起一次Binder通信,将本地的Binder(ApplicationThread)发送给AMS进程,AMS接收到了以后将其保存在自己的ProcessRecord中,以后当AMS需要向APP发起跨进程通信时,只需要通过ProcessRecord中保存的APP进程的代理即可;
网友评论