Android 8.0系统源码分析--Binder进程间通信(一)

本文深入剖析Android 8.0系统中Binder作为进程间通信(IPC)的实现,从Activity的startActivity方法入手,详细解读从Application层到ActivityManagerService之间的Binder调用流程,涉及Parcel对象的创建、BinderProxy的transact方法及native层的交互。通过对关键代码的分析,揭示Binder通信的核心原理。
摘要由CSDN通过智能技术生成

     开始我们的沉淀之路,老罗的书中第二章讲的是Android HAL层的知识,而且直接自己实现了一个虚拟的freg驱动程序,后面的几节是分别从native、java层如何访问这个虚拟的驱动程序接口,我这里没有这样的环境,所以就不分析这节了,第三章的智能指针我对比8.0系统源码和老罗的书,基本修改很小,大家如果要学习的话,就直接看老罗的书吧,这也反映出一个问题,就是我们学到的知识肯定是有用的,老罗在自己博客下面回答博友的提问时也一直在强调这点,我们学过的、学会的知识不可能浪费,没有用,肯定是有用的,即使上层再如何变化,但是涉及到核心的东西,变化也是很小的。老罗书中的第四章讲的是Log驱动的实现,对比Log来说,我们一般也就是会使用就可以了,所以也不打算在这一章节上花时间。

     那么我们就进入第五章--Binder进程间通信。这是最有分量的一节,难度也非常大,之前自己也看过老罗的Binder系列博客很久了,但是对其中的各各环节还是理解的不透,我们就从这里开始学习吧。

     老罗分析Binder进程间通信的实现时,开始讲解了很多Binder的结构体,我个人讲不清这个,我就按照自己的思路来学吧。如果大家搞过应用层的开发,相信大家都很清楚,我们使用的最多的就是Activity,它的启动过程就是一个完整的Binder调用,那么我们就以这个过程为学习路线,来分析一下startActivity的过程中Application应用层是怎么通过Binder进程间通信调用到ActivityManagerServie当中的。

     我们的入口函数当然就是Activity类的startActivity方法了。Activity类的startActivity方法实现很简单,就是直接调用两个参数的startActivity方法,此时传入的第二个参数options为空,该方法的实现如下:

@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}
    
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
    @Nullable Bundle options) {
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        if (ar != null) {
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            // If this start is requesting a result, we can avoid making
            // the activity visible until the result is received.  Setting
            // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
            // activity hidden during this time, to avoid flickering.
            // This can only be done when a result is requested because
            // that guarantees we will get information back when the
            // activity is finished, no matter what happens to it.
            mStartedActivity = true;
        }
        cancelInputsAndStartExitTransition(options);
        // TODO Consider clearing/flushing other event sources and events for child windows.
    } else {
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            // Note we want to go through this method for compatibility with
            // existing applications that may have overridden it.
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}
     按照我们正常的启动逻辑,第二个参数options为空,所以进入else分支,调用startActivityForResult来进一步处理,再次调用三个参数的同名方法,mParent变量一般为空,所以会进入第一个if分支,这里最重要的就是mInstrumentation.execStartActivity、mMainThread.sendActivityResult这两句逻辑了。mInstrumentation.execStartActivity这句就会进入到我们的目标,将Activity的启动数据封装完成后,通过binder机制发送到Server端,也就是ActivityManagerService;mMainThread.sendActivityResult这句在判断调用正常的情况下,通知应用主线程ActivityThread来处理启动后的结果,mMainThread是一个ActivityThread类型的成员变量,它是在当前的Activity启动成功后,通过应用程序主线程ActivityThread类的performLaunchActivity方法来赋值的。我们就追踪mInstrumentation.execStartActivity的实现就可以了。mInstrumentation是Activity类的成员变量,它的类型是Instrumentation,它有三个execStartActivity重名方法,而当前的调用是第四个参数为Activity类型的,该方法的实现如下:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                ActivityResult result = null;
                if (am.ignoreMatchingSpecificIntents()) {
                    result = am.onStartActivity(intent);
                }
                if (result != null) {
                    am.mHits++;
                    return result;
                } else if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(who);
        int result = ActivityManager.getService()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        checkStartActivityResult(result, intent);
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

     这个方法中最重要的就是最后的try/catch了,通过调用ActivityManager.getService().startActivity来启动目标Activity,然后调用checkStartActivityResult方法来检查启动结果。我们继续跟踪ActivityManager.getService().startActivity,它需要分两段来分析。

     第一段调用ActivityManager.getService()来获取binder代理对象,它的实现如下:

/**
 * @hide
 */
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;
            }
        };

     IActivityManagerSingleton是ActivityManager类中类型为Singleton<IActivityManager>的静态成员变量,get()方法是单例模式Singleton来实现的,当调用get()方法时,就会执行范型 T 的create()方法,Singleton类的代码如下:

public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

     ActivityManager这里以Context.ACTIVITY_SERVICE为key值获取到一个IBinder对象,然后调用IActivityManager.Stub.asInterface(b)进行转换,就会得到一个BinderProxy对象,IActivityManager.aidl文件经过编译后就会生成IActivityManager.java,但是源码中没有,我就自己写了一个ICameraService.aidl文件,然后生成对应的ICameraService.java,我们可以用它来对比分析一下,ICameraService.java源码如下:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\Work\\Project\\workstudio\\CameraService\\app\\src\\main\\aidl\\com\\huawei\\camerase
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

红-旺永福

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值