天天看點

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

在我的上一篇文章:

AJie:按下電源鍵後竟然發生了這一幕 —— Android 系統啟動流程分析​zhuanlan.zhihu.com

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

我們分析了系統在開機以後的一系列行為,其中最後一階段 AMS(ActivityManagerService) 會啟動 Launcher 來展示我們手機中所有已安裝的應用圖示,點選圖示後相應的應用程式将會被系統啟動運作并展示在我們面前,那麼,點選了圖示之後系統道理做了哪些工作呢?應用程序是怎麼被啟動的呢?Activity 的生命周期是什麼時候被誰調用的呢?本文将繼續基于 Android Nougat 的 frameworks 層源碼的解答這些問題。

閱讀建議:

如果你是首次閱讀這個過程的源碼,建議你忽略一些細枝末節的代碼,先抓主幹代碼,從整體上了解代碼的執行流程(右下角文章目錄視圖中可以點選跳轉到相應章節),否則将會被細節的代碼擾亂思路。最後可以回頭多看幾遍,這時候如果有需要可以追蹤一些枝幹代碼,做到融會貫通。

1. Launcher —— AMS

1.1 調用過程分析

1.1.1 Launcher.onClick

在 Launcher app 的主 Activity —— Launcher.java 中,App 圖示的點選事件最終會回調 Launcher.java 中的 onClick 方法,

packages/apps/Launcher3/src/com/android/launcher3/Launcher.java:

public 
           

1.1.2 Launcher.onClickAppShortcut

如果是快捷方式圖示,則調用 onClickAppShortcut 方法進而調用 startAppShortcutOrInfoActivity 方法:

@Thunk 
           

1.1.3 Launcher.startActivity

擷取相應 App 的 Intent 資訊之後,調用 startActivity 方法:

private 
           

1.1.4 Activity.startActivity

這裡最終調用了 Activity 中的 startActivity 方法,并且設定 Flag 為 FLAG_ACTIVITY_NEW_TASK。到此為止,已經跟啟動普通的 Activity 流程彙合起來了,繼續往下分析。

frameworks/base/core/java/android/app/Activity.java:

@Override
           

1.1.5 Activity.startActivityForResult

調用 Activity 的 startActivityForResult 方法

public 
           

1.1.6 Instrumentation.execStartActivity

frameworks/base/core/java/android/app/Instrumentation.java:

public 
           

1.1.7 ActivityManagerProxy.startActivity

以上過程是在 Launcher App 所在的程序中發生的,在我的另外一篇文章

AJie:借助 AIDL 了解 Android Binder 機制——AIDL 的使用和原理分析​zhuanlan.zhihu.com

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

中我們分析了 AIDL 的實作過程,由于遠端 Service 跟使用 Service 的 Activity 不在同一個程序中,是以他們之間互動需要通過 Binder IPC 機制的支援,在這個過程中Client 首先擷取到 Server 端的代理對象,在 Client 看來 Server 代理對象同樣具有 Server 本地對象承諾的能力,是以 Client 可以調用 Server 代理對象跟 Sever 本地對象進行資料互動,Binder 驅動作為橋梁在他們中間起到中間人的作用。

在Android 系統啟動流程分析中曾經分析過,AMS 是運作在 system_server 線程中的,這時 AMS 就相當于 AIDL 中的遠端 Service,App 程序要與 AMS 互動,需要通過 AMS 的代理對象 AMP(ActivityManagerProxy) 來完成,來看 ActivityManagerNative.getDefault() 拿到的是什麼:

frameworks/base/core/java/android/app/ActivityManagerNative.java:

static 
           

getDefault 是一個靜态變量:

private 
           

同樣,在文章

AJie:借助 AIDL 了解 Android Binder 機制——Binder 來龍去脈​zhuanlan.zhihu.com

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

中也講到過:

ServiceManager 是 Binder IPC 通信過程的核心,是上下文的管理者,Binder 服務端必須先向 ServerManager 注冊才能夠為用戶端提供服務,Binder 用戶端在與服務端通信之前需要從 ServerManager 中查找并擷取 Binder 服務端的引用。

