一、第一次啟動插件中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等等。