天天看點

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程序

目錄

1、介紹

2、Launcher 請求 AMS 過程

3、 AMS 到 ApplicationThread的調用過程

4、ActivityThread 啟動 Activity 的過程

5、根 Activity 啟動過程中涉及的程序

1、介紹

Activity的啟動過程分為兩種,一種是根Activity的啟動過程,另一種是普通Activity的啟動過程。根Activity指的是應用程式啟動的第一個Activity,是以根Activity的啟動過程一般情況下也可以了解為應用程式的啟動過程。普通Activity指的是除應用程式啟動的第一個Activity之外的其他Activity。

根Activity的啟動過程比較複雜,是以這裡分為 3 個部分來講,分别是 :

1、Launcher 請求 AMS 過程;

2、AMS 到 ApplicationThread 的調用過程

3、ActivityThread 啟動 Activity。

2、Launcher 請求 AMS 過程

在Android系統中,Launcher的重要作用有兩點:

(1)作為Android系統的啟動器,用來啟動應用程式。

(2)作為Android系統的桌面,用于顯示和管理應用程式的快捷圖示或者其他桌面元件。

當 Luancher 啟動後會将已安裝應用程式的快捷圖示顯示到桌面上,這些應用程式的快捷圖示就是啟動根Activity的入口,當我們點選某個應用程式的快捷圖示時,就會通過 Launcher 請求 AMS 來啟動該應用程式。Launcher 請求 AMS 的時序圖如圖所示:

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

1、當我們點選應用程式的快捷圖示時,就會調用 Launcher 的 startActivitySafely 方法,如下所示:

該類在該包内:packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

2、在紅色框内處将 Flag 設定為 Intent.FLAG_ACTIVITY_NEW_TASK ,這樣根 Activity 會在新的任務棧中啟動;

在藍色框處會調用 startActivity() 方法,這個 startActivity() 方法在 Activity 中實作,如下所示:

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

3、在 startActivity 方法中調用 startActivityForResult 方法,它的第二個參數為 -1,表示 Launcher 不需要知道 Activity 啟動的結果,startActivityForResult 方法的代碼如下所示:

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

4、上面的 mParent 是 Activity 類型的,表示目前 Activity 的父類。因為目前根 Activity 還沒有建立出來,是以,mParent == null 成立。

接着調用 Instrumentation 的 execStartActivity() 方法,Instrumentation 主要用來監控應用程式和系統的互動,execStartActivity() 方法的代碼如下所示:

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

5、首先調用 ActivityManager 的 getService() 方法來擷取 AMS 的代理對象,按着調用它的 startActivity 方法。

這裡與 Android 8.0 之前代碼的邏輯有些不同,Android 8.0 之前是通過 ActivityManagerNative 的 getDefault 來擷取 AMS 的代理對象的,現在這個邏輯封裝到了 ActivityManager 中而不是 ActivityManagerNative 中。

首先我們來檢視 ActivityManager 的 getService 方法做了什麼:

frameworks/base/core/java/android/app/ActivityManager.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

6、getService() 方法調用了 IActivityManagerSingleton 的 get() 方法,我們接着往下看,IActivityManagerSingleton 是一個 Singleton 類。

在紅框中第一行處得到名為 "activity" 的 Service 引用,也就是 IBinder 類型的 AMS 的引用。

接着在紅框中第二行處将它轉換成 IActivityManager 類型的對象,這段代碼采用的是 AIDL,IActivityManager.java 類是由 AIDL 工具在編譯時自動生成的,IActivityManager.aidl 的檔案路徑為 frameworks/base/core/java/android/app/IActivityManager.aidl。

要實作程序間通信,伺服器端也就是 AMS 隻需要繼承 IActivityManager.Stub 類并實作相應的方法就可以了。

注意 Android 8.0 之前并沒有采用 AIDL,而是采用了類似 AIDL 的形式,用 AMS 的代理對象 ActivityManagerProxy 來與 AMS 進行程序間通信,Android 8.0 去除了 ActivityManagerNative 的内部類 ActivityManagerProxy,代替它的是 IActivityManager,它是 AMS 在本地的代理。

回到 Instrumentation 類的 execStartActivity 方法中,從上面得知 execStartActivity 方法最終調用的是 AMS 的 startActivity 方法。

3、 AMS 到 ApplicationThread的調用過程

Luancher 請求 AMS 後,代碼邏輯已進入 AMS 中,接着是 AMS 到 ApplicationThread 的調用流程,時序圖如果所示:
Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

7、AMS中的startActivity()方法如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

8、在 AMS 的 startActivity() 方法中傳回了 startActivityAsUser() 方法,可以發現 startActivityAsUser() 方法比 startActivity() 方法多了一個參數 UserHandle.getCallingUserId(),這個方法會獲得調用者的 UserId,AMS 根據這個 UserId 來确定調用者的權限。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

9、在黃色框處判斷調用者程序是否被隔離,如果被隔離則抛出 SecurityException 異常,

