从应用中的Binder谈起

一、前言

要自顶向下的介绍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。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页