這裡通過 "activity" 這個名字向 ServiceManager 查詢 AMS 的引用,擷取 AMS 的引用後,調用 asInterface 方法:

static 
           

因為 AMS 與 Launcher App 不在同一個程序中,這裡傳回的 IBinder 對象是一個 Binder 代理對象,是以這類将其包裝成 AMP(ActivityManagerProxy) 對象并傳回,AMP 是 AMN(ActivityManagerNative) 的内部類,檢視 AMP 類 :

class 
           

可以看到,AMP 裡面将用戶端的請求通過 mRemote.transact 進行轉發,mRemote 對象正是 Binder 驅動傳回來的 Binder Proxy 對象,通過 Binder Proxy,Binder 驅動最終将調用處于 Binder Server 端 AMN 中的 onTransact 方法:

@Override
           

1.1.8 ActivityManagerService.startActivity

AMN 是一個抽象類,它的 startActivity 為抽象方法,具體的實作在 frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java 中:

@Override
           

1.2 小結

從 Launcher App 到 AMS 的調用過程中使用了 Binder IPC 機制,如果你已經看了上面提到的我之前寫的兩篇文章——借助 AIDL 了解 Android Binder 機制——Binder 來龍去脈和借助 AIDL 了解 Android Binder 機制——AIDL 的使用和原理分析,并且運作了文章中使用到的 Demo,你應該可以發現,相對于 AIDL 的調用過程,調用方 Launcher App 相當于 AIDL 過程中的 Activity 所在的 App,充當 Clinent 的角色;AMS 相當于遠端 Service 的角色,充當 Server 端角色,他們的調用過程總體上都是一樣的。

從 Launcher App 到 AMS 的時序圖如下:

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

2. AMS —— zygote

2.1 調用過程分析

2.1.1 ActivityManagerService.startActivityAsUser

接着從 AMS 的 startActivityAsUser 方法開始分析:

@Override
           

2.1.2 ActivityStarter.startActivityMayWait

繼續跟進 frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java:

final 
           

2.1.3 ActivityStarter.startActivityLocked

檢視 startActivityLocked 方法:

final 
           

2.1.4 ActivityStarter.doPendingActivityLaunchesLocked

檢視 doPendingActivityLaunchesLocked 方法:

final 
           

2.1.5 ActivityStarter.startActivityUnchecked

檢視 startActivityUnchecked 方法:

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {
    ...  
    // 調用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法
    mSupervisor.resumeFocusedStackTopActivityLocked();  
    ... 
    return START_SUCCESS;
}
           

2.1.6 ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java:

boolean 
           

2.1.7 ActivityStack.resumeTopActivityUncheckedLocked

檢視 ActivityStack 的 resumeTopActivityUncheckedLocked 方法:

boolean 
           

2.1.8 ActivityStack.resumeTopActivityInnerLocked

檢視 resumeTopActivityInnerLocked 方法:

private 
           

2.1.9 ActivityStackSupervisor.startSpecificActivityLocked

回到 ActivityStackSupervisor 的 startSpecificActivityLocked 方法:

void 
           

首先,在方法中擷取了目前 Activity 附屬的 Application,如果已經在運作了,說明這個 App 是已經被啟動過了的,這時候調用

realStartActivityLocked

方法就可以進入下一步的流程了,同一個 App 中不同 Activity 的互相啟動就是走的這個流程。當 Application 沒有運作的時候,就需要調用 AMS 的 startProcessLocked 方法啟動一個程序去承載它然後完成後續的工作,順便鋪墊一下,當新程序被啟動完成後還會調用回到這個方法,檢視 AMS 的 startProcessLocked 方法:

2.1.10 ActivityManagerService.startProcessLocked

final 
           

2.1.11 ActivityManagerService.startProcessLocked

調用 startProcessLocked 方法:

final 
           

2.1.12 ActivityManagerService.startProcessLocked

調用 startProcessLocked 的重載方法:

private 
           

2.1.13 Process.start

frameworks/base/services/core/java/android/os/Process.java:

public 
           

2.1.14 Process.startViaZygote

檢視 startViaZygote 方法:

private 
           

