ActivityManagerService的啟動流程
- 介紹
- 總體流程
- 涉及的資料結構
- ProcessRecord(行程)
- ActivityRecord
- TaskRecord
- ActivityStack
- ActivityStackSupervisor
- 詳細的流程
介紹
這篇文章是講,從手機桌面(Launcher)點擊一個未啟動app的圖示到這個app啟動完成的流程(冷啟動),
總體流程

Launcher、AMS、Zygote、app都處于不同的行程,他們之間需要跨行程才能通信,
用戶點擊Launcher的app圖示后,Launcher通知AMS,如果目標app未啟動(冷啟動),AMS會通過Socket來通知Zygote去創建行程,Zygote就fork出我們要啟動的app行程,
緊接著app要打開HomeActivity,需要與AMS互動
- app -> AMS : 因為AMS啟動時,就注冊到ServiceManager了,所以app呼叫getService就能從ServiceManager獲取到AMS的代理類IActivityManager(客戶端),app從而通過IActivityManager呼叫AMS(服務端)的方法,
- AMS -> app : AMS準備一個IBinder,叫IApplicationThread(服務端),當app行程啟動完成后,會呼叫IApplicationThread的attachApplication方法,把app的代理類ApplicationThread(客戶端)作為引數傳給AMS,AMS可以呼叫ApplicationThread的方法從而控制app,
IApplicationThread的實作類是ActivityThread的內部類ApplicationThread
看完流程圖,我們再來看時序圖

