android activity啟動源碼分析

一、概述

平時在Android中對activity的啟動概念僅僅停留在startactivity,對于startactivity之后系統(tǒng)有哪些行為確知曉的不多,這對于應(yīng)用行為特征分析而言,僅僅這樣是遠(yuǎn)遠(yuǎn)不夠的。因此專門跟蹤了一下源碼,分析了一下應(yīng)用啟動從應(yīng)用到framwork以及system_server的整體流程。

關(guān)鍵進(jìn)程

app進(jìn)程:調(diào)用startactivity的app進(jìn)程,普通android應(yīng)用
system_server: 系統(tǒng)服務(wù)進(jìn)程,其中activitymanager系統(tǒng)服務(wù)負(fù)責(zé)activity的管理 ,在Android 10中,activity的調(diào)度和管理已經(jīng)從AMS移到了ActivityTaskManagerService(ATMS)中
zygote:所有android應(yīng)用的父進(jìn)程。

分析設(shè)備:pixel3xl android11, sdk30

二、分析目標(biāo)

理清楚從startactivity 到activity oncreate的代碼流程。跟蹤intent在代碼中的流轉(zhuǎn),分清楚代碼邊界app,framwork,system_server(ams)的邊界。

分析從應(yīng)用側(cè)代碼開始,往系統(tǒng)層進(jìn)行代碼跟蹤。系統(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
運(yùn)行時Context實(shí)際類型是ContextImpl,去framework中找代碼實(shí)現(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


2022-10-29-16-49-23.png

execStartActivity函數(shù)中調(diào)用了系統(tǒng)服務(wù)ATMS的startactivity
接下來進(jìn)入服務(wù)端流程。

3.2 system_server代碼流程

經(jīng)過binder IPC,進(jìn)入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實(shí)例,就執(zhí)行execute方法

com.android.server.wm.ActivityStarter.execute() : int
根據(jù)源碼中的注釋,execute正式開啟activity的啟動之旅。

2022-10-29-17-12-29.png

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)實(shí)例是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
至此就正式進(jìn)入activity oncreate

四、擴(kuò)展思考

大致梳理清除activity啟動的整個流程過后,在今后分析和解決問題的時候,思路可以更加開闊了。比如:
在分析一些令人討厭的彈窗的時候,就可以通過hook ams,記錄所有的intent,callingpid,callinguid,當(dāng)彈窗出現(xiàn)就可以很快發(fā)現(xiàn)彈窗是由哪個應(yīng)用,在什么時候彈出來的。
還可以在ams對intent進(jìn)行攔截和轉(zhuǎn)發(fā)來實(shí)現(xiàn)一些高級功能,這里以第三方應(yīng)用授權(quán)登入為例。通過跨設(shè)備攔截轉(zhuǎn)發(fā)intent,可以實(shí)現(xiàn)僅一臺手機(jī)登入三方授權(quán)賬號,支持多臺手機(jī)進(jìn)行應(yīng)用三方授權(quán)登入。

五、總結(jié)

activity啟動是個比較復(fù)雜的流程,其中涉及的android知識點(diǎn)也很多。這里只是簡單的把代碼執(zhí)行流程都記錄了下來,沒過多描述具體代碼功能。后續(xù)有需要可以從感興趣的函數(shù)再展開細(xì)致分析。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容