鍍金池/ 教程/ Android/ 第6章?深入理解ActivityManagerService
第2章? 深入理解 Java Binder 和 MessageQueue
第7章? 深入理解 ContentProvider
第5章? 深入理解 PowerManagerService
第3章? 深入理解 SystemServer
第8章? 深入理解ContentService 和 AccountManagerService
第1章?開(kāi)發(fā)環(huán)境部署
第4章? 深入理解 PackageManagerService
第6章?深入理解ActivityManagerService

第6章?深入理解ActivityManagerService

本章主要內(nèi)容:

·??詳細(xì)分析ActivityManagerService

本章所涉及的源代碼文件名及位置:

·??SystemServer.java

frameworks/base/services/java/com/android/server/SystemServer.java

·??ActivityManagerService.java

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

·??ContextImpl.java

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

·??ActivityThread.java

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

·??ActivityStack.java

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

·??Am.java

frameworks/base/cmds/am/src/com/android/commands/am/Am.java

·??ProcessRecord.java

frameworks/base/services/java/com/android/server/am/ProcessRecord.java

·??ProcessList.java

frameworks/base/services/java/com/android/server/am/ProcessList.java

·??RuntimeInit.java

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

6.1 ?概述

相信絕大部分讀者對(duì)本書(shū)提到的ActivityManagerService(以后簡(jiǎn)稱AMS)都有所耳聞。AMS是Android中最核心的服務(wù),主要負(fù)責(zé)系統(tǒng)中四大組件的啟動(dòng)、切換、調(diào)度及應(yīng)用進(jìn)程的管理和調(diào)度等工作,其職責(zé)與操作系統(tǒng)中的進(jìn)程管理和調(diào)度模塊相類似,因此它在Android中非常重要。

AMS是本書(shū)碰到的第一塊難啃的骨頭[①],涉及的知識(shí)點(diǎn)較多。為了幫助讀者更好地理解AMS,本章將帶領(lǐng)讀者按五條不同的線來(lái)分析它。

·??第一條線:同其他服務(wù)一樣,將分析SystemServer中AMS的調(diào)用軌跡。

·??第二條線:以am命令啟動(dòng)一個(gè)Activity為例,分析應(yīng)用進(jìn)程的創(chuàng)建、Activity的啟動(dòng),以及它們和AMS之間的交互等知識(shí)。

·??第三條線和第四條線:分別以Broadcast和Service為例,分析AMS中Broadcast和Service的相關(guān)處理流程。

·??第五條線:以一個(gè)Crash的應(yīng)用進(jìn)程為出發(fā)點(diǎn),分析AMS如何打理該應(yīng)用進(jìn)程的身后事。

除了這五條線外,還將統(tǒng)一分析在這五條線中頻繁出現(xiàn)的與AMS中應(yīng)用進(jìn)程的調(diào)度、內(nèi)存管理等相關(guān)的知識(shí)。

提示ContentProvider將放到下一章分析,不過(guò)本章將涉及和ContentProvider有關(guān)的知識(shí)點(diǎn)。

先來(lái)看AMS的家族圖譜,如圖6-1所示。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter6/image001.png" alt="image" />

圖6-1? AMS家族圖譜

由圖6-1可知:

·??AMS由ActivityManagerNative(以后簡(jiǎn)稱AMN)類派生,并實(shí)現(xiàn)Watchdog.Monitor和BatteryStatsImpl.BatteryCallback接口。而AMN由Binder派生,實(shí)現(xiàn)了IActivityManager接口。

·??客戶端使用ActivityManager類。由于AMS是系統(tǒng)核心服務(wù),很多API不能開(kāi)放供客戶端使用,所以設(shè)計(jì)者沒(méi)有讓ActivityManager直接加入AMS家族。在ActivityManager類內(nèi)部通過(guò)調(diào)用AMN的getDefault函數(shù)得到一個(gè)ActivityManagerProxy對(duì)象,通過(guò)它可與AMS通信。

AMS的簡(jiǎn)單介紹就到此為止,下面分析AMS。相信不少讀者已經(jīng)磨拳擦掌,躍躍欲試了。

提示讀者們最好在桌上放一杯清茶,以保持AMS分析旅途中頭腦清醒。

6.2? 初識(shí)ActivityManagerService

AMS由SystemServer的ServerThread線程創(chuàng)建,提取它的調(diào)用軌跡,代碼如下:

[-->SystemServer.java::ServerThread的run函數(shù)]

//①調(diào)用main函數(shù),得到一個(gè)Context對(duì)象

context =ActivityManagerService.main(factoryTest);

?

//②setSystemProcess:這樣SystemServer進(jìn)程可加到AMS中,并被它管理

ActivityManagerService.setSystemProcess();

?

//③installSystemProviders:將SettingsProvider放到SystemServer進(jìn)程中來(lái)運(yùn)行

ActivityManagerService.installSystemProviders();

?

//④在內(nèi)部保存WindowManagerService(以后簡(jiǎn)稱WMS)

ActivityManagerService.self().setWindowManager(wm);

?

//⑤和WMS交互,彈出“啟動(dòng)進(jìn)度“對(duì)話框

ActivityManagerNative.getDefault().showBootMessage(

?????????????context.getResources().getText(

????????? ?????//該字符串中文為:“正在啟動(dòng)應(yīng)用程序”

????????? ?????com.android.internal.R.string.android_upgrading_starting_apps),

??????????????false);

?

//⑥AMS是系統(tǒng)的核心,只有它準(zhǔn)備好后,才能調(diào)用其他服務(wù)的systemReady

//注意,有少量服務(wù)在AMS systemReady之前就緒,它們不影響此處的分析