在綠色框 處檢查調用者是否有權限,如果沒有權限也會抛出 SecurityException 異常。

最後通過 mActivityStartController.obtainStarter()擷取到了ActivityStarter對象,并執行了它的execute()方法。

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式
10、在上面execute()方法中會通過mRequest.mayWait字段來判斷最後執行startActivityMayWait()或者startActivity().(這一步是在Android9.0添加的)
Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

mRequest.mayWait字段的值,在ActivityManagerService中調用execute()的前,就調用了setMayWait()方法指派為了true。

最後調用了 startActivityMayWait() 方法,startActivityMayWait ()方法的參數要比 startActivityAsUser() 多幾個,需要注意的是倒數第三個參數類型為 TaskRecord,代表啟動的 Activity 所在的棧。

startActivityMayWait() 方法的代碼如下所示:

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

11、ActivityStarter 是 Android 7.0 中新加入的類,它是加載 Activity 的控制類,會收集所有的邏輯來決定如何将 Intent 和 Flags 轉換為 Activity,并将 Activity 和 Task 以及 Stack 相關聯。

ActivityStarter 的 startActivityMayWait() 方法調用了 startActivity()方法,如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

12、在上面代碼中我們看到會對啟動原因 reason進行判斷,判斷啟動的理由不為空,如果為空則抛出 IllegalArgumentException 異常。緊接着又調用了 startActivity 方法,如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

13、ActivityStarter 的 startActivity 方法邏輯比較多,這裡列出部分我們需要關心的代碼。

在藍色框 處判斷 IApplicationThread 類型的 caller 是否為 null,這個 caller 是方法調用一路傳過來的,指向的是 Launcher 所在的應用程式的 ApplicationThread 對象;

在綠色框 處調用 AMS 的 getRecordForAppLocked 方法得到的是代表 Launcher 程序的 callerApp 對象,它是 ProcessRecord 類型的,ProcessRecord 用于描述一個應用程式程序。

同樣地,ActivityRecord 用于描述一個 Activity,用來記錄一個 Activity 的所有資訊。接下來建立 ActivityRecord,用于描述将要啟動的 Activity,并在紅色框處将建立的 ActivityRecord 指派給 ActivityRecord [] 類型的 outActivity,

這個 outActivity 會作為最底部 的 startActivity 方法的參數傳遞下去。

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

14、startActivity 方法緊接着調用了 startActivityUnchecked() 方法:

frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

15、startActivityUnchecked 方法主要處理與棧管理相關的邏輯。

根據上文中 startActivitySafely 方法我們得知,啟動根 Activity 時會将 Intent 的 Flag 設定為 FLAG_ACTIVITY_NEW_TASK,這樣藍色框 處的條件判斷就會滿足;

接着執行綠色框處的 setTaskFromReuseOrCreateNewTask 方法,其内部會建立一個新的 TaskRecord,用來描述一個 Activity 任務棧,也就是說 setTaskFromReuseOrCreateNewTask 方法内部會建立一個新的 Activity 任務棧。

在黃色框處會調用 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法,如下所示:

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

16、在紅色框第一行 處調用 ActivityStack 的 topRunningActivityLocked 方法擷取要啟動的 Activity 所在棧的棧頂的不是處于停止狀态的 ActivityRecord。

在紅色框第二行處,如果 ActivityRecord 不為 null,或者要啟動的 Activity 的狀态不是 RESUMED 狀态,就會調用紅色框第三行  處的 ActivityStack 的 resumeTopActivityUncheckedLocked 方法。

對于即将啟動的 Activity,紅色框第二行 處的條件判斷是肯定滿足的,我們來檢視 ActivityStack 的resumeTopActivityUncheckedLocked 方法,如下所示:

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

17、緊接着檢視紅色框處 ActivityStack 的 resumeTopActivityInnerLocked 方法:

frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

18、resumeTopActivityInnerLocked 方法代碼非常多,我們隻需要關注調用了 ActivityStackSupervisor 的 startSpecificActivityLocked 方法,代碼如下所示。

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

19、在黃色框處擷取即将啟動的 Activity 所在的應用程式程序;

在綠色框 處判斷要啟動的 Activity 所在的應用程式程序如果已經運作的話;

就會調用紅色框 處的 realStartActivityLocked 方法,這個方法的第二個參數是代表要啟動的 Activity 所在的應用程式程序 ProcessRecord。

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式
20、這裡的 app.thread 指的是 IApplicationThread,它的實作是 ActivityThread 的内部類 ApplicationThread,其中 ApplicationThread 繼承了 IApplicationThread.Stub。
Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式
app 指的是傳入的要啟動的 Activity 所在的應用程式程序,是以,這段代碼指的就是要在目标應用程式程序啟動 Activity。目前代碼邏輯運作在 AMS 所在的程序(SystemServer 程序)中,通過 ApplicationThread 來與應用程式程序進行 Binder 通信,換句話說,ApplicationThread 是 AMS 所在程序(SystemServer 程序)和應用程式程序的通信橋梁,如圖所示:
Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