2.1.15 Process.zygoteSendArgsAndGetResult、Process.openZygoteSocketIfNeeded

檢視 zygoteSendArgsAndGetResult 方法:

private 
           

在 zygoteSendArgsAndGetResult 中等待 Socket 服務端,也就是 zygote 程序傳回建立新程序的結果,這裡 zygoteState 參數是由 openZygoteSocketIfNeeded 方法傳回的,openZygoteSocketIfNeeded 方法則負責根據 abi 向 Zygote 程序發起連接配接請求:

private 
           

2.2 小結

如果是從桌面新啟動一個 App 中的 Activity,此時是沒有程序去承載這個 App 的,是以需要通過 AMS 向 zygote 繼承發起請求去完成這個任務,AMS 運作在 system_server 程序中,它通過 Socket 向 zygote 發起 fock 程序的請求,從 AMS 開始的調用時序圖如下:

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

3. zygote —— ActivityThread

3.1 調用過程分析

3.1.1 ZygoteInit.main

在 Android 系統啟動流程分析 文中提到過 zygote 程序的其中一項任務就是:

調用 registerZygoteSocket() 函數建立 Socket 通道,使 zygote 程序成為 Socket 服務端,并通過 runSelectLoop() 函數等待 ActivityManagerService 發送請求建立新的應用程式程序。

zygote 終于要再次上場了!接下來從 ZygoteInit.java 的 main 方法開始回顧一下 zygote 程序的工作:

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:

public 
           

3.1.2 ZygoteInit.runSelectLoop

檢視 runSelectLoop 方法:

private 
           

3.1.3 ZygoteConnection.runOnce

檢視 frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java 的 runOnce 方法:

boolean 
           

3.1.4 ZygoteConnection.handleChildProc

首先解析 Socket 用戶端傳過來的參數,Zygote.java 的 forkAndSpecialize 傳回的 pid == 0 的時候表示此時在 fock 出來的子程序中執行,繼續調用 handleChildProc 方法,并将參數繼續層層傳遞:

private 
           

3.1.5 RuntimeInit.zygoteInit

檢視 frameworks/base/core/java/com/android/internal/os/RuntimeInit.java 的 zygoteInit 方法:

public 
           

3.1.6 RuntimeInit.applicationInit

繼續調用 applicationInit 方法:

private 
           

3.1.7 RuntimeInit.invokeStaticMain

主要調用了 invokeStaticMain 方法:

private 
           

3.1.8 MethodAndArgsCaller.run

回到 ZygoteInit 的 main 方法:

public 
           

跟 system_server 程序的啟動過程一樣,這裡同樣通過抛出異常的方式來清空調用 ActivityThread.main 之前的方法棧幀。

ZygoteInit 的 MethodAndArgsCaller 類是一個 Exception 類,同時也實作了 Runnable 接口:

public 
           

3.1.9 ActivityThread .main

最後通過反射調用到 ActivityThread 的 main 方法:

public 
           

3.2 小結

zygote 程序作為 Socket 服務端在接收到作為用戶端的 AMS 發送過來的請求和參數之後,fock 出新的程序并根據各種參數程序了初始化的工作,這個過程和 zygote 啟動 system_server 程序的過程如出一轍,時序圖如下所示:

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

4. ActivityThread —— Activity

4.1 調用過程分析

4.1.1 ActivityThread.attach

上一小節的最後,ActivityThread 的 main 通過反射被運作起來了,接着會調用 ActivityThread 的 attach 方法:

private 
           

這裡,我們再一次通過 Binder IPC 機制跟 AMS 通信,通信模型跟前面 Launcher App 調用 AMS 的 startActivity 方法一樣,getDefault 過程不重複分析,這次是調用了 AMS 的 attachApplication 方法,注意這裡将 ApplicationThead 類型的 mAppThread 對象作為參數傳遞了過去,ApplicationThead 是 ActivityThread 的一個内部類,後面我們會講到,先檢視 AMP 的 attachApplication 方法:

4.1.2 ActivityManagerProxy.attachApplication

public 
           

4.1.3 ActivityManagerNative.onTransact

public 
           

