一、前言
要自顶向下的介绍Binder,那么我们需要先从日常开发中接触到的Binder组件说起,对于应用开发来说Binder的存在是透明的,我们可能在不经意间就通过Binder完成了一系列操作,接下来我将会介绍和应用开发和Binder关系最为紧密的部分,以次让读者对Binder的在系统中的存在有初步的认识和了解。
二、Activity的启动
Activity启动的时候是我第一个想到的使用Binder的场景,这是我们开发中最频繁使用的功能,接下来我们看看我潜入到Activity启动中看看Binder如何扮演角色,我们不关心具体启动过程中的Activity的具体细节,只看Binder相关部分即可。
~一大波代码即将来袭
//frameworks/base/core/java/android/app/Activity.java
@Override
public void startActivity(Intent intent) {
startActivity(intent, null);
}
这个认识吧,就位于Activity中,不多做解释,传递的参数为Intent,关于Intent,我们知道它是用来在组件之间传递参数的,但更深刻的理解是,从Binder层面来讲,它是一个Parcelable,那么什么又是Parcelable呢?这里我先简单说下,Parcelable是一个接口,继承了Parcelable就意味着可以将对象的数据写入到Parcel中,那么什么又是Parcel呢?Parcel呢,可以理解为Binder通信过程中用来规范传递的数据。好了到此为此,不做详细的介绍了,后面的文章再说吧,回到正题。
//frameworks/base/core/java/android/app/Activity.java
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
....
}
跟踪代码可以发现,无论是startActivity还是startActivityForResult最终都会调用这个方法来进行启动,这里通过Instrumentation的execStartActivity来完成启动Activity。
//frameworks/base/core/java/android/app/Instrumentation.java
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
return null;
}
来到Instrumentation中,我们看看execStartActivity的实现,我把其他和主线不相关的代码都删掉了,这里我们也不要管 Instrumentation是什么了(打死我也不会说的=_=,它真的和我们的主线没什么关系),记住只有Binder才是我们需要关注的,只有Binder,其他统统不要管,记住!
从实现来看它通过ActivityManagerNative的startActivity来启动Activity。这个ActivityManagerNative是什么呢?我先声明下,事实上到这里就算是一条分割线,这条分割线的上层就是我们的应用,准确来说是应用进程,而分割线的下层就是Binder Server进程,这个进程就是system_server进程,里面有众多的Binder Server,一个进程有可能不止一个Binder Server哦,完成Activity启动的Binder Server我们叫它ActivityManagerServer,小名AMS。我们从不同的角度看这里,可能是Binder的C/S进程,也可以是系统层面的架构,应用层/Framework层。所谓的IPC跨进程通信在这里就是从我们开发的应用进程调系统进程system_server进程的Binder服务来完成一系列的事务再返回,这个过程对应用进程来说是无感的,即我们可以像调用类的方法那样就可以完成进程通信,即Binder模糊了进程边界。至于这些Binder进程通信的细节是本系列文章的主要任务,我们将拨云开雾深刻的理解这之间到底发生了什么。
三、service的启动
//frameworks/base/core/java/android/app/ContextImpl.java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags) {
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, Process.myUserHandle());
}
再来看看service的启动
private ComponentName startServiceCommon(Intent service, UserHandle user) {
...
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
...
}
private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
UserHandle user) {
...
int res = ActivityManagerNative.getDefault().bindService(
mMainThread.getApplicationThread(), getActivityToken(),
service, service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, user.getIdentifier());
...
}
是不是又看到了熟悉的面孔,没错又是ActivityManagerNative,可见service启动过程和AMS的关系也很大啊,同样的不要关注具体的细节实现,这里又同样的是一个类似的分割线,分割了Binder的C/S端。实时上在framework中我们可以看到许多类似的代码, 如XXXNatvie.getDefault这就是要通过Binder来进行IPC通信了。
四、广播的注册
//frameworks/base/core/java/android/app/ContextImpl.java
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
return registerReceiver(receiver, filter, null, null);
}
再来看看广播,这是要把四大组件说完?没错,机智的小伙,不这么做你可能不信啊,凭什么说Binder就是Android IPC的骨骼架构啊,我怎么看不到它在哪里用到呢。这些就是让你相信,我真的没撒谎哈哈!
//frameworks/base/core/java/android/app/ContextImpl.java
private Intent registerReceiverInternal(BroadcastReceiver receiver, int userId,
IntentFilter filter, String broadcastPermission,
Handler scheduler, Context context) {
...
return ActivityManagerNative.getDefault().registerReceiver(
mMainThread.getApplicationThread(), mBasePackageName,
rd, filter, broadcastPermission, userId);
...
}
又是老伙计,不多做介绍了。
五、ContentProvider的查询
@Override
//frameworks/base/core/java/android/app/ContextImpl.java
public ContentResolver getContentResolver() {
return mContentResolver;
}
ContentResolver是ContentProvider的服务接口。你懂的!
public final Cursor query(final Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
CancellationSignal cancellationSignal) {
....
IContentProvider unstableProvider = acquireUnstableProvider(uri);
...
stableProvider = acquireProvider(uri);
....
}
这里我们看查询的操作即可。
public final IContentProvider acquireProvider(
Context c, String auth, int userId, boolean stable) {
final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);
...
try {
holder = ActivityManagerNative.getDefault().getContentProvider(
getApplicationThread(), auth, userId, stable);
} catch (RemoteException ex) {
}
...
}
又是这货,看完四大组件,我们应该大概有个认识就是Binder和四大组件有莫大的关系,同时AMS作为Binder Server一方和四大组件也有很大的关系,它可不止和Activity组件相关哦。这里虽然我们还没见到Binder的面孔,但接下来的系列篇章我们都会基于此更加深入的介绍关于Binder的内容。
六、总结
实际上,不止四大组件,这里仅仅挑选几个最具代表的和Binder相关的开发组件进行介绍,还有一些如AIDL,我们常用的getSystemService方法,摄像头预览,播放音乐等等,这些都离不开Binder的支持,总的来说,你只需记住,在Android系统中有服务进程的地方就有Binder。