4、ActivityThread 啟動 Activity 的過程

通過上面的講解,我們知道目前的代碼邏輯已經運作在應用程式程序中。先來檢視 ActivityThread 啟動 Activity 過程的時序圖,如圖所示:
Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

21、接着檢視 ApplicationThread 的 scheduleLaunchActivity 方法,其中 ApplicationThread 是 ActivityThread 的内部類,應用程式程序建立後會運作代表主線程的執行個體 ActivityThread,它管理着目前應用程式程序的主線程。

ApplicationThread 的 scheduleLaunchActivity 方法如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

22、scheduleLaunchActivity 方法将啟動 Activity 的參數封裝成 ActivityClientRecord,sendMessage 方法向 H 類發送類型為 LAUNCH_ACTIVITY 的消息,并将 ActivityClientRecord 傳遞過去,sendMessage 方法有多個重載方法,最終調用的 sendMessage 方法如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

23、這裡的 mH 指的是 H,它是 ActivityThread 的内部類并繼承自 Handler,是應用程式程序中主線程的消息管理類。

因為 ApplicationThread 是一個 Binder,它的調用邏輯運作在 Binder 線程池中,是以這裡需要用 H 将代碼的邏輯切換到主線程中。

H 的代碼如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

24、檢視 H 的 handleMessage 方法中對 LAUNCH_ACTIVITY 的處理;

在注釋 1 處将傳過來的 msg 的成員變量 obj 轉換為 ActivityClientRecord;

在 注釋 2 處通過 getPackageInfoNoCheck 方法獲得 LoadedApk 類型的對象并指派給 ActivityClientRecord 的成員變量 packageInfo。應用程式程序要啟動 Activity 時需要将該 Activity 所屬的 APK 加載進來,而 LoadApk 就是用來描述已加載的 APK 檔案的。

在注釋 3 處調用 handleLaunchActivity 方法,代碼如下所示:

frameworks/base/core/java/android/app/ActivityThread.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

25、注釋 1 處的 performLaunchActivity 方法用來啟動 Activity;

注釋 2 處的代碼用來将 Activity 的狀态設定為 Resume。

如果該 Activity 為 null 則會通知 AMS 停止啟動 Activity。

下面來檢視 performLaunchActivity 方法做了什麼:

frameworks/base/core/java/android/app/ActivityThread.java

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

26、注釋 1 處用來擷取 ActivityInfo,用于儲存代碼以及 AndroidManifes 設定的 Activity 和 Receiver 節點資訊,比如 Activity 的 theme 和 launchMode。

在注釋 2 處擷取 APK 檔案的描述類 LoadedApk。

在注釋 3 處擷取要啟動的 Activity 的 ComponentName 類,在 ComponentName 類中儲存了該 Activity 的包名和類名。

在注釋 4 處用來建立要啟動 Activity 的上下文環境。

在注釋 5 處根據 ComponentName 中儲存的 Activity 類名,用類加載器來建立該 Activity 的執行個體。

在注釋 6 處用來建立 Application,makeApplication 方法内部會調用 Application 的 onCreate 方法。

在注釋 7 處調用 Activity 的 attach 方法初始化 Activity,在 attach 方法中會建立 Window 對象(PhoneWindow)并與 Activity 自身進行關聯。

在注釋 8 處調用 Instrumentation 的 callActivityOnCreate 方法來啟動 Activity,如下所示:

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

27、注釋 1 處調用了 Activity 的 performCreate 方法,代碼如下所示:

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

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式
28、在 performCreate 方法中調用 Activity 的 onCreate 方法,講到這裡,根 Activity 就啟動了,即應用程式就啟動了。根 Activity 啟動過程就講到這裡,下面我們來學習根 Activity 啟動過程中涉及的程序。

5、根 Activity 啟動過程中涉及的程序

根 Activity 啟動過程中會涉及 4 個程序,分别是 Zygote 程序、Launcher 程序、AMS 所在的程序(SystemServer程序)、應用程式程序。它們之間的關系如圖所示:
Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

首先 Launcher 程序向 AMS 請求建立根程序 Activity,AMS 會判斷根 Activity 所需的應用程式程序是否存在并啟動,如果不存在就會請求 Zygote 程序建立應用程式程序。

應用程式程序啟動後,AMS 會請求建立應用程式程序并啟動根 Activity。

其中步驟 2 采用的是 Socket 通信,步驟 1 和步驟 4 采用的是 Binder 通信。

為了更好了解,下面給出這個 4 個程序調用的時序圖,如圖所示:

Kotlin進階-10-Activity的啟動流程1、介紹2、Launcher 請求 AMS 過程3、 AMS 到 ApplicationThread的調用過程4、ActivityThread 啟動 Activity 的過程5、根 Activity 啟動過程中涉及的程式

                                                                                 學習資料主要來源于《Android進階解密》 

繼續閱讀