ActivityManagerService.self().systemReady(newRunnable() {

??? publicvoid run() {

???startSystemUi(contextF);//啟動(dòng)systemUi。如此,狀態(tài)欄就準(zhǔn)備好了

??? if(batteryF != null) batteryF.systemReady();

??? if(networkManagementF != null) networkManagementF.systemReady();

??? ......

??? Watchdog.getInstance().start();//啟動(dòng)Watchdog

??? ......//調(diào)用其他服務(wù)的systemReady函數(shù)

}

在以上代碼中,一共列出了6個(gè)重要調(diào)用及這些調(diào)用的簡(jiǎn)單說(shuō)明,本節(jié)將分析除與WindowManagerService(以后簡(jiǎn)稱WMS)交互的4、5外的其余四項(xiàng)調(diào)用。

先來(lái)分析1處調(diào)用。

6.2.1? ActivityManagerService main分析

AMS的main函數(shù)將返回一個(gè)Context類型的對(duì)象,該對(duì)象在SystemServer中被其他服務(wù)大量使用。Context,顧名思義,代表了一種上下文環(huán)境(筆者覺(jué)得其意義和JNIEnv類似),有了這個(gè)環(huán)境,我們就可以做很多事情(例如獲取該環(huán)境中的資源、Java類信息等)。那么AMS的main將返回一個(gè)怎樣的上下文環(huán)境呢?來(lái)看以下代碼:

[-->ActivityManagerService.java::main]

?publicstatic final Context main(int factoryTest) {

??? AThreadthr = new AThread();//①創(chuàng)建一個(gè)AThread線程對(duì)象

??? thr.start();

?? ?......//等待thr創(chuàng)建成功

??? ActivityManagerServicem = thr.mService;

??? mSelf =m;

??? //②調(diào)用ActivityThread的systemMain函數(shù)

??? ActivityThreadat = ActivityThread.systemMain();

??? mSystemThread= at;

?

??? //③得到一個(gè)Context對(duì)象,注意調(diào)用的函數(shù)名為getSystemContext,何為System Context

??? Contextcontext = at.getSystemContext();

??? context.setTheme(android.R.style.Theme_Holo);

??? m.mContext= context;

??? m.mFactoryTest= factoryTest;

?

??? //ActivtyStack是AMS中用來(lái)管理Activity的啟動(dòng)和調(diào)度的核心類,以后再分析它

?? ?m.mMainStack = new ActivityStack(m, context,true);

??? //調(diào)用BSS的publish函數(shù),我們?cè)诘?章的BSS知識(shí)中介紹過(guò)了

??? m.mBatteryStatsService.publish(context);

??? //另外一個(gè)service:UsageStatsService。后續(xù)再分析該服務(wù)

??? m.mUsageStatsService.publish(context);

??? synchronized (thr) {

???????????thr.mReady = true;

???????????thr.notifyAll();//通知thr線程,本線程工作完成

???? }

?

??? //④調(diào)用AMS的startRunning函數(shù)

?? ?m.startRunning(null, null, null, null);

???????

?? returncontext;

}

在main函數(shù)中,我們又列出了4個(gè)關(guān)鍵函數(shù),分別是:

·??創(chuàng)建AThread線程。雖然AMS的main函數(shù)由ServerThread線程調(diào)用,但是AMS自己的工作并沒(méi)有放在ServerThread中去做,而是新創(chuàng)建了一個(gè)線程,即AThread線程。

·??ActivityThread.systemMain函數(shù)。初始化ActivityThread對(duì)象。

·??ActivityThread.getSystemContext函數(shù)。用于獲取一個(gè)Context對(duì)象,從函數(shù)名上看,該Context代表了System的上下文環(huán)境。

·??AMS的startRunning函數(shù)。

注意,main函數(shù)中有一處等待(wait)及一處通知(notifyAll),原因是:

·??main函數(shù)首先需要等待AThread所在線程啟動(dòng)并完成一部分工作。

·??AThread完成那一部分工作后,將等待main函數(shù)完成后續(xù)的工作。

這種雙線程互相等待的情況,在Android代碼中比較少見(jiàn),讀者只需了解它們的目的即可。下邊來(lái)分析以上代碼中的第一個(gè)關(guān)鍵點(diǎn)。

1.? AThread分析

(1)?AThread分析

AThread的代碼如下:

[-->ActivityManagerService.java::AThread]

static class AThread extends Thread {//AThread從Thread類派生

?? ActivityManagerServicemService;

?? booleanmReady = false;

?? publicAThread() {

???? super("ActivityManager");//線程名就叫“ActivityManager”

?? }

?? publicvoid run() {

???? Looper.prepare();//看來(lái),AThread線程將支持消息循環(huán)及處理功能

???? android.os.Process.setThreadPriority(//設(shè)置線程優(yōu)先級(jí)

???????????????????android.os.Process.THREAD_PRIORITY_FOREGROUND);

???? android.os.Process.setCanSelfBackground(false);

????? //創(chuàng)建AMS對(duì)象

?????ActivityManagerService m = new ActivityManagerService();

?????synchronized (this) {

?????????? mService= m;//賦值A(chǔ)Thread內(nèi)部成員變量mService,指向AMS

??????????notifyAll();? //通知main函數(shù)所在線程

????? }

?????synchronized (this) {

????????while (!mReady) {

?????????? try{

?????????????????wait();//等待main函數(shù)所在線程的notifyAll

???????????????}......

?????????? }

?????? }......

??? Looper.loop();//進(jìn)入消息循環(huán)

?}

?}

從本質(zhì)上說(shuō),AThread是一個(gè)支持消息循環(huán)及處理的線程,其主要工作就是創(chuàng)建AMS對(duì)象,然后通知AMS的main函數(shù)。這樣看來(lái),main函數(shù)等待的就是這個(gè)AMS對(duì)象。

(2)?AMS的構(gòu)造函數(shù)分析

AMS的構(gòu)造函數(shù)的代碼如下:

[-->ActivityManagerService.java::ActivityManagerService構(gòu)造]

private ActivityManagerService() {

??? FiledataDir = Environment.getDataDirectory();//指向/data/目錄

??? FilesystemDir = new File(dataDir, "system");//指向/data/system/目錄

???systemDir.mkdirs();//創(chuàng)建/data/system/目錄

?

??? //創(chuàng)建BatteryStatsService(以后簡(jiǎn)稱BSS)和UsageStatsService(以后簡(jiǎn)稱USS)

?? //我們?cè)诜治鯬owerManageService時(shí)已經(jīng)見(jiàn)過(guò)BSS了

???mBatteryStatsService = new BatteryStatsService(new File(

???????????????systemDir, "batterystats.bin").toString());

???mBatteryStatsService.getActiveStatistics().readLocked();

??? mBatteryStatsService.getActiveStatistics().writeAsyncLocked();

???mOnBattery = DEBUG_POWER ? true

???????????????: mBatteryStatsService.getActiveStatistics().getIsOnBattery();

???mBatteryStatsService.getActiveStatistics().setCallback(this);

?

??? //創(chuàng)建USS

??? mUsageStatsService= new UsageStatsService(new File(

???????????????systemDir, "usagestats").toString());

??? //獲取OpenGl版本

???GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",

???????????ConfigurationInfo.GL_ES_VERSION_UNDEFINED);

???? //mConfiguration類型為Configuration,用于描述資源文件的配置屬性,例如

??? ?//字體、語(yǔ)言等。后文再討論這方面的內(nèi)容

????mConfiguration.setToDefaults();

????mConfiguration.locale = Locale.getDefault();

???? //mProcessStats為ProcessStats類型,用于統(tǒng)計(jì)CPU、內(nèi)存等信息。其內(nèi)部工作原理就是

??? //讀取并解析/proc/stat文件的內(nèi)容。該文件由內(nèi)核生成,用于記錄kernel及system

??? //一些運(yùn)行時(shí)的統(tǒng)計(jì)信息。讀者可在Linux系統(tǒng)上通過(guò)man proc命令查詢?cè)敿?xì)信息

????mProcessStats.init();

?

???? //解析/data/system/packages-compat.xml文件,該文件用于存儲(chǔ)那些需要考慮屏幕尺寸

??? //的APK的一些信息。讀者可參考AndroidManifest.xml中compatible-screens相關(guān)說(shuō)明。

?? ?//當(dāng)APK所運(yùn)行的設(shè)備不滿足要求時(shí),AMS會(huì)根據(jù)設(shè)置的參數(shù)以采用屏幕兼容的方式去運(yùn)行它

????mCompatModePackages = new CompatModePackages(this, systemDir);

?

???? Watchdog.getInstance().addMonitor(this);

???? //創(chuàng)建一個(gè)新線程,用于定時(shí)更新系統(tǒng)信息(和mProcessStats交互)

????mProcessStatsThread = new Thread("ProcessStats") {...//先略去該段代碼}

????mProcessStatsThread.start();

?}

AMS的構(gòu)造函數(shù)比想象得要簡(jiǎn)單些,下面回顧一下它的工作:

·??創(chuàng)建BSS、USS、mProcessStats (ProcessStats類型)、mProcessStatsThread線程,這些都與系統(tǒng)運(yùn)行狀況統(tǒng)計(jì)相關(guān)。

·??創(chuàng)建/data/system目錄,為mCompatModePackages(CompatModePackages類型)和mConfiguration(Configuration類型)等成員變量賦值。

AMS main函數(shù)的第一個(gè)關(guān)鍵點(diǎn)就分析到此,再來(lái)分析它的第二個(gè)關(guān)鍵點(diǎn)。

2.? ActivityThread.systemMain函數(shù)分析

ActivityThread是Android Framework中一個(gè)非常重要的類,它代表一個(gè)應(yīng)用進(jìn)程的主線程(對(duì)于應(yīng)用進(jìn)程來(lái)說(shuō),ActivityThread的main函數(shù)確實(shí)是由該進(jìn)程的主線程執(zhí)行),其職責(zé)就是調(diào)度及執(zhí)行在該線程中運(yùn)行的四大組件。

注意應(yīng)用進(jìn)程指那些運(yùn)行APK的進(jìn)程,它們由Zyote 派生(fork)而來(lái),上面運(yùn)行了dalvik虛擬機(jī)。與應(yīng)用進(jìn)程相對(duì)的就是系統(tǒng)進(jìn)程(包括Zygote和SystemServer)。

另外,讀者須將“應(yīng)用進(jìn)程和系統(tǒng)進(jìn)程”與“應(yīng)用APK和系統(tǒng)APK”的概念區(qū)分開(kāi)來(lái)。APK的判別依賴其文件所在位置(如果apk文件在/data/app目錄下,則為應(yīng)用APK)。

該函數(shù)代碼如下:

[-->ActivityThread.java::systemMain]

public static final ActivityThread systemMain() {

?? HardwareRenderer.disable(true);//禁止硬件渲染加速

?? //創(chuàng)建一個(gè)ActivityThread對(duì)象,其構(gòu)造函數(shù)非常簡(jiǎn)單

??ActivityThread thread = new ActivityThread();

??thread.attach(true);//調(diào)用它的attach函數(shù),注意傳遞的參數(shù)為true

?? returnthread;

?}

在分析ActivityThread的attach函數(shù)之前,先提一個(gè)問(wèn)題供讀者思考:前面所說(shuō)的ActivityThread代表應(yīng)用進(jìn)程(其上運(yùn)行了APK)的主線程,而SystemServer并非一個(gè)應(yīng)用進(jìn)程,那么為什么此處也需要ActivityThread呢?

·??還記得在PackageManagerService分析中提到的framework-res.apk嗎?這個(gè)APK除了包含資源文件外,還包含一些Activity(如關(guān)機(jī)對(duì)話框),這些Activity實(shí)際上運(yùn)行在SystemServer進(jìn)程中[②]。從這個(gè)角度看,SystemServer是一個(gè)特殊的應(yīng)用進(jìn)程。

·??另外,通過(guò)ActivityThread可以把Android系統(tǒng)提供的組件之間的交互機(jī)制和交互接口(如利用Context提供的API)也拓展到SystemServer中使用。

提示解答這個(gè)問(wèn)題,對(duì)于理解SystemServer中各服務(wù)的交互方式是尤其重要的。

下面來(lái)看ActivityThread的attach函數(shù)。

(1)?attach函數(shù)分析

[-->ActivityThread.java::attach]

private void attach(boolean system) {

??? sThreadLocal.set(this);

??? mSystemThread= system;//判斷是否為系統(tǒng)進(jìn)程

??? if(!system) {

?????? ?......//應(yīng)用進(jìn)程的處理流程

??? ?} else {//系統(tǒng)進(jìn)程的處理流程,該情況只在SystemServer中處理

?????? //設(shè)置DDMS時(shí)看到的systemserver進(jìn)程名為system_process

?????? android.ddm.DdmHandleAppName.setAppName("system_process");

?????? try {

????????????//ActivityThread的幾員大將出場(chǎng),見(jiàn)后文的分析

????????????mInstrumentation = new Instrumentation();

????????????ContextImpl context = new ContextImpl();

????????????//初始化context,注意第一個(gè)參數(shù)值為getSystemContext

????????????context.init(getSystemContext().mPackageInfo, null, this);

????????????Application app = //利用Instrumentation創(chuàng)建一個(gè)Application對(duì)象

???????????? ???????Instrumentation.newApplication(Application.class,context);

??????????? ?//一個(gè)進(jìn)程支持多個(gè)Application,mAllApplications用于保存該進(jìn)程中

????????????//的Application對(duì)象

????????????mAllApplications.add(app);

???????????? mInitialApplication = app;//設(shè)置mInitialApplication

????????????app.onCreate();//調(diào)用Application的onCreate函數(shù)

?????????? }......//try/catch結(jié)束

????? }//if(!system)判斷結(jié)束

?

???? //注冊(cè)Configuration變化的回調(diào)通知

???? ViewRootImpl.addConfigCallback(newComponentCallbacks2() {

????????? publicvoid onConfigurationChanged(Configuration newConfig) {

????????????......//當(dāng)系統(tǒng)配置發(fā)生變化(如語(yǔ)言切換等)時(shí),需要調(diào)用該回調(diào)

????????? }

???????????public void onLowMemory() {}

???????????public void onTrimMemory(int level) {}

??????? });

?}

attach函數(shù)中出現(xiàn)了幾個(gè)重要成員,其類型分別是Instrumentation類、Application類及Context類,它們的作用如下(為了保證準(zhǔn)確,這里先引用Android的官方說(shuō)明)。

·??Instrumentation:Base class for implementingapplication instrumentation code. When running with instrumentation turned on,this class will be instantiated for you before any of the application code,allowing you to monitor all of the interaction the system has with the application.An Instrumentation implementation is described to the system through anAndroidManifest.xml's <instrumentation> tag.大意是:Instrumentaion是一個(gè)工具類。當(dāng)它被啟用時(shí),系統(tǒng)先創(chuàng)建它,再通過(guò)它來(lái)創(chuàng)建其他組件。另外,系統(tǒng)和組件之間的交互也將通過(guò)Instrumentation來(lái)傳遞,這樣,Instrumentation就能監(jiān)測(cè)系統(tǒng)和這些組件的交互情況了。在實(shí)際使用中,我們可以創(chuàng)建Instrumentation的派生類來(lái)進(jìn)行相應(yīng)的處理。讀者可查詢Android中Junit的使用來(lái)了解Intrstrumentation的作用。本書(shū)不討論Intrstrumentation方面的內(nèi)容。

·??Application:Base class for those who need tomaintain global application state. You can provide your own implementation byspecifying its name in your AndroidManifest.xml's <application> tag,which will cause that class to be instantiated for you when the process foryour application/package is created.大意是:Application類保存了一個(gè)全局的application狀態(tài)。Application由AndroidManifest.xml中的<application>標(biāo)簽聲明。在實(shí)際使用時(shí)需定義Application的派生類。

·??Context:Interface to global informationabout an application environment. This is an abstract class whoseimplementation is provided by the Android system. It allows access toapplication-specific resources and classes, as well as up-calls forapplication-level operations such as launching activities, broadcasting andreceiving intents, etc.大意是:Context是一個(gè)接口,通過(guò)它可以獲取并操作Application對(duì)應(yīng)的資源、類,甚至包含于Application中的四大組件。

提示此處的Application是Android中的一個(gè)概念,可理解為一種容器,它內(nèi)部包含四大組件。另外,一個(gè)進(jìn)程可以運(yùn)行多個(gè)Application。

Context是一個(gè)抽象類,而由AMS創(chuàng)建的將是它的子類ContextImpl。如前所述,Context提供了Application的上下文信息,這些信息是如何傳遞給Context的呢?此問(wèn)題包括兩個(gè)方面:

·??Context本身是什么?

·??Context背后所包含的上下文信息又是什么?

下面來(lái)關(guān)注上邊代碼中調(diào)用的getSystemContext函數(shù)。

(2)?getSystemContext函數(shù)分析

[-->ActivityThread.java::getSystemContext]

public ContextImpl getSystemContext() {

? synchronized(this) {

?? if(mSystemContext == null) {//單例模式

?????? ContextImplcontext =? ContextImpl.createSystemContext(this);

?????? //LoadedApk是2.3引入的一個(gè)新類,代表一個(gè)加載到系統(tǒng)中的APK

?????? LoadedApkinfo = new LoadedApk(this, "android", context, null,

???????????????????????CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);

?????? //初始化該ContextImpl對(duì)象

??????context.init(info, null, this);

????? //初始化資源信息

??????context.getResources().updateConfiguration(

??????????????????????? getConfiguration(),getDisplayMetricsLocked(

???????????????????????CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false));

???????mSystemContext = context;//保存這個(gè)特殊的ContextImpl對(duì)象

????? }

?? }

??? returnmSystemContext;

}

以上代碼無(wú)非是先創(chuàng)建一個(gè)ContextImpl,然后再將其初始化(調(diào)用init函數(shù))。為什么函數(shù)名是getSystemContext呢?因?yàn)樵诔跏蓟疌ontextImp時(shí)使用了一個(gè)LoadedApk對(duì)象。如注釋中所說(shuō),LoadedApk是Android 2.3引入的一個(gè)類,該類用于保存一些和APK相關(guān)的信息(如資源文件位置、JNI庫(kù)位置等)。在getSystemContext函數(shù)中初始化ContextImpl的這個(gè)LoadedApk所代表的package名為“android”,其實(shí)就是framework-res.apk,由于該APK僅供SystemServer使用,所以此處叫g(shù)etSystemContext。

上面這些類的關(guān)系比較復(fù)雜,可通過(guò)圖6-2展示它們之間的關(guān)系。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter6/image002.png" alt="image" />

圖6-2? ContextImpl和它的“兄弟”們

由圖6-2可知:

·??先來(lái)看派生關(guān)系, ApplicationContentResolver從ConentResolver派生,它主要用于和ContentProvider打交道。ContextImpl和ContextWrapper均從Context繼承,而Application則從ContextWrapper派生。

·??從社會(huì)關(guān)系角度看,ContextImpl交際面最廣。它通過(guò)mResources指向Resources,mPackageInfo指向LoadedApk,mMainThread指向ActivityThread,mContentResolver指向ApplicationContentResolver。

·??ActivityThread代表主線程,它通過(guò)mInstrumentation指向Instrumentation。另外,它還保存多個(gè)Application對(duì)象。

注意在函數(shù)中有些成員變量的類型為基類類型,而在圖6-2中直接指向了實(shí)際類型。

(3)?systemMain函數(shù)總結(jié)

調(diào)用systemMain函數(shù)結(jié)束后,我們得到了什么?

·??得到一個(gè)ActivityThread對(duì)象,它代表應(yīng)用進(jìn)程的主線程。

·??得到一個(gè)Context對(duì)象,它背后所指向的Application環(huán)境與framework-res.apk有關(guān)。

費(fèi)了如此大的功夫,systemMain函數(shù)的目的到底是什么?一針見(jiàn)血地說(shuō):

systemMain函數(shù)將為SystemServer進(jìn)程搭建一個(gè)和應(yīng)用進(jìn)程一樣的Android運(yùn)行環(huán)境。這句話涉及兩個(gè)概念。

·??進(jìn)程:來(lái)源于操作系統(tǒng),是在OS中看到的運(yùn)行體。我們編寫(xiě)的代碼一定要運(yùn)行在一個(gè)進(jìn)程中。

·??Android運(yùn)行環(huán)境:Android努力構(gòu)筑了一個(gè)自己的運(yùn)行環(huán)境。在這個(gè)環(huán)境中,進(jìn)程的概念被模糊化了。組件的運(yùn)行及它們之間的交互均在該環(huán)境中實(shí)現(xiàn)。

Android運(yùn)行環(huán)境是構(gòu)建在進(jìn)程之上的。有Android開(kāi)發(fā)經(jīng)驗(yàn)的讀者可能會(huì)發(fā)現(xiàn),在應(yīng)用程序中,一般只和Android運(yùn)行環(huán)境交互?;谕瑯拥牡览?,SystemServer希望它內(nèi)部的那些Service也通過(guò)Android運(yùn)行環(huán)境交互,因此也需為它創(chuàng)建一個(gè)運(yùn)行環(huán)境。由于SystemServer的特殊性,此處調(diào)用了systemMain函數(shù),而普通的應(yīng)用進(jìn)程將在主線程中調(diào)用ActivityThread的main函數(shù)來(lái)創(chuàng)建Android運(yùn)行環(huán)境。

另外,ActivityThread雖然本意是代表進(jìn)程的主線程,但是作為一個(gè)Java類,它的實(shí)例到底由什么線程創(chuàng)建,恐怕不是ActivityThread自己能做主的,所以在SystemServer中可以發(fā)現(xiàn),ActivityThread對(duì)象由其他線程創(chuàng)建,而在應(yīng)用進(jìn)程中,ActivityThread將由主線程來(lái)創(chuàng)建。

3.?ActivityThread.getSystemContext函數(shù)分析

該函數(shù)在上一節(jié)已經(jīng)見(jiàn)過(guò)了。調(diào)用該函數(shù)后,將得到一個(gè)代表系統(tǒng)進(jìn)程的Context對(duì)象。到底什么是Context?先來(lái)看如圖6-3所示的Context家族圖譜。

注意該族譜成員并不完全。另外,Activity、Service和Application所實(shí)現(xiàn)的接口也未畫(huà)出。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter6/image003.png" alt="image" />

圖6-3? Context家族圖譜

由圖6-3可知:

·??ContextWrapper比較有意思,其在SDK中的說(shuō)明為“Proxying implementation ofContext that simply delegates all of its calls to another Context. Can besubclassed to modify behavior without changing the original Context.”大概意思是:ContextWrapper是一個(gè)代理類,被代理的對(duì)象是另外一個(gè)Context。在圖6-3中,被代理的類其實(shí)是ContextImpl,由ContextWrapper通過(guò)mBase成員變量指定。讀者可查看ContextWrapper.java,其內(nèi)部函數(shù)功能的實(shí)現(xiàn)最終都由mBase完成。這樣設(shè)計(jì)的目的是想把ContextImpl隱藏起來(lái)。

·??Application從ContextWrapper派生,并實(shí)現(xiàn)了ComponentCallbacks2接口。Application中有一個(gè)LoadedApk類型的成員變量mLoadedApk。LoadedApk代表一個(gè)APK文件。由于一個(gè)AndroidManifest.xml文件只能聲明一個(gè)Application標(biāo)簽,所以一個(gè)Application必然會(huì)和一個(gè)LoadedApk綁定。

·??Service從ContextWrapper派生,其中Service內(nèi)部成員變量mApplication指向Application(在AndroidManifest.xml中,Service只能作為Application的子標(biāo)簽,所以在代碼中Service必然會(huì)和一個(gè)Application綁定)。

·??ContextThemeWrapper重載了和Theme(主題)相關(guān)的兩個(gè)函數(shù)。這些和界面有關(guān),所以Activity作為Android系統(tǒng)中的UI容器,必然也會(huì)從ContextThemeWrapper派生。與Service一樣,Activity內(nèi)部也通過(guò)mApplication成員變量指向Application。

對(duì)Context的分析先到這里,再來(lái)分析第三個(gè)關(guān)鍵函數(shù)startRunning。

4.? AMS的startRunning函數(shù)分析

[-->ActivityManagerService.java::startRunning]

//注意調(diào)用該函數(shù)時(shí)所傳遞的4個(gè)參數(shù)全為null

public final void startRunning(String pkg, Stringcls, String action,

??????????? ????????????????????????String data) {

??synchronized(this) {

??? ?if (mStartRunning) return; ?//如果已經(jīng)調(diào)用過(guò)該函數(shù),則直接返回

?

????mStartRunning = true;

???? //mTopComponent最終賦值為null

????mTopComponent = pkg != null && cls != null

???????????????????? new ComponentName(pkg, cls) : null;

????mTopAction = action != null ? action : Intent.ACTION_MAIN;

????mTopData = data; //mTopData最終為null

???? if(!mSystemReady) return; //此時(shí)mSystemReady為false,所以直接返回

??? }

???systemReady(null);//這個(gè)函數(shù)很重要,可惜不在本次startRunning中調(diào)用

}

startRunning函數(shù)很簡(jiǎn)單,此處不贅述。

至此,ASM 的main函數(shù)所涉及的4個(gè)知識(shí)點(diǎn)已全部分析完。下面回顧一下AMS 的main函數(shù)的工作。

5.? ActivityManagerService的main函數(shù)總結(jié)

AMS的main函數(shù)的目的有兩個(gè):

·??首先也是最容易想到的目的是創(chuàng)建AMS對(duì)象。

·??另外一個(gè)目的比較隱晦,但是非常重要,那就是創(chuàng)建一個(gè)供SystemServer進(jìn)程使用的Android運(yùn)行環(huán)境。

根據(jù)目前所分析的代碼,Android運(yùn)行環(huán)境將包括兩個(gè)成員:ActivityThread和ContextImpl(一般用它的基類Context)。

圖6-4展示了在這兩個(gè)類中定義的一些成員變量,通過(guò)它們可看出ActivityThread及ContextImpl的作用。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter6/image004.png" alt="image" />

圖6-4? ActivityThread和ContextImpl的部分成員變量

由圖6-4可知:

·??ActivityThread中有一個(gè)mLooper成員,它代表一個(gè)消息循環(huán)。這恐怕是ActivityThread被稱做“Thread”的一個(gè)直接證據(jù)。另外,mServices用于保存Service,Activities用于保存ActivityClientRecord,mAllApplications用于保存Application。關(guān)于這些變量的具體作用,以后遇到時(shí)再說(shuō)。

·??對(duì)于ContextImpl,其成員變量表明它和資源、APK文件有關(guān)。

AMS的main函數(shù)先分析到此,至于其創(chuàng)建的Android運(yùn)行環(huán)境將在下節(jié)分析中派上用場(chǎng)。

接下來(lái)分析AMS的第三個(gè)調(diào)用函數(shù)setSystemProcess。

6.2.2? AMS的setSystemProcess分析

AMS的setSystemProcess的代碼如下:

[-->ActivityManagerService.java::setSystemProcess]

public static void setSystemProcess() {

? try {

??????ActivityManagerService m = mSelf;

?????? //向ServiceManager注冊(cè)幾個(gè)服務(wù)

? ?????ServiceManager.addService("activity",m);

?????? //用于打印內(nèi)存信息

??????ServiceManager.addService("meminfo", new MemBinder(m));

?

?????? /*

??????? Android4.0新增的,用于打印應(yīng)用進(jìn)程使用硬件顯示加速方面的信息(Applications

???????? Graphics Acceleration Info)。讀者通過(guò)adb shell dumpsys gfxinfo看看具體的

???????? 輸出

?????? */

??????ServiceManager.addService("gfxinfo", new GraphicsBinder(m));

?

??????? if(MONITOR_CPU_USAGE)//該值默認(rèn)為true,添加cpuinfo服務(wù)

????????????ServiceManager.addService("cpuinfo", new CpuBinder(m));

?

??????? //向SM注冊(cè)權(quán)限管理服務(wù)PermissionController

???????ServiceManager.addService("permission", newPermissionController(m));

?

??????/*??? 重要說(shuō)明:

??????? 向PackageManagerService查詢package名為"android"的ApplicationInfo。

??????? 注意這句調(diào)用:雖然PKMS和AMS同屬一個(gè)進(jìn)程,但是二者交互仍然借助Context。

??????? 其實(shí),此處完全可以直接調(diào)用PKMS的函數(shù)。為什么要費(fèi)如此周折呢

????? */

??????ApplicationInfo info = //使用AMS的mContext對(duì)象

???????????????mSelf.mContext.getPackageManager().getApplicationInfo(

??????????????????????? "android",STOCK_PM_FLAGS);

?

??????????//①調(diào)用ActivityThread的installSystemApplicationInfo函數(shù)

?????????? ?mSystemThread.installSystemApplicationInfo(info);

???????????synchronized (mSelf) {

???????????????//②此處涉及AMS對(duì)進(jìn)程的管理,見(jiàn)下文分析

???????????????ProcessRecord app = mSelf.newProcessRecordLocked(

???????????????????????mSystemThread.getApplicationThread(), info,

??????????????????????? info.processName);//注意,最后一個(gè)參數(shù)為字符串,值為“system”

???????????????app.persistent = true;

???????????????app.pid = MY_PID;

???????????????app.maxAdj = ProcessList.SYSTEM_ADJ;

???????????????//③保存該P(yáng)rocessRecord對(duì)象

???????????????mSelf.mProcessNames.put(app.processName, app.info.uid, app);

???????????????synchronized (mSelf.mPidsSelfLocked) {

???????????????????mSelf.mPidsSelfLocked.put(app.pid, app);

???????????????}

???????????????//根據(jù)系統(tǒng)當(dāng)前狀態(tài),調(diào)整進(jìn)程的調(diào)度優(yōu)先級(jí)和OOM_Adj,后續(xù)將詳細(xì)分析該函數(shù)

??????? ????????mSelf.updateLruProcessLocked(app, true,true);

???????????}

??????? } ......//拋異常

??? }

在以上代碼中列出了一個(gè)重要說(shuō)明和兩個(gè)關(guān)鍵點(diǎn)。

·??重要說(shuō)明:AMS向PKMS查詢名為“android”的ApplicationInfo。此處AMS和PKMS的交互是通過(guò)Context來(lái)完成的,查看這一系列函數(shù)調(diào)用的代碼,最終發(fā)現(xiàn)AMS將通過(guò)Binder發(fā)送請(qǐng)求給PKMS來(lái)完成查詢功能。AMS和PKMS同屬一個(gè)進(jìn)程,它們完全可以不通過(guò)Context來(lái)交互。此處為何要如此大費(fèi)周章呢?原因很簡(jiǎn)單,Android希望SystemServer中的服務(wù)也通過(guò)Android運(yùn)行環(huán)境來(lái)交互。這更多是從設(shè)計(jì)上來(lái)考慮的,比如組件之間交互接口的統(tǒng)一及未來(lái)系統(tǒng)的可擴(kuò)展性。

·??關(guān)鍵點(diǎn)一:ActivityThread的installSystemApplicationInfo函數(shù)。

·??關(guān)鍵點(diǎn)二:ProcessRecord類,它和AMS對(duì)進(jìn)程的管理有關(guān)。

通過(guò)重要說(shuō)明,相信讀者能真正理解AMS的 main函數(shù)中第二個(gè)隱含目的的作用,故此處不再展開(kāi)敘述。

現(xiàn)在來(lái)看第一個(gè)關(guān)鍵點(diǎn),即ActivityThread的installSystemApplicationInfo函數(shù)。

1.? ActivityThread的installSystemApplicationInfo函數(shù)分析

installSystemApplicationInfo函數(shù)的參數(shù)為一個(gè)ApplicationInfo對(duì)象,該對(duì)象由AMS通過(guò)Context查詢PKMS中一個(gè)名為“android”的package得來(lái)(根據(jù)前面介紹的知識(shí),目前只有framework-res.apk聲明其package名為“android”)。

再來(lái)看installSystemApplicationInfo的代碼,如下所示:

[-->ActivityThread.java::installSystemApplicationInfo]

public voidinstallSystemApplicationInfo(ApplicationInfo info) {

?synchronized (this) {

?? //返回的ContextImpl對(duì)象即之前在AMS的main函數(shù)一節(jié)中創(chuàng)建的那個(gè)對(duì)象

???ContextImpl context = getSystemContext();

??? //又調(diào)用init初始化該Context,是不是重復(fù)調(diào)用init了?

???context.init(new LoadedApk(this, "android", context, info,

??????????????CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this);

???? //創(chuàng)建一個(gè)Profiler對(duì)象,用于性能統(tǒng)計(jì)

??? ?mProfiler = new Profiler();

???? }

?}

在以上代碼中看到調(diào)用context.init的地方,讀者可能會(huì)有疑惑,getSystemContext函數(shù)將返回mSystemContext,而此mSystemContext在AMS的main函數(shù)中已經(jīng)初始化過(guò)了,此處為何再次初始化呢?

仔細(xì)查看看代碼便會(huì)發(fā)現(xiàn):

·??第一次執(zhí)行init時(shí),在LoadedApk構(gòu)造函數(shù)中第四個(gè)表示ApplicationInfo的參數(shù)為null。

·??第二次執(zhí)行init時(shí),LoadedApk構(gòu)造函數(shù)的第四個(gè)參數(shù)不為空,即該參數(shù)將真正指向一個(gè)實(shí)際的ApplicationInfo,該ApplicationInfo來(lái)源于framework-res.apk。

基于上面的信息,某些讀者可能馬上能想到:Context第一次執(zhí)行init的目的僅僅是為了創(chuàng)建一個(gè)Android運(yùn)行環(huán)境,而該Context并沒(méi)有和實(shí)際的ApplicationInfo綁定。而第二次執(zhí)行init前,先利用Context和PKMS交互得到一個(gè)實(shí)際的ApplicationInfo,然后再通過(guò)init將此Context和ApplicationInfo綁定。

是否覺(jué)得前面的疑惑已豁然而解?且慢,此處又拋出了一個(gè)更難的問(wèn)題:

第一次執(zhí)行init后得到的Context雖然沒(méi)有綁定ApplicationInfo,不是也能使用嗎?此處為何非要和一個(gè)ApplicationInfo綁定?

答案很簡(jiǎn)單,因?yàn)閒ramework-res.apk(包括后面將介紹的SettingsProvider.apk)運(yùn)行在SystemServer中。和其他所有apk一樣,它的運(yùn)行需要一個(gè)正確初始化的Android運(yùn)行環(huán)境。

長(zhǎng)噓一口氣,這個(gè)大難題終于弄明白了!在此即基礎(chǔ)上,AMS下一步的工作就就順理成章了。

由于framework-res.apk是一個(gè)APK文件,和其他APK文件一樣,它應(yīng)該運(yùn)行在一個(gè)進(jìn)程中。而AMS是專門用于進(jìn)程管理和調(diào)度的,所以運(yùn)行APK的進(jìn)程應(yīng)該在AMS中有對(duì)應(yīng)的管理結(jié)構(gòu)。因此AMS下一步工作就是將這個(gè)運(yùn)行環(huán)境和一個(gè)進(jìn)程管理結(jié)構(gòu)對(duì)應(yīng)起來(lái)并交由AMS統(tǒng)一管理。

AMS中的進(jìn)程管理結(jié)構(gòu)是ProcessRecord。

2.? 關(guān)于ProcessRecord和IApplicationThread的介紹

分析ProcessRecord之前,先來(lái)思考一個(gè)問(wèn)題:

AMS如何與應(yīng)用進(jìn)程交互?例如AMS啟動(dòng)一個(gè)位于其他進(jìn)程的Activity,由于該Activity運(yùn)行在另外一進(jìn)程中,因此AMS勢(shì)必要和該進(jìn)程進(jìn)行跨進(jìn)程通信。

答案自然是通過(guò)Binder進(jìn)行通信。為此,Android提供了一個(gè)IApplicationThread接口,該接口定義了AMS和應(yīng)用進(jìn)程之間的交互函數(shù),如圖6-5所示為該接口的家族圖譜。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter6/image005.png" alt="image" />

圖6-5? ApplicationThread類

由圖6-5可知:

·??ApplicationThreadNative實(shí)現(xiàn)了IApplicationThread接口。從該接口定義的函數(shù)可知,AMS通過(guò)它可以和應(yīng)用進(jìn)程進(jìn)行交互,例如,AMS啟動(dòng)一個(gè)Activity的時(shí)候會(huì)調(diào)用該接口的scheduleLaunchActivity函數(shù)。

·??ActivityThread通過(guò)成員變量mAppThread指向它的內(nèi)部類ApplicationThread,而ApplicationThread從ApplicationThreadNative派生。

基于以上知識(shí),讀者能快速得出下面問(wèn)題的答案嗎?

IApplicationThread的Binder服務(wù)端在應(yīng)用進(jìn)程中還是在AMS中?

提示如果讀者知道Binder系統(tǒng)支持客戶端監(jiān)聽(tīng)服務(wù)端的死亡消息,那么這個(gè)問(wèn)題的答案就簡(jiǎn)單了:服務(wù)端自然在應(yīng)用進(jìn)程中,因?yàn)锳MS需要監(jiān)聽(tīng)?wèi)?yīng)用進(jìn)程的死亡通知。

