
在我的上一篇文章:
AJie:按下電源鍵後竟然發生了這一幕 —— Android 系統啟動流程分析zhuanlan.zhihu.com
我們分析了系統在開機以後的一系列行為,其中最後一階段 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
中我們分析了 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
中也講到過:
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 的時序圖如下:
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 開始的調用時序圖如下:
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 程序的過程如出一轍,時序圖如下所示:
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 方法,整個過程的時序圖如下:
5. 總結
縱觀整個過程,從 Launcher 到 AMS、從 AMS 再到 Zygote、再從 Zygote 到 ActivityThread,最後在 ActivitThread 中層層調用到 Activity 的生命周期方法,中間涉及到了無數的細節,但總體上脈絡還是非常清晰的,各個 Android 版本的 Framework 層代碼可以某些過程的實作不太一樣,但是整個調用流程大體上也是相同的,借用 Gityuan 大神的一張圖作為結尾:
AJie:按下電源鍵後竟然發生了這一幕 —— Android 系統啟動流程分析zhuanlan.zhihu.com
AJie:App 竟然是這樣跑起來的 —— Android App/Activity 啟動流程分析zhuanlan.zhihu.com
AJie:螢幕上内容究竟是怎樣畫出來的 —— Android View 工作原理詳解zhuanlan.zhihu.com
startActivity啟動過程分析 - Gityuan部落格 | 袁輝輝的技術部落格
Android深入四大元件(一)應用程式啟動過程(前篇)
如果你對文章内容有疑問或者有不同的意見,歡迎留言,我們一同探讨。