android activity啟動源碼分析

一、概述

平時在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


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

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的啟動之旅。

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)實例是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ì)致分析郭怪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市刊橘,隨后出現(xiàn)的幾起案子鄙才,更是在濱河造成了極大的恐慌,老刑警劉巖促绵,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件攒庵,死亡現(xiàn)場離奇詭異嘴纺,居然都是意外死亡,警方通過查閱死者的電腦和手機浓冒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門栽渴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人稳懒,你說我怎么就攤上這事闲擦。” “怎么了场梆?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵墅冷,是天一觀的道長。 經(jīng)常有香客問我辙谜,道長俺榆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任装哆,我火速辦了婚禮罐脊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蜕琴。我一直安慰自己萍桌,他們只是感情好樱哼,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布沐兵。 她就那樣靜靜地躺著,像睡著了一般蕊程。 火紅的嫁衣襯著肌膚如雪雏搂。 梳的紋絲不亂的頭發(fā)上藕施,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音凸郑,去河邊找鬼裳食。 笑死,一個胖子當(dāng)著我的面吹牛芙沥,可吹牛的內(nèi)容都是我干的诲祸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼而昨,長吁一口氣:“原來是場噩夢啊……” “哼救氯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起歌憨,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤着憨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后务嫡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體享扔,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡底桂,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了惧眠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡于个,死狀恐怖氛魁,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情厅篓,我是刑警寧澤秀存,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站羽氮,受9級特大地震影響或链,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜档押,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一澳盐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧令宿,春花似錦叼耙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至癞松,卻和暖如春爽撒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背响蓉。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工硕勿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厕妖。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓首尼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親言秸。 傳聞我的和親對象是個殘疾皇子软能,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容