asInterface 将 ActivityThread 對象轉換成了 ApplicationThreadNative(ATN) 的 Binder 代理對象 ApplicationThreadProxy(ATP),并作為參數傳給 attachApplication 方法,其中 ATP 是 ATN 的内部類。

4.1.4 ActivityManagerService.attachApplication

public 
           

4.1.5 ActivityManagerService.attachApplicationLocked

private 
           

首先,通過 ATP 使用 Binder 向 ATN 發起 bindApplication 請求,然後通過 normalMode 字段判斷是否為 Activity,如果是則執行 ActivityStackSupervisor 的 attachApplicationLocked 方法。

4.1.5.1 ActivityThread.java::ApplicationThread.bindApplication

thread 對象類型是 ATP,通過 Binder 驅動調到了 ATN 的方法,ATN 是一個抽象類,它的實作都委托給了 ApplicationThread(這跟 AMS 跟 AMN 的關系一樣),ApplicationThread 作為 ActivityThread 的内部類存在,它的 binderApplication 方法如下:

ActivityThread.java::ApplicationThread:

public 
           

H 是 ActivityThread 中的一個 Handler 對象,用于處理發送過來的各種消息:

private 
           

調用了 handleBindApplication 方法:

private 
           

4.1.5.2 ActivityStackSupervisor.attachApplicationLocked

4.1.4

小節中通過 Binder 向 ActivityThread 發起 bindApplication 請求後,會根據啟動元件的類型去做相應的處理,如果是 Acitivity,則會調用 ActivityStackSupervisor 的 attachApplicationLocked 方法:

boolean 
           

4.1.5.2.1 ActivityStackSupervisor.realStartActivityLocked

前面

2.1.8 ActivityStackSupervisor.startSpecificActivityLocked

小節中分析過,如果目前 Activity 依附的 Application 已經被啟動,則調用 realStartActivityLocked 方法,否則建立新的程序,再建立新的程序之後,兩個流程的在這裡合并起來了:

final 
           

這裡有一次使用 Binder 調用 ApplicationThread 的 scheduleLaunchActivity 方法。

4.1.5.2.2 ApplicationThread.scheduleLaunchActivity

public 
           

上面提到過,H 是 ActivityThread 中一個 Handler 類,它接收到 LAUNCH_ACTIVITY 消息後會調用 handleLaunchActivity 方法。

4.1.5.2.3 ActivityThread.handleLaunchActivity

private 
           

4.1.4.2.4 ApplicationThread.performLaunchActivity

private 
           

4.1.5.2.5 Instrumentation.callActivityOnCreate

public 
           

4.1.5.2.6 Activity.performCreate

final 
           

終于,onCreate 方法被調用了!!!

4.2 小結

從 ActivityThread 到最終 Activity 被建立及生命周期被調用,核心過程涉及到了三次 Binder IPC 過程,分别是:ActivityThread 調用 AMS 的 attachApplication 方法、AMS 調用 ApplicationThread 的 bindApplication 方法、ASS 調用 Application 的 attachApplicationLocked 方法,整個過程的時序圖如下:

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

5. 總結

縱觀整個過程,從 Launcher 到 AMS、從 AMS 再到 Zygote、再從 Zygote 到 ActivityThread,最後在 ActivitThread 中層層調用到 Activity 的生命周期方法,中間涉及到了無數的細節,但總體上脈絡還是非常清晰的,各個 Android 版本的 Framework 層代碼可以某些過程的實作不太一樣,但是整個調用流程大體上也是相同的,借用 Gityuan 大神的一張圖作為結尾:

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...
系列文章

AJie:按下電源鍵後竟然發生了這一幕 —— Android 系統啟動流程分析​zhuanlan.zhihu.com

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

AJie:App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析​zhuanlan.zhihu.com

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...

AJie:螢幕上内容究竟是怎樣畫出來的 —— Android View 工作原理詳解​zhuanlan.zhihu.com

android activity啟動流程_App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析...
參考文章

startActivity啟動過程分析 - Gityuan部落格 | 袁輝輝的技術部落格

Android深入四大元件(一)應用程式啟動過程(前篇)

如果你對文章内容有疑問或者有不同的意見,歡迎留言,我們一同探讨。