最近出于提升专业技能水平和深入了解Android系统的目的,进行了插件化相关的学习并简单写了一些demo。但是在写动态hook系统SDK实现启动插件化activity的过程当中遇到了一些问题,特此记录,与大家一起分享我的学习经验。

首先先放一张图,图片来自:https://juejin.im/post/6844903965679681549【追根究底】Android的startActivity源码到底咋写的?

类似的图片只要使用搜索引擎检索startactivity源码分析,很容易找到许多类似的图片。但是很多图片往往都在细节上有所不同,这不禁引发了博主的好奇心:为啥这么多大佬画的图还能出现各种版本呢?

经过https://cs.android.com/检索源码发现,主要是Android版本之间的差异。

很多大佬写文章或者画图的时候其实都是出于记录,没有详细地说明查阅的源码版本,而Android的版本更新迭代速度非常之快,造成了各种startactivity的流程之间有所差异,以下记录若干版本的startactivity的流程供参考。

此处引用https://blog.csdn.net/qianxiangsen/article/details/81352563的图片:

【追根究底】Android的startActivity源码到底咋写的?

不难发现其实执行activity的startactivity方法在我查阅的版本当中都会走向ContextImpl的startactivity方法,而该方法都会调用mInstrumentation的execStartActivity方法,关于Instrumentation是如何创建的此处不展开,请自行查阅。

execStartActivity方法开始,不同的Android版本出现了许多不同的实现,特此记录若干博主选取的经典版本。

版本1:android-5.1.1_r38

该版本Instrumentation总共包含三个参数列表不同的execStartActivity方法,最终都指向ActivityManagerNative,截取代码示例如下:

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess();
        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);
    } catch (RemoteException e) {
    }
    return null;
}

可以明显看到ActivityManagerNative是真正的执行者,查阅ActivityManagerNative的方法得到不同参数列表的方法最后都走了mRemote的方法执行,选取代码示例如下:

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
                         String resolvedType, IBinder resultTo, String resultWho, int requestCode,
                         int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    data.writeString(callingPackage);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo);
    data.writeString(resultWho);
    data.writeInt(requestCode);
    data.writeInt(startFlags);
    if (profilerInfo != null) {
        data.writeInt(1);
        profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        data.writeInt(0);
    }
    if (options != null) {
        data.writeInt(1);
        options.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
    reply.readException();
    int result = reply.readInt();
    reply.recycle();
    data.recycle();
    return result;
}

查阅mRemote发现使用了Binder进行通信,通信对象为AMS。

版本2:android-6.0.1_r82

同上。

版本3:android-7.1.2_r36

同上。

版本4:android-8.1.0-r62

出现差异,instrumentaion和AMS的通信方法修改为:

int result = ActivityManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null ? target.mEmbeddedID : null,
                requestCode, 0, null, options);

可以看到不再直接使用Binder通信,而是通过标准化的service来进行对AMS的获取。

版本5:android-9.0.0_r34

同上。

版本6:android-10.0.0_r30

int result = ActivityTaskManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent,
                intent.resolveTypeIfNeeded(who.getContentResolver()),
                token, target != null ? target.mEmbeddedID : null,
                requestCode, 0, null, options);

出现差异,可以看到ActivityManager被ActivityTaskManager取代。

版本7:android-11.0.0_r3

同上。

相关文章:

  • 2022-02-25
  • 2021-12-05
  • 2021-07-15
  • 2021-06-19
  • 2021-10-08
  • 2021-09-10
  • 2021-09-23
猜你喜欢
  • 2021-07-07
  • 2022-01-10
  • 2022-01-05
  • 2021-09-02
  • 2021-09-24
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案