VirtualApp拆解之二:Activity启动流程

2017-06-04  本文已影响0人  alen17

一、第一次启动插件中Activity的流程

这是指从九宫格点击第一次进入插件时的Activity启动流程。点此链接可查看高清svg图:startActivityFromLaunch

过程分拆:

1、获取插件启动的launch intent

VirtualCore的getLaunchIntent方法通过VPackageManager调用远程(:x进程)的VPackageManagerService的queryIntentActivities方法查询launch intent。

2、发送启动LoadingActivity的请求

请求参数里包含了要启动插件的包名、第一步获取的launch intent、以及由哪个用户启动的(再次申明,VirtualApp是支持多用户的)

3、在LoadingActivity的onCreate回调里做真正启动插件的工作

这个过程包含了以下几步工作

(1)、对插件做dex优化。

(2)、调用VirtualCore的resolveActivityInfo方法解析ActivityInfo,其内部还是要依赖VPackageManager调用远程(:x)进程的VPackageManagerService的相应方法。

(3)、调用VActivityManager的public int startActivity(Intent intent, ActivityInfo info, IBinder resultTo, Bundle options, String resultWho,intrequestCode,intuserId)方法,其实最终是调用了:x进程的VActivityManagerService的对应方法。

4、ActivityStack处理工作

(1)、ActivityStack会向VActivityManagerService查询可用的Stub(坑),然后调用其performStartProcessLocked方法,该方法内部又是去访问可用进程的StubContentProvider的call方法,传递的methodName为initProcess

(2)、调用VClientImpl的initProcess方法初始化该进程相关信息,如ProcessRecord和插件的vuid,其中vuid的获取参看如下代码:

/**

* Returns the vuid that is composed from the userId and the appId.

*@hide

*/

public static intgetUid(intuserId,intappId) {

if(MU_ENABLED) {

returnuserId *PER_USER_RANGE+ (appId %PER_USER_RANGE);

}else{

returnappId;

}

}

(3)、StubContentProvider的initProcess方法处理完成会返回一个Bundle,其中包含了VClientImpl的Binder对象和插件进程的pid,VActivityManagerService则会从Binder中拿到新插件进程的ApplicationThread对象并记录(为了后续处理插件Service)。

(4)、查询可用的StubActivity(占位坑),新建对应的targetIntent,并将要启动的intent信息填入targetIntent中。

5、Hook工作

(1)、启动targetIntent,会进入hooked StartActivity方法(为什么呢?只可意会),该方法发现这是要启动StubActivity,不进行特殊处理。

(2)、真正的AMS会调用插件进程的ApplicationThread的scheduleLaunchActivity方法,然后交由ActivityThread接管,它会利用注入到H的HCallbackStub解析真正要启动的Activity,并上报给VActivityManagerService。

(3)、代理ActivityThread的默认Instrumentation,重写其callActivityOnCreate方法,在这里hack真正启动起来的Activity,如ContextFixer.fixContext、ActivityFixer.fixActivity等等。

二、从插件中启动同进程的standard模式的Activity的流程

这是指在插件启动后,从插件内的Activity跳转到同进程的另一个Activity的过程。点此链接可查看高清svg图:startActivityStandardInSameProcess

过程分拆:

1、第一次Hook

在插件内启动Activity,会进入hooked StartActivity方法,该方法发现这是要启动插件内部的Activity,将解析对应的ActivityInfo,然后交由VActivityManager的public intstartActivity(Intent intent, ActivityInfo info, IBinder resultTo, Bundle options, String resultWho,intrequestCode,intuserId)方法,当然,其实最终是调用了:x进程的VActivityManagerService的对应方法。

2、ActivityStack处理工作

ActivityStack发现要启动的Activity不需要开启新进程,那么它做的事情仅是查询可用的StubActivity(占位坑),新建对应的targetIntent,并将要启动的intent信息填入targetIntent中。最后,重新调用ActivityManagerNative.getDefault.call()的startActivity方法。注意:这里的ActivityManagerNative.getDefault.call()是已经被hook的对象。

3、第二次Hook

(1)、启动第二步建立的targetIntent,会进入hooked StartActivity方法(为什么呢?只可意会),该方法发现这是要启动StubActivity,不进行特殊处理。

(2)、真正的AMS会调用插件进程的ApplicationThread的scheduleLaunchActivity方法,然后交由ActivityThread接管,它会利用注入到H的HCallbackStub解析真正要启动的Activity,并上报给VActivityManagerService。

(3)、代理ActivityThread的默认Instrumentation,重写其callActivityOnCreate方法,在这里hack真正启动起来的Activity,如ContextFixer.fixContext、ActivityFixer.fixActivity等等。

上一篇下一篇

猜你喜欢

热点阅读