一、概述
平時在Android中對activity的啟動概念僅僅停留在startactivity论衍,對于startactivity之后系統(tǒng)有哪些行為確知曉的不多粟按,這對于應(yīng)用行為特征分析而言阻桅,僅僅這樣是遠(yuǎn)遠(yuǎn)不夠的翔烁。因此專門跟蹤了一下源碼,分析了一下應(yīng)用啟動從應(yīng)用到framwork以及system_server的整體流程友驮。
關(guān)鍵進程
app進程:調(diào)用startactivity的app進程漂羊,普通android應(yīng)用
system_server: 系統(tǒng)服務(wù)進程,其中activitymanager系統(tǒng)服務(wù)負(fù)責(zé)activity的管理 卸留,在Android 10中走越,activity的調(diào)度和管理已經(jīng)從AMS移到了ActivityTaskManagerService(ATMS)中
zygote:所有android應(yīng)用的父進程。
分析設(shè)備:pixel3xl android11, sdk30
二耻瑟、分析目標(biāo)
理清楚從startactivity 到activity oncreate的代碼流程旨指。跟蹤intent在代碼中的流轉(zhuǎn),分清楚代碼邊界app喳整,framwork谆构,system_server(ams)的邊界。
分析從應(yīng)用側(cè)代碼開始框都,往系統(tǒng)層進行代碼跟蹤搬素。系統(tǒng)層代碼可以在網(wǎng)上找到源碼,也可以從設(shè)備中提取魏保。
framework代碼在設(shè)備/system/framework/framework.jar
system_server代碼在設(shè)備/system/framework/service.
三蔗蹋、源碼跟蹤
3.1 app側(cè)代碼流程
最開始的從開發(fā)者的startactivity開始:
android.content.Context.startActivity(android.content.Intent) : void
運行時Context實際類型是ContextImpl,去framework中找代碼實現(xiàn)
android.content.ContextImpl.startActivity(android.content.Intent) : void
ContextImpl會繼續(xù)調(diào)用同名函數(shù)startActivity
android.app.ContextImpl.startActivity(android.content.Intent, android.os.Bundle) : void
@Override // android.content.Context
public void startActivity(Intent intent, Bundle options) {
this.warnIfCallingFromSystemProcess();
int targetSdkVersion = this.getApplicationInfo().targetSdkVersion;
if((intent.getFlags() & 0x10000000) == 0 && (targetSdkVersion < 24 || targetSdkVersion >= 28) && (options == null || ActivityOptions.fromBundle(options).getLaunchTaskId() == -1)) {
throw new AndroidRuntimeException("Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?");
}
this.mMainThread.getInstrumentation().execStartActivity(this.getOuterContext(), this.mMainThread.getApplicationThread(), null, null, intent, -1, options);
}
這里獲取了當(dāng)前主線程的Instrumentation囱淋,并且執(zhí)行execStartActivity方法
android.app.Instrumentation.execStartActivity(android.content.Context, android.os.IBinder, android.os.IBinder, android.app.Activity, android.content.Intent, int, android.os.Bundle) : android.app.Instrumentation$ActivityResult
execStartActivity函數(shù)中調(diào)用了系統(tǒng)服務(wù)ATMS的startactivity
接下來進入服務(wù)端流程。
3.2 system_server代碼流程
經(jīng)過binder IPC,進入atms服務(wù)端代碼流程:
com.android.server.wm.ActivityTaskManagerService.startActivity(android.app.IApplicationThread, java.lang.String, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.app.ProfilerInfo, android.os.Bundle) : int
com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(android.app.IApplicationThread, java.lang.String, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.app.ProfilerInfo, android.os.Bundle, int) : int
com.android.server.wm.ActivityTaskManagerService.startActivityAsUser(android.app.IApplicationThread, java.lang.String, java.lang.String, android.content.Intent, java.lang.String, android.os.IBinder, java.lang.String, int, int, android.app.ProfilerInfo, android.os.Bundle, int, boolean) : int
服務(wù)側(cè)會調(diào)用到startActivityAsUser餐塘,這里會通過Binder檢查調(diào)用服務(wù)對象的uid和pid妥衣,并且獲取activitystarter對象來對intent后續(xù)操作。
activitystarter理解為專門activity啟動的類,成員有activity相關(guān)數(shù)據(jù)税手,intent蜂筹,flags等描述信息。intent傳遞到了activitystarter的成員mRequest
構(gòu)造好activitystarter實例芦倒,就執(zhí)行execute方法
com.android.server.wm.ActivityStarter.execute() : int
根據(jù)源碼中的注釋艺挪,execute正式開啟activity的啟動之旅。
com.android.server.wm.ActivityStarter.executeRequest(com.android.server.wm.ActivityStarter$Request) : int
執(zhí)行actiivty啟動reqeust兵扬,其中包含應(yīng)用activity的一般檢查麻裳。
com.android.server.wm.ActivityStarter.startActivityUnchecked(com.android.server.wm.ActivityRecord, com.android.server.wm.ActivityRecord, android.service.voice.IVoiceInteractionSession, com.android.internal.app.IVoiceInteractor, int, boolean, android.app.ActivityOptions, com.android.server.wm.Task, boolean, com.android.server.uri.NeededUriGrants) : int
com.android.server.wm.ActivityStarter.startActivityInner(com.android.server.wm.ActivityRecord, com.android.server.wm.ActivityRecord, android.service.voice.IVoiceInteractionSession, com.android.internal.app.IVoiceInteractor, int, boolean, android.app.ActivityOptions, com.android.server.wm.Task, boolean, com.android.server.uri.NeededUriGrants) : int
com.android.server.wm.RootWindowContainer.resumeFocusedStacksTopActivities(com.android.server.wm.ActivityStack, com.android.server.wm.ActivityRecord, android.app.ActivityOptions) : boolean
com.android.server.wm.ActivityStack.resumeTopActivityUncheckedLocked(com.android.server.wm.ActivityRecord, android.app.ActivityOptions) : boolean
com.android.server.wm.ActivityStack.resumeTopActivityInnerLocked(com.android.server.wm.ActivityRecord, android.app.ActivityOptions) : boolean
com.android.server.wm.ActivityStackSupervisor.startSpecificActivity(com.android.server.wm.ActivityRecord, boolean, boolean) : void
com.android.server.wm.ActivityStackSupervisor.realStartActivityLocked(com.android.server.wm.ActivityRecord, com.android.server.wm.WindowProcessController, boolean, boolean) : boolean
com.android.server.wm.ClientLifecycleManager.scheduleTransaction(android.app.servertransaction.ClientTransaction) : void
3.3 再次回到app側(cè)代碼流程
ipc再次返回客戶端調(diào)用schedule
android.app.servertransaction.ClientTransaction.schedule() : void
android.app.ActivityThread$ApplicationThread.scheduleTransaction(android.app.servertransaction.ClientTransaction) : void
android.app.ClientTransactionHandler.scheduleTransaction(android.app.servertransaction.ClientTransaction) : void
android.app.ClientTransactionHandler.sendMessage(int, java.lang.Object) : void
android.app.ActivityThread.sendMessage(int, java.lang.Object) : void
這里通過一個系統(tǒng)自定義handler類型H,對應(yīng)實例是mH器钟,回到了應(yīng)用主線程
android.app.ActivityThread$H.handleMessage(android.os.Message) : void
android.app.servertransaction.TransactionExecutor.execute(android.app.servertransaction.ClientTransaction) : void
android.app.servertransaction.TransactionExecutor.executeCallbacks(android.app.servertransaction.ClientTransaction) : void
android.app.servertransaction.LaunchActivityItem.execute(android.app.ClientTransactionHandler, android.os.IBinder, android.app.servertransaction.PendingTransactionActions) : void
android.app.ActivityThread.handleLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.app.servertransaction.PendingTransactionActions, android.content.Intent) : android.app.Activity
android.app.ActivityThread.performLaunchActivity(android.app.ActivityThread$ActivityClientRecord, android.content.Intent) : android.app.Activity
android.app.Instrumentation.newActivity(java.lang.ClassLoader, java.lang.String, android.content.Intent) : android.app.Activity
android.app.Instrumentation.callActivityOnCreate(android.app.Activity, android.os.Bundle, android.os.PersistableBundle) : void
至此就正式進入activity oncreate
四津坑、擴展思考
大致梳理清除activity啟動的整個流程過后,在今后分析和解決問題的時候傲霸,思路可以更加開闊了疆瑰。比如:
在分析一些令人討厭的彈窗的時候,就可以通過hook ams昙啄,記錄所有的intent穆役,callingpid,callinguid梳凛,當(dāng)彈窗出現(xiàn)就可以很快發(fā)現(xiàn)彈窗是由哪個應(yīng)用耿币,在什么時候彈出來的。
還可以在ams對intent進行攔截和轉(zhuǎn)發(fā)來實現(xiàn)一些高級功能伶跷,這里以第三方應(yīng)用授權(quán)登入為例掰读。通過跨設(shè)備攔截轉(zhuǎn)發(fā)intent,可以實現(xiàn)僅一臺手機登入三方授權(quán)賬號叭莫,支持多臺手機進行應(yīng)用三方授權(quán)登入蹈集。
五、總結(jié)
activity啟動是個比較復(fù)雜的流程雇初,其中涉及的android知識點也很多拢肆。這里只是簡單的把代碼執(zhí)行流程都記錄了下來,沒過多描述具體代碼功能靖诗。后續(xù)有需要可以從感興趣的函數(shù)再展開細(xì)致分析郭怪。