天天看點

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

ActivityManagerService(AMS)是Android中核心的服務之一,主要負責系統中四大元件的啟動、切換、排程及應用程式的管理和排程等工作。

AMS啟動整體流程圖

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

從上圖可以看出,經過的類不是很多,但是每個方法中的細分支很多,這我就不貼代碼了,詳細的邏輯請見源碼,這個隻是做個大概的總結,流程中的部分分支和作用請見圖中的文字說明

下面再說說兩個關于記憶體管理的方法:

ActivityManagerService.updateLruProcessLocked

排程優先級:就是作業系統配置設定CPU資源給程序時,需要參考的一個重要名額。

排程政策:用于描述作業系統的排程子產品,配置設定CPU資源給應用程序時,所遵循的規則。

oom_adj:當系統出現記憶體不足的情況時,核心可以根據程序的oom_adj值,來選擇殺死一些程序,以回收記憶體。

Low Memory Killer(LMK)機制:LMK的配置檔案中,預先定義了不同的記憶體門檻值及對應的oom_adj。當LMK監控到系統記憶體下降到某個門檻值時,就會kill掉目前系統内,oom_adj超過該門檻值預定義oom_adj的所有程序。

重點内容

1. 是否需要調整程序在LRU表中的位置,LRU特意定義了兩個索引mLruProcessServiceStart和mLruProcessActivityStart。包含Activity的程序,将插入到mLruProcessActivityStart之後的位置; 不包含Activity,但包含Service的程序,将插入到mLruProcessServiceStart之後,目前的流程并沒有判斷程序中是否含有Service,整體來講,後運作的程序,将插入到先運作的程序的後面,即LRU表的前面儲存的是老舊的程序,後面儲存的是使用者使用的較新的程序

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

2. 在更新位置之前,先移除LRU中舊有的資訊,并更新兩個索引mLruProcessServiceStart或mLruProcessActivityStart 的值

3. 更新含有activity的程序,将運作在activity的程序直接插到最後,将本程序沒有但用戶端含有activity的程序插入到導數第二個,為了公平不同使用者的程序位置會交換一下。(相同使用者的多個程序連續排列的話)

4. 更新service程序,理論上是直接插入到mLruProcessActivityStart 即可,但是目前代碼中hasService一直為false,是以并沒有使用

5. 更新其它程序,一般都放在mLruProcessServiceStart,但是如果該程序含有用戶端,那麼目前程序就需要放在用戶端之前,此時,若該程序綁定了僅含有Service或Provider的程序,這些程序将被插入到該程序的前面

6. 更新僅含有背景Service或ContentProvider的程序,通過updateLruProcessInternalLocked 更新,一般不會降低他們的重要性

ActivityManagerService.updateOomAdjLocked

  1. 在ProcessList.java中定義了很多程序在不同場景下oom_adj的值
  2. 通過逆序處理LRU中的程序,通過computeOomAdjLocked方法計算出每個程序oom_adj值,通過值的判斷通過LMK來kill掉相關程序
  3. 通過程序優先級回收程序記憶體,不kill記憶體,對于重要性大于home的程序而言,重要性越大,記憶體的回收等級越低,對于重要性小于home的程序而言,重要性越大,記憶體的回收等級越高(需要元件自己實作onTrimMemory方法,大部分都沒有實作,是以點幾乎沒作用)

computeOomAdjLocked的oom_adjzhi值的計算過程:

其實該函數的原理還是依據程序中運作的元件以及程序的種類,來計算相應的oom_adj。

  1. 包含前台Activity的程序、運作測試類的程序、處理廣播的程序及包含正在運作服務的程序,其oom_adj均被指派為FOREGROUND_APP_ADJ,即從LMK的角度來看,它們的重要性是一緻的。 但這些程序的procState不同,于是從AMS主動回收記憶體的角度來看,它們的重要性不同。
  2. 處理包含Activity的程序時,程序最終的oom_adj将由其中最要的Activity決定。 即程序中存在可見Activity時,程序的oom_adj就為VISIBLE_APP_ADJ; 否則,若程序中存在處于PAUSING、PAUSED或STOPPING狀态的Activity時,程序的oom_adj就為PERCEPTIBLE_APP_ADJ
  3. 當程序中含有Unbounded Service時,如果程序之前沒有啟動過UI,且Unbounded Service存活的時間沒有逾時, 程序的oom_ad才能被調整為SERVICE_ADJ;否則程序的oom_adj仍然是UNKNOW_ADJ或其它大于500的值。
  4. 處理Bounded Service時,整個計算的複雜度就飙升了,它将考慮到Bound時使用的flag及用戶端的情況,綜合調整程序的oom_adj。
  5. 處理含有ContentProvider的程序時,相對比較簡單。基本上與處理含有Unbounded Service的程序一緻,隻是最後增加了一些特殊情況的處理

AMS相關類圖關系

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

原圖來自這裡

從圖中可以看出:

1. AMS繼承自ActivityManagerNative(AMN),并實作了Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口

2. AMN繼承Java的Binder類,同時實作了IActivityManager接口,即AMN将作為Binder通信的服務端為使用者提供支援

3. 在ActivityManagerNative類中定義了内部類ActivityManagerProxy,該類同樣實作了IActivityManager接口,将作為用戶端使用的服務端代理

4. 其它程序将使用ActivityManager來使用AMS的服務。ActivityManager通過AMN提供的getDefault接口得到ActivityManagerProxy,然後再以Binder通信的方式調用AMS的接口

5. 從這裡我們可以看出應用程序通過binder的方式和systemserver程序進行通信

ApplicationThread相關類圖關系

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

原圖來自這裡

如上圖所示

  1. ActivityThread作為應用程序的主線程代表,在其中持有ApplicationThread
  2. ApplicationThread繼承ApplicationThreadNative(ATN),當AMS與應用程序通信時,ApplicationThread将作為Binder通信的服務端。
  3. ATN繼承自Binder并實作了IApplicationThread接口,即ATN将作為Binder通信的服務端為使用者提供支援
  4. ApplicationThreadProxy實作了IApplicationThread接口,是以它将作為用戶端使用的服務端代理
  5. AMS與應用程序通信時,通過ApplicationThreadNative擷取應用程序對應的ApplicationThreadProxy對象,通過ApplicationThreadProxy對象,将調用資訊通過Binder傳遞到ActivityThread中的ApplicationThread
  6. 從這裡我們可以出systemserver通過binder的方式和應用程式進行通信

Binder使用

Native層Binder使用

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

原圖來自這裡

Framework層Binder使用

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

原圖來自這裡

Native層和Framework的差別就是,native是直接使用binder去跨程序通信,Framework層則在java層封裝了一個service和一個service的代理類

AIDL的使用

Android ActivityManagerService 啟動流程總結AMS啟動整體流程圖AMS相關類圖關系ApplicationThread相關類圖關系Binder使用

原圖來自這裡

AIDL其實也是通過Framework層的binder架構實作的,隻不過我們隻需要定義好IRemoteService.aidl這個檔案就好了,編譯工具會自動幫我們生成java端可以調用的service和service的代理類,然後寫個service使用這些對象就可以了

參考連結:

http://gityuan.com/2015/11/22/binder-use/

http://blog.csdn.net/gaugamela/article/details/53067769