有了IApplicationThread接口,AMS就可以和應(yīng)用進(jìn)程交互了。例如,對(duì)于下面一個(gè)簡(jiǎn)單的函數(shù):

[-->ActivityThread.java::scheduleStopActivity]

public final void scheduleStopActivity(IBindertoken, boolean showWindow,

?????????????????????????????????????intconfigChanges) {

??queueOrSendMessage(//該函數(shù)內(nèi)部將給一個(gè)Handler發(fā)送對(duì)應(yīng)的消息

???????????????showWindow ? H.STOP_ACTIVITY_SHOW : H.STOP_ACTIVITY_HIDE,

???????????????token, 0, configChanges);

?}

當(dāng)AMS想要停止(stop)一個(gè)Activity時(shí),會(huì)調(diào)用對(duì)應(yīng)進(jìn)程IApplicationThread Binder客戶端的scheduleStopActivity函數(shù)。該函數(shù)服務(wù)端實(shí)現(xiàn)的就是向ActivityThread所在線程發(fā)送一個(gè)消息。在應(yīng)用進(jìn)程中,ActivityThread運(yùn)行在主線程中,所以這個(gè)消息最終在主線程被處理。

提示Activity的onStop函數(shù)也將在主線程中被調(diào)用。

IApplicationThread僅僅是AMS和另外一個(gè)進(jìn)程交互的接口,除此之外,AMS還需要更多的有關(guān)該進(jìn)程的信息。在AMS中,進(jìn)程的信息都保存在ProcessRecord數(shù)據(jù)結(jié)構(gòu)中。那么,ProcessRecord是什么呢?先來(lái)看setSystemProcess的第二個(gè)關(guān)鍵點(diǎn),即newProcessRecordLocked函數(shù),其代碼如下:

[-->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將為該進(jìn)程創(chuàng)建一個(gè)耗電量統(tǒng)計(jì)項(xiàng)

??????? ps =stats.getProcessStatsLocked(info.uid, proc);

?? }

?? //創(chuàng)建一個(gè)ProcessRecord對(duì)象,用于和其他進(jìn)程通信的thread作為第一個(gè)參數(shù)

?? returnnew ProcessRecord(ps, thread, info, proc);

?}

ProcessRecord的成員變量較多,先來(lái)看看再其構(gòu)造函數(shù)中都初始化了哪些成員變量。

[-->ProcessRecord.java::ProcessRecord]

ProcessRecord(BatteryStatsImpl.Uid.Proc_batteryStats,

??????? IApplicationThread_thread,ApplicationInfo _info, String _processName) {

????batteryStats = _batteryStats; //用于電量統(tǒng)計(jì)

???? info =_info; //保存ApplicationInfo

????processName = _processName; //保存進(jìn)程名

????? //一個(gè)進(jìn)程能運(yùn)行多個(gè)Package,pkgList用于保存package名

????pkgList.add(_info.packageName);

???? thread= _thread;//保存IApplicationThread,通過(guò)它可以和應(yīng)用進(jìn)程交互

?

???? //下面這些xxxAdj成員變量和進(jìn)程調(diào)度優(yōu)先級(jí)及OOM_adj有關(guān)。以后再分析它的作用

???? maxAdj= ProcessList.EMPTY_APP_ADJ;

????hiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;

????curRawAdj = setRawAdj = -100;

???? curAdj= setAdj = -100;

? ?//用于控制該進(jìn)程是否常駐內(nèi)存(即使被殺掉,系統(tǒng)也會(huì)重啟它),只有重要的進(jìn)程才會(huì)有此待遇

????persistent = false;

???? removed= false;

}

