ActivityManagerService(AMS)是Android中核心的服務之一,主要負責系統中四大元件的啟動、切換、排程及應用程式的管理和排程等工作。
AMS啟動整體流程圖
從上圖可以看出,經過的類不是很多,但是每個方法中的細分支很多,這我就不貼代碼了,詳細的邏輯請見源碼,這個隻是做個大概的總結,流程中的部分分支和作用請見圖中的文字說明
下面再說說兩個關于記憶體管理的方法:
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表的前面儲存的是老舊的程序,後面儲存的是使用者使用的較新的程序
2. 在更新位置之前,先移除LRU中舊有的資訊,并更新兩個索引mLruProcessServiceStart或mLruProcessActivityStart 的值
3. 更新含有activity的程序,将運作在activity的程序直接插到最後,将本程序沒有但用戶端含有activity的程序插入到導數第二個,為了公平不同使用者的程序位置會交換一下。(相同使用者的多個程序連續排列的話)
4. 更新service程序,理論上是直接插入到mLruProcessActivityStart 即可,但是目前代碼中hasService一直為false,是以并沒有使用
5. 更新其它程序,一般都放在mLruProcessServiceStart,但是如果該程序含有用戶端,那麼目前程序就需要放在用戶端之前,此時,若該程序綁定了僅含有Service或Provider的程序,這些程序将被插入到該程序的前面
6. 更新僅含有背景Service或ContentProvider的程序,通過updateLruProcessInternalLocked 更新,一般不會降低他們的重要性
ActivityManagerService.updateOomAdjLocked
- 在ProcessList.java中定義了很多程序在不同場景下oom_adj的值
- 通過逆序處理LRU中的程序,通過computeOomAdjLocked方法計算出每個程序oom_adj值,通過值的判斷通過LMK來kill掉相關程序
- 通過程序優先級回收程序記憶體,不kill記憶體,對于重要性大于home的程序而言,重要性越大,記憶體的回收等級越低,對于重要性小于home的程序而言,重要性越大,記憶體的回收等級越高(需要元件自己實作onTrimMemory方法,大部分都沒有實作,是以點幾乎沒作用)
computeOomAdjLocked的oom_adjzhi值的計算過程:
其實該函數的原理還是依據程序中運作的元件以及程序的種類,來計算相應的oom_adj。
- 包含前台Activity的程序、運作測試類的程序、處理廣播的程序及包含正在運作服務的程序,其oom_adj均被指派為FOREGROUND_APP_ADJ,即從LMK的角度來看,它們的重要性是一緻的。 但這些程序的procState不同,于是從AMS主動回收記憶體的角度來看,它們的重要性不同。
- 處理包含Activity的程序時,程序最終的oom_adj将由其中最要的Activity決定。 即程序中存在可見Activity時,程序的oom_adj就為VISIBLE_APP_ADJ; 否則,若程序中存在處于PAUSING、PAUSED或STOPPING狀态的Activity時,程序的oom_adj就為PERCEPTIBLE_APP_ADJ
- 當程序中含有Unbounded Service時,如果程序之前沒有啟動過UI,且Unbounded Service存活的時間沒有逾時, 程序的oom_ad才能被調整為SERVICE_ADJ;否則程序的oom_adj仍然是UNKNOW_ADJ或其它大于500的值。
- 處理Bounded Service時,整個計算的複雜度就飙升了,它将考慮到Bound時使用的flag及用戶端的情況,綜合調整程序的oom_adj。
- 處理含有ContentProvider的程序時,相對比較簡單。基本上與處理含有Unbounded Service的程序一緻,隻是最後增加了一些特殊情況的處理
AMS相關類圖關系
原圖來自這裡
從圖中可以看出:
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相關類圖關系
原圖來自這裡
如上圖所示
- ActivityThread作為應用程序的主線程代表,在其中持有ApplicationThread
- ApplicationThread繼承ApplicationThreadNative(ATN),當AMS與應用程序通信時,ApplicationThread将作為Binder通信的服務端。
- ATN繼承自Binder并實作了IApplicationThread接口,即ATN将作為Binder通信的服務端為使用者提供支援
- ApplicationThreadProxy實作了IApplicationThread接口,是以它将作為用戶端使用的服務端代理
- AMS與應用程序通信時,通過ApplicationThreadNative擷取應用程序對應的ApplicationThreadProxy對象,通過ApplicationThreadProxy對象,将調用資訊通過Binder傳遞到ActivityThread中的ApplicationThread
- 從這裡我們可以出systemserver通過binder的方式和應用程式進行通信
Binder使用
Native層Binder使用
原圖來自這裡
Framework層Binder使用
原圖來自這裡
Native層和Framework的差別就是,native是直接使用binder去跨程序通信,Framework層則在java層封裝了一個service和一個service的代理類
AIDL的使用
原圖來自這裡
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