↓雙擊 Markdown插件,就可以開始編輯啦。
APP進程
ActivityThread的啓動
public static void main(String[] args) {
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
}
在attach方法中主要做了以下重要的事情:
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
attach方法把應用進程的ApplicationThread通過IActivityManager傳遞到ActivityManagerService,而IActivityManager是ActivityManagerService系統服務在APP進程的一個代理,這個是一個跨進程的調用,最終會調用到ActivityManagerService的attachApplication方法:
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
attachApplication方法裏面又調用到:
IApplicationThread是APP進程ApplicationThread在系統進程的一個代理對象,bindApplication是一個系統進程到APP進程的跨進層調用,負責把一些初始化的數據回傳到APP進程,例如系統服務的各種Binder代理對象,bindApplication最後會調用到ApplicationThread的bindApplication方法,這裏面主要做了三件事:
- 一個是把系統服務的Binder對象緩存到ServiceManager中
- 第二個是創建LoadedApk對象,LoadedApk是應用在內存上的一個體現,包含了應用信息,資源路徑,內部文件路徑,apk路徑,receiver信息,Service信息
- 第三個是通過Handler類對象H來實現Application的創建,onCreate的回調
ActivityThread的啓動流程
App進程與AMS進程的通信過程如圖所示
系統進程
SystemServer啓動
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
在system_process進程啓動的時候就會初始化一些系統服務,例如ActivityManagerService:
APP進程啓動
通過LocalSocket來用命令的方式啓動Process
Activity啓動
Activity啓動的核心類
- ActivityThread:應用進程的啓動初始化和四大組件在應用進程的調度
- ApplicationThread:應用進程和系統進程誇進程通信的服務端
- IActivityManager:ActivityManagerService在應用進程的binder代理對象,系統進程和應用進程進行跨進程通信的客戶端
- SystemServer:系統進程的啓動初始化
- ActivityManagerService:四大組件在系統進程的調度,系統進程和應用進程進行誇進程通信的服務端
- IApplicationThread:ApplicationThread在系統進程的binder代理對象,系統進程和應用進程進行誇進程通信的客戶端
- ServiceManager:系統服務的管理
Activity啓動過程
- 通過Context的startActivity方法發起Activity的啓動
- 然後進入ContextImpl中的startActivity方法,並在該方法中通過ActivityThread獲取到Instrumentation對象,並調用execStartActivity方法
- 在execStartActivity方法中會通過IActivityManager代理對象觸發誇進程調用,把Activity的一些信息參數傳遞到系統進程ActivityManagerService中
- 在ActivityManagerService會逐層調用,然後進入ActivityStarter類中的startActivityMayWait方法,ActivityStarter會進行一些權限檢查,並創建ActivityRecord對象把Activity信息存到該對象中去
- 加下來會執行到ActivityStack中,顧名思義,這個是對Activity棧進行管理的操作
- 接着繼續執行到ActivityStackSupervisor類的startSpecificActivityLocked方法,在這個方法裏面就會去判斷當前需要啓動的Activity所在的進程是否已經存在如果存在則調用realStartActivityLocked方法,否則就startProcessAsync方法優先啓動進程
- 接下來Android8.0以後的代碼和8.0以前的代碼就有一些小差異,但是做的事情都是一樣的:通過IApplicationThread跨進程通知應用進程,並繼續在應用進程執行下一步操作
- 應用進程在收到通知後會在Handler類H中去執行Activity的創建以及回掉各個Activity的生命週期的方法(通過狀態模式來實現Activity的生命週期的切換)
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
ClientTransaction transaction) {
final int size = path.size();
for (int i = 0, state; i < size; i++) {
state = path.get(i);
if (DEBUG_RESOLVER) {
Slog.d(TAG, tId(transaction) + "Transitioning activity: "
+ getShortActivityName(r.token, mTransactionHandler)
+ " to state: " + getStateName(state));
}
switch (state) {
case ON_CREATE:
mTransactionHandler.handleLaunchActivity(r, mPendingActions,
null /* customIntent */);
break;
case ON_START:
mTransactionHandler.handleStartActivity(r, mPendingActions);
break;
case ON_RESUME:
mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
break;
case ON_PAUSE:
mTransactionHandler.handlePauseActivity(r.token, false /* finished */,
false /* userLeaving */, 0 /* configChanges */, mPendingActions,
"LIFECYCLER_PAUSE_ACTIVITY");
break;
case ON_STOP:
mTransactionHandler.handleStopActivity(r.token, false /* show */,
0 /* configChanges */, mPendingActions, false /* finalStateRequest */,
"LIFECYCLER_STOP_ACTIVITY");
break;
case ON_DESTROY:
mTransactionHandler.handleDestroyActivity(r.token, false /* finishing */,
0 /* configChanges */, false /* getNonConfigInstance */,
"performLifecycleSequence. cycling to:" + path.get(size - 1));
break;
case ON_RESTART:
mTransactionHandler.performRestartActivity(r.token, false /* start */);
break;
default:
throw new IllegalArgumentException("Unexpected lifecycle state: " + state);
}
}
}
- 這裏注意一個誤區,Activity的啓動計時是以onWindowFocused爲準而不是以onResume爲準,應爲onResume執行完了之後,Activity才添加到Window中並進行進行界面佈局的繪製,至此Activity的啓動基本完成
Activity啓動流程總結
- Activity啓動過程中其實就是應用進程和系統進程通過AIDL來進行雙向跨進程通信的一個過程
解決ActivityNotFoundException問題
爲什麼會有ActivityNotFoundException這個異常
- Activity需要在配置文件中註冊,然後在系統進程中對配置文件中的Activity進行檢測,如果發現Activity沒有註冊就會返回一個錯誤的結果,然後在Instrumentation類的checkStartActivityResult方法中會拋出這個異常
實現插件化啓動Activity如何解決這個問題?
- Activity的信息類是被裝在Intent中傳遞給ActivityManagerService中的,然後在ActivityManagerService去對Activity信息進行檢測,如果我們想啓動一個沒有註冊過的Activity可以在應用進程的某一處節點hook掉,把我們要啓動的目標Activity替換成已經註冊好的Activity,這樣在系統進程進行Activity檢測的時候就可以騙過去
- 系統進程完成Activity檢測後會再回傳到應用進程,然後根據Activity信息來創建Activity類並執行生命週期的方法,所以我們可以在應用進程的某一處節點再hook一下,把Activity類信息替換回我們想要啓動的目標Activity,這樣就可以啓動未註冊過的Activity而不報錯
如何尋找Hook點?
- 由於我們鎖需要hook的地方都是在應用進程的,所以應用進程的hook我們是可以輕鬆的通過Java反射,動態代理來進行攔截的
- Hook的原則是靜態變量或者單例對象,儘量Hook pulic的對象和方法,非public不保證每個版本都一樣,需要適配
Activity啓動流程的hook點(針對Android9.0以上)
- ActivityManager的IActivityManagerSingleton屬性
hook代碼:
Method getServiceMethod = ActivityManager.class.getDeclaredMethod("getService");
getServiceMethod.setAccessible(true);
Object iActivityManagerObj = getServiceMethod.invoke(ActivityManager.class, null);
Field IActivityManagerSingleton = ActivityManager.class.getDeclaredField("IActivityManagerSingleton");
IActivityManagerSingleton.setAccessible(true);
Object IActivityManagerSingletonObj = IActivityManagerSingleton.get(ActivityManager.class);
Class<?> singletonCls = Class.forName("android.util.Singleton");
Field mInstance = singletonCls.getDeclaredField("mInstance");
mInstance.setAccessible(true);
Class<?> iActivityManagerInterface = Class.forName("android.app.IActivityManager");
Object iActivityManagerProxy = Proxy.newProxyInstance(ActivityManager.class.getClassLoader()
, new Class<?>[]{iActivityManagerInterface}, new IActivityManagerHandler(iActivityManagerObj));
mInstance.set(IActivityManagerSingletonObj, iActivityManagerProxy);
-
用Java動態代理把Activity信息替換成代理Activity
-
通過hook Handle的Callback來攔截回傳Activity的信息,並換回我們要啓動的Activity