圖中的4就是attachApplication的程序,把app的代理類ApplicationThread交給AMS,
圖中的5就是AMS做完一些處理后,通過app的代理類ApplicationThread來啟動app的HomeActivity,
涉及的資料結構
在看原始碼之前,需要先了解幾個重要的資料結構
ProcessRecord(行程)
第一類資料:描述身份的資料
- ApplicationInfo info:AndroidManifest.xml中定義的Application資訊
- boolean isolated:是不是isolated行程
- int uid:行程uid
- int userId:這個是android做的多用戶系統id,就像windows可以登錄很多用戶一樣,android也希望可以實作類似的多用戶
- String processName:行程名字,默認情況下是包名
- UidRecord uidRecord:記錄已經使用的uid
- IApplicationThread thread:這個很重要,它是ApplicationThread的客戶端,AMS就是通過這個物件給apk行程發送異步訊息的(管理四大組件的訊息),所以只有這個物件不為空的情況下,才代表apk行程可以使用了
- int pid:行程的pid
- String procStatFile:proc目錄下每一個行程都有一個以pid命名的目錄檔案,這個目錄下記載著行程的詳細資訊,這個目錄及目錄下的檔案是內核創建的, proc是內核檔案系統,proc就是process的縮寫,涉及的目的就是匯出行程內核資訊
- int[] gids:gid組
- CompatibilityInfo compat : 兼容性資訊
- String requiredAbi : abi資訊
- String instructionSet : 指令集資訊
第二類資料:描述行程中組件的資料
- pkgList:行程中運行的包
- ArraySet pkgDeps:行程運行依賴的包
- ArrayList activities:行程啟動的所有的activity組件記錄表
- ArraySet services:行程啟動的所有的service組件記錄表
- ArraySet executingServices:正在運行(executing)是怎么定義的?首先需要明確的是系統是怎么控制組件的?發送訊息給apk行程,apk行程處理訊息,上報訊息完成,這被定義為一個完整的執行程序,因此正在執行(executing)被定義為發送訊息到上報完成這段時間
- ArraySet connections:系結service的客戶端記錄表
- ArraySet receivers:廣播接收器的記錄表
- ContentProviderRecord pubProviders:pub是publish(發布)的意思,ContentProvider需要安裝然后把自己發布到系統(AMS)中后,才能使用,安裝指的是apk行程加載ContentProvider子類、初始化創建資料庫等程序,發布是將ContentProvider的binder客戶端注冊到AMS中
- ArrayList conProviders:使用ContentProvider的客戶端記錄表
- BroadcastRecord curReceiver:當前行程正在執行的廣播 在本節中以上組件資訊只是做一個簡單的描述,以后單獨分析組件管理的時候在詳細介紹
此外還有描述行程狀態的資料、和pss相關的資料、和時間相關的資料、crash和anr相關的資料、和instrumentation相關的資料、電源資訊和除錯資訊等,
ActivityRecord
Activity在AMS內部是以ActivityRecord的形式存在的,Activity和ActivityRecord是一一對應的,
- ProcessRecord app:跑在哪個行程
- TaskRecord task :跑在哪個task
- ActivityInfo info :Activity資訊
- int mActivityType:Activity型別
- ActivityState state:Activity狀態
- ApplicationInfo appInfo :跑在哪個app
- ComponentName realActivity :組件名
- String packageName :包名
- String processName :行程名
- int launchMode:啟動模式
- int userId :該Activity運行在哪個用戶id
mActivityType
- APPLICATION_ACTIVITY_TYPE:普通應用型別
- HOME_ACTIVITY_TYPE:桌面型別
- RECENTS_ACTIVITY_TYPE:最近任務型別
ActivityState
- INITIALIZING
- RESUMED:已恢復
- PAUSING
- PAUSED:已暫停
- STOPPING
- STOPPED:已停止
- FINISHING
- DESTROYING
- DESTROYED:已銷毀
ActivityRecord是在ActivityStarter的startActivity方法里創建的
TaskRecord
任務堆疊TaskRecord,內部維護一個 ArrayList 用來保存ActivityRecord,
- ActivityStack stack:當前所屬的stack
- ArrayList mActivities:當前task的所有Activity串列
- int taskId
- String affinity:是指root activity的affinity,即該Task中第一個Activity
- int mCallingUid
- String mCallingPackage:呼叫者的包名
TaskRecord是在ActivityStarter的setTaskFromReuseOrCreateNewTask里創建的,
ActivityStack
ActivityStack,內部維護了一個 ArrayList ,用來管理TaskRecord,
手機有三個虛擬按鍵,按最右邊的正方形按鍵,會顯示最近任務,這個最近任務就是一個ActivityStack,桌面應用也是一個ActivityStack,
ArrayList mTaskHistory //保存所有的Task串列
ArrayList mStacks; //所有stack串列
final int mStackId;
int mDisplayId;
ActivityRecord mPausingActivity //正在pause
ActivityRecord mLastPausedActivity
ActivityRecord mResumedActivity //已經resumed
ActivityRecord mLastStartedActivity
所有前臺stack的mResumedActivity的state == RESUMED, 則表示allResumedActivitiesComplete, 此時mLastFocusedStack = mFocusedStack;
ActivityStackSupervisor
ActivityStackSupervisor,顧名思義,就是用來管理ActivityStack的
- ActivityStack mHomeStack:桌面的stack
- ActivityStack mFocusedStack:當前聚焦stack
- ActivityStack mLastFocusedStack:正在切換
- SparseArray mActivityDisplays:displayId為key
- SparseArray mActivityContainers: mStackId為key
- home的堆疊ID等于0,即HOME_STACK_ID = 0;
ActivityStackSupervisor內部有兩個不同的ActivityStack物件:mHomeStack、mFocusedStack,用來管理不同的任務,
ActivityStackSupervisor內部包含了創建ActivityStack物件的方法,
AMS初始化時會創建一個ActivityStackSupervisor物件

詳細的流程

- Instrumentation:管理Activity的生命周期以及啟動
- ActivityManagerProxy:AMS的代理物件
- ApplicationThreadProxy:啟動APP的代理物件
- ApplicationThread是一個Binder服務,不是主執行緒
第9步是通過Handler來跨執行緒通信,從子執行緒ApplicationThread走到主執行緒ActivityThread,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/224301.html
標籤:其他