ProcessRecord除保存和應(yīng)用進(jìn)程通信的IApplicationThread對(duì)象外,還保存了進(jìn)程名、不同狀態(tài)對(duì)應(yīng)的Oom_adj值及一個(gè)ApplicationInfo。一個(gè)進(jìn)程雖然可運(yùn)行多個(gè)Application,但是ProcessRecord一般保存該進(jìn)程中先運(yùn)行的那個(gè)Application的ApplicationInfo。

至此,已經(jīng)創(chuàng)建了一個(gè)ProcessRecord對(duì)象,和其他應(yīng)用進(jìn)程不同的是,該對(duì)象對(duì)應(yīng)的進(jìn)程為SystemServer。為了彰顯其特殊性,AMS為其中的一些成員變量設(shè)置了特定的值:

?? app.persistent = true;//設(shè)置該值為true

?? app.pid =MY_PID;//設(shè)置pid為SystemServer的進(jìn)程號(hào)

?? app.maxAdj= ProcessList.SYSTEM_ADJ;//設(shè)置最大OOM_Adj,系統(tǒng)進(jìn)程默認(rèn)值為-16

?? //另外,app的processName被設(shè)置成“system”

這時(shí),一個(gè)針對(duì)SystemServer的ProcessRecord對(duì)象就創(chuàng)建完成了。此后AMS將把它并入自己的勢(shì)力范圍內(nèi)。

