AMS的setSystemProcess的代碼如下:
**ActivityManagerService.java::setSystemProcess**
~~~
public static void setSystemProcess() {
try {
ActivityManagerService m = mSelf;
//向ServiceManager注冊幾個服務
ServiceManager.addService("activity",m);
//用于打印內存信息
ServiceManager.addService("meminfo", new MemBinder(m));
/*
Android4.0新增的,用于打印應用進程使用硬件顯示加速方面的信息(Applications
Graphics Acceleration Info)。讀者通過adb shell dumpsys gfxinfo看看具體的
輸出
*/
ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
if(MONITOR_CPU_USAGE)//該值默認為true,添加cpuinfo服務
ServiceManager.addService("cpuinfo", new CpuBinder(m));
//向SM注冊權限管理服務PermissionController
ServiceManager.addService("permission", newPermissionController(m));
/* 重要說明:
向PackageManagerService查詢package名為"android"的ApplicationInfo。
注意這句調用:雖然PKMS和AMS同屬一個進程,但是二者交互仍然借助Context。
其實,此處完全可以直接調用PKMS的函數。為什么要費如此周折呢
*/
ApplicationInfo info = //使用AMS的mContext對象
mSelf.mContext.getPackageManager().getApplicationInfo(
"android",STOCK_PM_FLAGS);
//①調用ActivityThread的installSystemApplicationInfo函數
mSystemThread.installSystemApplicationInfo(info);
synchronized (mSelf) {
//②此處涉及AMS對進程的管理,見下文分析
ProcessRecord app = mSelf.newProcessRecordLocked(
mSystemThread.getApplicationThread(), info,
info.processName);//注意,最后一個參數為字符串,值為“system”
app.persistent = true;
app.pid = MY_PID;
app.maxAdj = ProcessList.SYSTEM_ADJ;
//③保存該ProcessRecord對象
mSelf.mProcessNames.put(app.processName, app.info.uid, app);
synchronized (mSelf.mPidsSelfLocked) {
mSelf.mPidsSelfLocked.put(app.pid, app);
}
//根據系統當前狀態,調整進程的調度優先級和OOM_Adj,后續將詳細分析該函數
mSelf.updateLruProcessLocked(app, true,true);
}
} ......//拋異常
}
~~~
在以上代碼中列出了一個重要說明和兩個關鍵點。
- 重要說明:AMS向PKMS查詢名為“android”的ApplicationInfo。此處AMS和PKMS的交互是通過Context來完成的,查看這一系列函數調用的代碼,最終發現AMS將通過Binder發送請求給PKMS來完成查詢功能。AMS和PKMS同屬一個進程,它們完全可以不通過Context來交互。此處為何要如此大費周章呢?原因很簡單,Android希望SystemServer中的服務也通過Android運行環境來交互。這更多是從設計上來考慮的,比如組件之間交互接口的統一及未來系統的可擴展性。
- 關鍵點一:ActivityThread的installSystemApplicationInfo函數。
- 關鍵點二:ProcessRecord類,它和AMS對進程的管理有關。
通過重要說明,相信讀者能真正理解AMS的 main函數中第二個隱含目的的作用,故此處不再展開敘述。
現在來看第一個關鍵點,即ActivityThread的installSystemApplicationInfo函數。
1. ActivityThread的installSystemApplicationInfo函數分析
installSystemApplicationInfo函數的參數為一個ApplicationInfo對象,該對象由AMS通過Context查詢PKMS中一個名為“android”的package得來(根據前面介紹的知識,目前只有framework-res.apk聲明其package名為“android”)。
再來看installSystemApplicationInfo的代碼,如下所示:
**ActivityThread.java::installSystemApplicationInfo**
~~~
public voidinstallSystemApplicationInfo(ApplicationInfo info) {
synchronized (this) {
//返回的ContextImpl對象即之前在AMS的main函數一節中創建的那個對象
ContextImpl context = getSystemContext();
//又調用init初始化該Context,是不是重復調用init了?
context.init(new LoadedApk(this, "android", context, info,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this);
//創建一個Profiler對象,用于性能統計
mProfiler = new Profiler();
}
}
~~~
在以上代碼中看到調用context.init的地方,讀者可能會有疑惑,getSystemContext函數將返回mSystemContext,而此mSystemContext在AMS的main函數中已經初始化過了,此處為何再次初始化呢?
仔細查看看代碼便會發現:
- 第一次執行init時,在LoadedApk構造函數中第四個表示ApplicationInfo的參數為null。
- 第二次執行init時,LoadedApk構造函數的第四個參數不為空,即該參數將真正指向一個實際的ApplicationInfo,該ApplicationInfo來源于framework-res.apk。
基于上面的信息,某些讀者可能馬上能想到:Context第一次執行init的目的僅僅是為了創建一個Android運行環境,而該Context并沒有和實際的ApplicationInfo綁定。而第二次執行init前,先利用Context和PKMS交互得到一個實際的ApplicationInfo,然后再通過init將此Context和ApplicationInfo綁定。
是否覺得前面的疑惑已豁然而解?且慢,此處又拋出了一個更難的問題:
第一次執行init后得到的Context雖然沒有綁定ApplicationInfo,不是也能使用嗎?此處為何非要和一個ApplicationInfo綁定?
答案很簡單,因為framework-res.apk(包括后面將介紹的SettingsProvider.apk)運行在SystemServer中。和其他所有apk一樣,它的運行需要一個正確初始化的Android運行環境。
長噓一口氣,這個大難題終于弄明白了!在此即基礎上,AMS下一步的工作就就順理成章了。
由于framework-res.apk是一個APK文件,和其他APK文件一樣,它應該運行在一個進程中。而AMS是專門用于進程管理和調度的,所以運行APK的進程應該在AMS中有對應的管理結構。因此AMS下一步工作就是將這個運行環境和一個進程管理結構對應起來并交由AMS統一管理。
AMS中的進程管理結構是ProcessRecord。
2. 關于ProcessRecord和IApplicationThread的介紹
分析ProcessRecord之前,先來思考一個問題:
AMS如何與應用進程交互?例如AMS啟動一個位于其他進程的Activity,由于該Activity運行在另外一進程中,因此AMS勢必要和該進程進行跨進程通信。
答案自然是通過Binder進行通信。為此,Android提供了一個IApplicationThread接口,該接口定義了AMS和應用進程之間的交互函數,如圖6-5所示為該接口的家族圖譜。
:-: 
圖6-5 ApplicationThread類
由圖6-5可知:
- ApplicationThreadNative實現了IApplicationThread接口。從該接口定義的函數可知,AMS通過它可以和應用進程進行交互,例如,AMS啟動一個Activity的時候會調用該接口的scheduleLaunchActivity函數。
- ActivityThread通過成員變量mAppThread指向它的內部類ApplicationThread,而ApplicationThread從ApplicationThreadNative派生。
基于以上知識,讀者能快速得出下面問題的答案嗎?IApplicationThread的Binder服務端在應用進程中還是在AMS中?
* * * * *
**提示**:如果讀者知道Binder系統支持客戶端監聽服務端的死亡消息,那么這個問題的答案就簡單了:服務端自然在應用進程中,因為AMS需要監聽應用進程的死亡通知。
* * * * *
有了IApplicationThread接口,AMS就可以和應用進程交互了。例如,對于下面一個簡單的函數:
**ActivityThread.java::scheduleStopActivity**
~~~
public final void scheduleStopActivity(IBindertoken, boolean showWindow,
intconfigChanges) {
queueOrSendMessage(//該函數內部將給一個Handler發送對應的消息
showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,
token, 0, configChanges);
}
~~~
當AMS想要停止(stop)一個Activity時,會調用對應進程IApplicationThread Binder客戶端的scheduleStopActivity函數。該函數服務端實現的就是向ActivityThread所在線程發送一個消息。在應用進程中,ActivityThread運行在主線程中,所以這個消息最終在主線程被處理。
* * * * *
**提示**:Activity的onStop函數也將在主線程中被調用。
* * * * *
IApplicationThread僅僅是AMS和另外一個進程交互的接口,除此之外,AMS還需要更多的有關該進程的信息。在AMS中,進程的信息都保存在ProcessRecord數據結構中。那么,ProcessRecord是什么呢?先來看setSystemProcess的第二個關鍵點,即newProcessRecordLocked函數,其代碼如下:
**ActivityManagerService.java::newProcessRecordLocked**
~~~
final ProcessRecordnewProcessRecordLocked(IApplicationThread thread,
ApplicationInfo info, String customProcess) {
Stringproc = customProcess != null ? customProcess : info.processName;
BatteryStatsImpl.Uid.Proc ps = null;
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
//BSImpl將為該進程創建一個耗電量統計項
ps =stats.getProcessStatsLocked(info.uid, proc);
}
//創建一個ProcessRecord對象,用于和其他進程通信的thread作為第一個參數
returnnew ProcessRecord(ps, thread, info, proc);
}
~~~
ProcessRecord的成員變量較多,先來看看再其構造函數中都初始化了哪些成員變量。
**ProcessRecord.java::ProcessRecord**
~~~
ProcessRecord(BatteryStatsImpl.Uid.Proc_batteryStats,
IApplicationThread_thread,ApplicationInfo _info, String _processName) {
batteryStats = _batteryStats; //用于電量統計
info =_info; //保存ApplicationInfo
processName = _processName; //保存進程名
//一個進程能運行多個Package,pkgList用于保存package名
pkgList.add(_info.packageName);
thread= _thread;//保存IApplicationThread,通過它可以和應用進程交互
//下面這些xxxAdj成員變量和進程調度優先級及OOM_adj有關。以后再分析它的作用
maxAdj= ProcessList.EMPTY_APP_ADJ;
hiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
curRawAdj = setRawAdj = -100;
curAdj= setAdj = -100;
//用于控制該進程是否常駐內存(即使被殺掉,系統也會重啟它),只有重要的進程才會有此待遇
persistent = false;
removed= false;
}
~~~
ProcessRecord除保存和應用進程通信的IApplicationThread對象外,還保存了進程名、不同狀態對應的Oom_adj值及一個ApplicationInfo。一個進程雖然可運行多個Application,但是ProcessRecord一般保存該進程中先運行的那個Application的ApplicationInfo。
至此,已經創建了一個ProcessRecord對象,和其他應用進程不同的是,該對象對應的進程為SystemServer。為了彰顯其特殊性,AMS為其中的一些成員變量設置了特定的值:
~~~
app.persistent = true;//設置該值為true
app.pid =MY_PID;//設置pid為SystemServer的進程號
app.maxAdj= ProcessList.SYSTEM_ADJ;//設置最大OOM_Adj,系統進程默認值為-16
//另外,app的processName被設置成“system”
~~~
這時,一個針對SystemServer的ProcessRecord對象就創建完成了。此后AMS將把它并入自己的勢力范圍內。
AMS中有兩個成員變量用于保存ProcessRecord,一個是mProcessNames,另一個是mPidsSelfLocked,如圖6-6所示為這兩個成員變量的數據結構示意圖。
:-: 
圖6-6 mPidsSelfLocked和mProcessNames數據結構示意圖
3. AMS的setSystemProcess總結
現在來總結回顧setSystemProcess的工作:
- 注冊AMS、meminfo、gfxinfo等服務到ServiceManager中。
- 根據PKMS返回的ApplicationInfo初始化Android運行環境,并創建一個代表SystemServer進程的ProcessRecord,從此,SystemServer進程也并入AMS的管理范圍內。
- 前言
- 第1章 搭建Android源碼工作環境
- 1.1 Android系統架構
- 1.2 搭建開發環境
- 1.2.1 下載源碼
- 1.2.2 編譯源碼
- 1.2.3 利用Eclipse調試system_process
- 1.3 本章小結
- 第2章 深入理解Java Binder和MessageQueue
- 2.1 概述
- 2.2 Java層中的Binder架構分析
- 2.2.1 Binder架構總覽
- 2.2.2 初始化Java層Binder框架
- 2.2.3 addService實例分析
- 2.2.4 Java層Binder架構總結
- 2.3 心系兩界的MessageQueue
- 2.3.1 MessageQueue的創建
- 2.3.2 提取消息
- 2.3.3 nativePollOnce函數分析
- 2.3.4 MessageQueue總結
- 2.4 本章小結
- 第3章 深入理解SystemServer
- 3.1 概述
- 3.2 SystemServer分析
- 3.2.1 main函數分析
- 3.2.2 Service群英會
- 3.3 EntropyService分析
- 3.4 DropBoxManagerService分析
- 3.4.1 DBMS構造函數分析
- 3.4.2 dropbox日志文件的添加
- 3.4.3 DBMS和settings數據庫
- 3.5 DiskStatsService和DeviceStorageMonitorService分析
- 3.5.1 DiskStatsService分析
- 3.5.2 DeviceStorageManagerService分析
- 3.6 SamplingProfilerService分析
- 3.6.1 SamplingProfilerService構造函數分析
- 3.6.2 SamplingProfilerIntegration分析
- 3.7 ClipboardService分析
- 3.7.1 復制數據到剪貼板
- 3.7.2 從剪切板粘貼數據
- 3.7.3 CBS中的權限管理
- 3.8 本章小結
- 第4章 深入理解PackageManagerService
- 4.1 概述
- 4.2 初識PackageManagerService
- 4.3 PKMS的main函數分析
- 4.3.1 構造函數分析之前期準備工作
- 4.3.2 構造函數分析之掃描Package
- 4.3.3 構造函數分析之掃尾工作
- 4.3.4 PKMS構造函數總結
- 4.4 APK Installation分析
- 4.4.1 adb install分析
- 4.4.2 pm分析
- 4.4.3 installPackageWithVerification函數分析
- 4.4.4 APK 安裝流程總結
- 4.4.5 Verification介紹
- 4.5 queryIntentActivities分析
- 4.5.1 Intent及IntentFilter介紹
- 4.5.2 Activity信息的管理
- 4.5.3 Intent 匹配查詢分析
- 4.5.4 queryIntentActivities總結
- 4.6 installd及UserManager介紹
- 4.6.1 installd介紹
- 4.6.2 UserManager介紹
- 4.7 本章學習指導
- 4.8 本章小結
- 第5章 深入理解PowerManagerService
- 5.1 概述
- 5.2 初識PowerManagerService
- 5.2.1 PMS構造函數分析
- 5.2.2 init分析
- 5.2.3 systemReady分析
- 5.2.4 BootComplete處理
- 5.2.5 初識PowerManagerService總結
- 5.3 PMS WakeLock分析
- 5.3.1 WakeLock客戶端分析
- 5.3.2 PMS acquireWakeLock分析
- 5.3.3 Power類及LightService類介紹
- 5.3.4 WakeLock總結
- 5.4 userActivity及Power按鍵處理分析
- 5.4.1 userActivity分析
- 5.4.2 Power按鍵處理分析
- 5.5 BatteryService及BatteryStatsService分析
- 5.5.1 BatteryService分析
- 5.5.2 BatteryStatsService分析
- 5.5.3 BatteryService及BatteryStatsService總結
- 5.6 本章學習指導
- 5.7 本章小結
- 第6章 深入理解ActivityManagerService
- 6.1 概述
- 6.2 初識ActivityManagerService
- 6.2.1 ActivityManagerService的main函數分析
- 6.2.2 AMS的 setSystemProcess分析
- 6.2.3 AMS的 installSystemProviders函數分析
- 6.2.4 AMS的 systemReady分析
- 6.2.5 初識ActivityManagerService總結
- 6.3 startActivity分析
- 6.3.1 從am說起
- 6.3.2 AMS的startActivityAndWait函數分析
- 6.3.3 startActivityLocked分析
- 6.4 Broadcast和BroadcastReceiver分析
- 6.4.1 registerReceiver流程分析
- 6.4.2 sendBroadcast流程分析
- 6.4.3 BROADCAST_INTENT_MSG消息處理函數
- 6.4.4 應用進程處理廣播分析
- 6.4.5 廣播處理總結
- 6.5 startService之按圖索驥
- 6.5.1 Service知識介紹
- 6.5.2 startService流程圖
- 6.6 AMS中的進程管理
- 6.6.1 Linux進程管理介紹
- 6.6.2 關于Android中的進程管理的介紹
- 6.6.3 AMS進程管理函數分析
- 6.6.4 AMS進程管理總結
- 6.7 App的 Crash處理
- 6.7.1 應用進程的Crash處理
- 6.7.2 AMS的handleApplicationCrash分析
- 6.7.3 AppDeathRecipient binderDied分析
- 6.7.4 App的Crash處理總結
- 6.8 本章學習指導
- 6.9 本章小結
- 第7章 深入理解ContentProvider
- 7.1 概述
- 7.2 MediaProvider的啟動及創建
- 7.2.1 Context的getContentResolver函數分析
- 7.2.2 MediaStore.Image.Media的query函數分析
- 7.2.3 MediaProvider的啟動及創建總結
- 7.3 SQLite創建數據庫分析
- 7.3.1 SQLite及SQLiteDatabase家族
- 7.3.2 MediaProvider創建數據庫分析
- 7.3.3 SQLiteDatabase創建數據庫的分析總結
- 7.4 Cursor 的query函數的實現分析
- 7.4.1 提取query關鍵點
- 7.4.2 MediaProvider 的query分析
- 7.4.3 query關鍵點分析
- 7.4.4 Cursor query實現分析總結
- 7.5 Cursor close函數實現分析
- 7.5.1 客戶端close的分析
- 7.5.2 服務端close的分析
- 7.5.3 finalize函數分析
- 7.5.4 Cursor close函數總結
- 7.6 ContentResolver openAssetFileDescriptor函數分析
- 7.6.1 openAssetFileDescriptor之客戶端調用分析
- 7.6.2 ContentProvider的 openTypedAssetFile函數分析
- 7.6.3 跨進程傳遞文件描述符的探討
- 7.6.4 openAssetFileDescriptor函數分析總結
- 7.7 本章學習指導
- 7.8 本章小結
- 第8章 深入理解ContentService和AccountManagerService
- 8.1 概述
- 8.2 數據更新通知機制分析
- 8.2.1 初識ContentService
- 8.2.2 ContentResovler 的registerContentObserver分析
- 8.2.3 ContentResolver的 notifyChange分析
- 8.2.4 數據更新通知機制總結和深入探討
- 8.3 AccountManagerService分析
- 8.3.1 初識AccountManagerService
- 8.3.2 AccountManager addAccount分析
- 8.3.3 AccountManagerService的分析總結
- 8.4 數據同步管理SyncManager分析
- 8.4.1 初識SyncManager
- 8.4.2 ContentResolver 的requestSync分析
- 8.4.3 數據同步管理SyncManager分析總結
- 8.5 本章學習指導
- 8.6 本章小結