AMS中有兩個(gè)成員變量用于保存ProcessRecord,一個(gè)是mProcessNames,另一個(gè)是mPidsSelfLocked,如圖6-6所示為這兩個(gè)成員變量的數(shù)據(jù)結(jié)構(gòu)示意圖。

http://wiki.jikexueyuan.com/project/deep-android-v2/images/chapter6/image006.png" alt="image" />

圖6-6? mPidsSelfLocked和mProcessNames數(shù)據(jù)結(jié)構(gòu)示意圖

3.? AMS的setSystemProcess總結(jié)

現(xiàn)在來(lái)總結(jié)回顧setSystemProcess的工作:

·??注冊(cè)AMS、meminfo、gfxinfo等服務(wù)到ServiceManager中。

·??根據(jù)PKMS返回的ApplicationInfo初始化Android運(yùn)行環(huán)境,并創(chuàng)建一個(gè)代表SystemServer進(jìn)程的ProcessRecord,從此,SystemServer進(jìn)程也并入AMS的管理范圍內(nèi)。

?

6.2.3? AMS的installSystemProviders函數(shù)分析

還記得Settings數(shù)據(jù)庫(kù)嗎?SystemServer中很多Service都需要向它查詢配置信息。為此,Android提供了一個(gè)SettingsProvider來(lái)幫助開(kāi)發(fā)者。該P(yáng)rovider在SettingsProvider.apk中,installSystemProviders就會(huì)加載該APK并把SettingsProvider放到SystemServer進(jìn)程中來(lái)運(yùn)行。

此時(shí)的SystemServer已經(jīng)加載了framework-res.apk,現(xiàn)在又要加載另外一個(gè)APK文件,這就是多個(gè)APK運(yùn)行在同一進(jìn)程的典型案例。另外,通過(guò)installSystemProviders函數(shù)還能見(jiàn)識(shí)ContentProvider的安裝過(guò)程,下面就來(lái)分析它。

提示讀者在定制自己的Android系統(tǒng)時(shí),萬(wàn)不可去掉/system/app/SettingsProvider.apk,否則系統(tǒng)將無(wú)法正常啟動(dòng)。

[-->ActivityManagerService.java::installSystemProviders]

public static final void installSystemProviders(){

?List<ProviderInfo> providers;

?synchronized (mSelf) {

??? /*

??? 從mProcessNames找到進(jìn)程名為“system”且uid為SYSTEM_UID的ProcessRecord,

?? ?返回值就是前面在installSystemApplication中創(chuàng)建的那個(gè)ProcessRecord,它代表

?? ?SystemServer進(jìn)程

??? */

???ProcessRecord app = mSelf.mProcessNames.get("system",Process.SYSTEM_UID);

?

??? //①關(guān)鍵調(diào)用,見(jiàn)下文分析

??? providers= mSelf.generateApplicationProvidersLocked(app);

??? if(providers != null) {

?????? ......//將非系統(tǒng)APK(即未設(shè)ApplicationInfo.FLAG_SYSTEM標(biāo)志)提供的Provider

????? //從providers列表中去掉

??????? }

???? if(providers != null) {//②為SystemServer進(jìn)程安裝Provider

?????????mSystemThread.installSystemProviders(providers);

???? }

??? //監(jiān)視Settings數(shù)據(jù)庫(kù)中Secure表的變化,目前只關(guān)注long_press_timeout配置的變化

????mSelf.mCoreSettingsObserver = new CoreSettingsObserver(mSelf);

?

???? //UsageStatsService的工作,以后再討論

????mSelf.mUsageStatsService.monitorPackages();

?}

在代碼