AMS啟動過程

com.android.server.am.ActivityManagerService

本文在 API 27 基礎(chǔ)上展開分析。
文章篇幅的長度與附上的代碼量有關(guān)希痴,請耐心查看。
沒時間的小伙伴春感,可以先大概瀏覽砌创,有一個感性認(rèn)識,后續(xù)再進(jìn)行研究鲫懒。

本文也是參考學(xué)習(xí)嫩实,如有錯誤,歡迎指正~

本文分析AMS啟動過程的主要流程窥岩,并非全部甲献。
有針對性和選擇性的分析AMS的相關(guān)代碼,非AMS的暫不討論颂翼。

為防止深入代碼導(dǎo)致記憶混亂晃洒,采用 step 標(biāo)識跟進(jìn),例如 step 1朦乏,step 1.1锥累,step 1.1.1 標(biāo)識從某個方法入口依次跟進(jìn)。

摘要

AMS - ActivityManagerService 集歇,是 Android 最核心 的服務(wù)桶略,主要負(fù)責(zé)系統(tǒng)中 四大組件 的啟動、切換、調(diào)度及應(yīng)用程序的管理和調(diào)度等工作际歼。

AMS通信結(jié)構(gòu)如下圖所示:

AMS通信

關(guān)鍵詞

  1. AMS:ActivityManagerService 惶翻;PMS-PackageManagerService;
  2. 系統(tǒng)服務(wù)鹅心;普通應(yīng)用吕粗;Client / Service 思想;
  3. Application旭愧;ApplicationInfo颅筋;
  4. SystemServiceManager;ServiceManager输枯;LocalServices议泵;

AMS啟動過程

為使讀者對AMS啟動有明確的方向,先將大致流程拋出來桃熄,方便整體把控先口。

  1. 創(chuàng)建出 SystemServer 進(jìn)程的 Android 運行環(huán)境
  2. AMS 的初始化和啟動
  3. SystemServer 進(jìn)程納入到 AMS 的管理體系
  4. AMS 啟動完成的后續(xù)工作

前提 已知

  1. Zygote 創(chuàng)建 fork 出的第一個 java 進(jìn)程是 SystemServer
  2. 每個進(jìn)程的入口是 main 函數(shù)瞳收。
com.android.internal.os.Zygote

public static void main(String argv[]) {
    ...
    Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
    ...
}

整個過程從 SystemServer 進(jìn)程的入口開始分析碉京,涉及 AMS 啟動主要過程的偽代碼如下:

com.android.server.SystemServer

public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    try {
        ...
        // Initialize native services.
        System.loadLibrary("android_servers");
        ...
        // Initialize the system context.
        // systemServer在啟動任何服務(wù)之前,先調(diào)用了createSystemContext 創(chuàng)建出 mSystemContext
        // step 1 
        createSystemContext();

        // Create the system service manager.
        // SystemServiceManager 負(fù)責(zé)啟動所有的 系統(tǒng)服務(wù)
        // mSystemContext 構(gòu)造出 SystemServiceManager螟深,
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        ...
        // LocalServices 管理當(dāng)前進(jìn)程的服務(wù)
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        ...
    } finally {
        ....
    }

    // Start services.
    try {
        ...
        // step 2 啟動引導(dǎo)服務(wù)谐宙,在其中創(chuàng)建并啟動AMS
        startBootstrapServices();
        ...
        // step 3 啟動其他服務(wù),在其中AMS注冊了SettingsProvider和其他后續(xù)工作
        startOtherServices();
        ...
    } catch (Throwable ex) {
        ...
    } finally {
        ...
    }
    ...
    // Loop forever.
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

Step 1 createSystemContext()

創(chuàng)建出 SystemServer 進(jìn)程的 Android 運行環(huán)境

com.android.server.SystemServer

private void createSystemContext() {
    // step 1.1 調(diào)用ActivityThread的systemMain函數(shù)界弧,其中會創(chuàng)建出系統(tǒng)對應(yīng)的Context對象
    ActivityThread activityThread = ActivityThread.systemMain();
    // step 1.2 取出上面函數(shù)創(chuàng)建的Context對象凡蜻,保存在mSystemContext中
    mSystemContext = activityThread.getSystemContext();
    // 設(shè)置系統(tǒng)主題
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
    ...
}

Step 1.1 ActivityThread.systemMain()

調(diào)用 ActivityThreadsystemMain() 函數(shù),其中會創(chuàng)建出系統(tǒng)對應(yīng)的 Context 對象

android.app.ActivityThread

public static ActivityThread systemMain() {
    //雖然寫著ActivityManager夹纫,但和AMS沒有任何關(guān)系咽瓷,就是利用系統(tǒng)屬性和配置信息進(jìn)行判斷
    if (!ActivityManager.isHighEndGfx()) {
        //低版本關(guān)閉硬件渲染功能
        ThreadedRenderer.disable(true);
    } else {
        ThreadedRenderer.enableForegroundTrimming();
    }

    // step 1.1.1 創(chuàng)建ActivityThread
    ActivityThread thread = new ActivityThread();
    //step 1.1.2 調(diào)用attach函數(shù),參數(shù)為true
    thread.attach(true);
    return thread;
}

ActivityThread 有自己的 main 入口函數(shù)舰讹,明確此處調(diào)用的是 systemMain()茅姜。

ActivityThread#systemMain() 了解到主要功能有:

  1. 判斷是否開啟硬件加速。
  2. 創(chuàng)建 ActivityThread 對象月匣。
  3. 調(diào)用 thread 對象的 attach(true)钻洒,注意參數(shù) system 傳入** true**。
Step 1.1.1 ActivityThread thread = new ActivityThread();

ActivityThread 的構(gòu)造函數(shù)比較簡單

com.android.app.ActivityThread

ActivityThread() {
    mResourcesManager = ResourcesManager.getInstance();
}

比較關(guān)鍵的是它內(nèi)部的成員變量锄开,

com.android.app.ActivityThread

public final class ActivityThread {
    ...
    //定義了AMS與應(yīng)用通信的接口
    final ApplicationThread mAppThread = new ApplicationThread();

    //擁有自己的looper素标,說明ActivityThread確實可以代表事件處理線程
    final Looper mLooper = Looper.myLooper();

    //H繼承Handler,ActivityThread中大量事件處理依賴此Handler
    final H mH = new H();

    //用于保存該進(jìn)程的ActivityRecord
    final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>()
    ...
    //用于保存進(jìn)程中的Service
    final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
    ...
    //用于保存進(jìn)程中的Application
    final ArrayList<Application> mAllApplications = new ArrayList<Application>();
    ...
}

ActivityThread萍悴,是 Android Framework 中一個非常重要的類头遭,它代表應(yīng)用進(jìn)程主線程寓免,其職責(zé)是調(diào)度及執(zhí)行在該線程中運行的四大組件。

在Android中
應(yīng)用進(jìn)程计维,指那些運行Apk的進(jìn)程袜香,它們有Zygote fork出來,其中運行著獨立的dalvik虛擬機鲫惶。
系統(tǒng)進(jìn)程蜈首,也應(yīng)用進(jìn)程相對,例如 Zygote 和 SystemServer欠母。其中SystemServer 也是由Zygote fork出來的欢策,也運行著一些系統(tǒng)Apk,例如 framework-res.apk赏淌、SettingsProvider.apk 等踩寇,該進(jìn)程也創(chuàng)建了主線程ActivityThread,所以SystemServer也可以看做是特殊的應(yīng)用進(jìn)程

對于上面提到的ActivityThread的成員變量猜敢,其用途基本上可以從名稱中得知姑荷,這里僅說明一下ApplicationThread盒延。

AMS負(fù)責(zé) 進(jìn)管理進(jìn)程調(diào)度缩擂,因此 AMS 和應(yīng)用進(jìn)程之間通信需要 Binder機制。為此 Android 提供了一個 android.app.IApplicationThread 接口添寺,繼承 IInterface胯盯,該接口定義了 AMS 和應(yīng)用進(jìn)程之間的交互函數(shù)。例如:scheduleLaunchActivity 计露、scheduleCreateService

當(dāng) AMS 與應(yīng)用進(jìn)程通信時博脑,ApplicationThread 繼承 IApplicationThread.Stub 作為Binder通信的服務(wù)端。

step 1.1.2 thread.attach(true);
android.app.ActivityThread

//此時票罐,我們傳入的參數(shù)為true叉趣,表示該ActivityThread是**系統(tǒng)進(jìn)程的ActivityThread**
private void attach(boolean system) {
    //創(chuàng)建出的ActivityThread保存在類的靜態(tài)變量sCurrentActivityThread
    //AMS中的大量操作將會依賴于這個ActivityThread
    sCurrentActivityThread = this;
    mSystemThread = system;

    if (!system) {
        //  '應(yīng)用進(jìn)程' 的處理流程
       ...
    } else { 
        // '系統(tǒng)進(jìn)程' 的處理流程,該情況只在SystemServer中處理

        // Don't set application object here -- if the system crashes,
        // we can't display an alert, we just want to die die die.
        //設(shè)置DDMS(Dalvik Debug Monitor Service)中看到的SystemServer進(jìn)程的名稱為“system_process”
        android.ddm.DdmHandleAppName.setAppName("system_process", UserHandle.myUserId());

        try {
            // 創(chuàng)建ActivityThread中的重要成員:
            // Instrumentation该押、Application疗杉、Context
            // step 1.1.2.1 
            mInstrumentation = new Instrumentation();
            // step 1.1.2.3
            ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo); // step 1.1.2.2
             // step 1.1.2.4
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            mInitialApplication.onCreate();
        } catch (Exception e) {
            ...
        }
    }

    //以下系統(tǒng)進(jìn)程和非系統(tǒng)進(jìn)程均會執(zhí)行
    ...
    //注冊Configuration變化的回調(diào)通知
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            //當(dāng)系統(tǒng)配置發(fā)生變化時(例如系統(tǒng)語言發(fā)生變化),回調(diào)該接口
            ...
        }
       ...
    });
}

系統(tǒng)進(jìn)程在ActivityThread的attach函數(shù)的主要工作:

  1. 創(chuàng)建Instrumentation
  2. 創(chuàng)建Context
    Context是Android中的一個抽象類蚕礼,用于維護(hù)應(yīng)用運行環(huán)境的全局信息烟具。
    通過Context可以訪問應(yīng)用的資源和類,甚至進(jìn)行系統(tǒng)級的操作奠蹬,例如啟動Activity朝聋、發(fā)送廣播等。
  3. 創(chuàng)建Application
step 1.1.2.1 new Instrumentation()

Instrumentation是Android中的一個工具類囤躁,當(dāng)該類被啟動時冀痕,它將優(yōu)先于其它的類被初始化荔睹。
此時,系統(tǒng)先創(chuàng)建它言蛇,再通過它創(chuàng)建其它組件应媚。

此外,系統(tǒng)和應(yīng)用組件之間的交互也將通過Instrumentation來傳遞猜极。
因此中姜,Instrumentation就能監(jiān)控系統(tǒng)和組件的交互情況了。

實際使用時,可以創(chuàng)建該類的派生類進(jìn)行相應(yīng)的操作徘键。
這個類在介紹啟動Activity的過程時還會碰到厕吉,此處不作展開。

step 1.1.2.2 getSystemContext()
android.app.ActivityThread

public ContextImpl getSystemContext() {
    synchronized (this) {
        if (mSystemContext == null) {
            //調(diào)用ContextImpl的靜態(tài)函數(shù)createSystemContext
            // step 1.1.2.2.1
            mSystemContext = ContextImpl.createSystemContext(this);
        }
        return mSystemContext;
    }
}

step 1.1.2.2.1 ContextImpl.createSystemContext

android.app.ContextImpl

static ContextImpl createSystemContext(ActivityThread mainThread) {
    // 創(chuàng)建LoadedApk類携龟,代表一個加載到系統(tǒng)中的APK
    // 注意現(xiàn)在處于構(gòu)建Android運行環(huán)境階段,PMS服務(wù)還沒有啟動勘高,無法得到有效的Application峡蟋,后續(xù)PMS啟動后,后調(diào)用 LoadedApk.installSystemApplicationInfo 進(jìn)行填充
    // 此時實例化的LoadedApk只是一個空殼华望,內(nèi)部使用空的Application
    // step 1.1.2.2.1.1 
    LoadedApk packageInfo = new LoadedApk(mainThread);

    //調(diào)用ContextImpl的構(gòu)造函數(shù)蕊蝗,參數(shù)中傳入了上面生成的對象packageInfo
    ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
            null);
    // 初始化資源 
    context.setResources(packageInfo.getResources());
    context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
            context.mResourcesManager.getDisplayMetrics());
    return context;
}

createSystemContext的主要工作:

  1. 創(chuàng)建一個 LoadApk,代表一個加載到系統(tǒng)中的Apk
  2. 將傳入的線程參數(shù) mainThread 和 上一步生成的packageInfo 實例化一個ContextImpl對象

似乎沒有什么特別的赖舟,那么為什么函數(shù)名叫做 createSystemContext 蓬戚??
為了回答這個問題宾抓,就要看看LoadedApk的構(gòu)造函數(shù)

step 1.1.2.2.1.1

android.app.LoadApk

LoadedApk(ActivityThread activityThread) {
    mActivityThread = activityThread;
    mApplicationInfo = new ApplicationInfo();

    //packageName為"android"
    mApplicationInfo.packageName = "android";
    mPackageName = "android";
    //下面許多參數(shù)為null
    ...
}

注意到 mPackageName = "android"子漩,也就是 framework-res.apk。該Apk僅供SystemServer進(jìn)程使用石洗,因此上一步的方法名被定義成 createSystemContext幢泼。

又注意到,實例化了一個mApplicationInfo對象讲衫,但是只賦值了其中的packageName屬性缕棵,所以說現(xiàn)在的LoadedApk只是一個空殼。ApplicationInfo中包含了許多Apk重要信息焦人,當(dāng)之后的PMS啟動挥吵,完成對應(yīng)的解析后,AMS將重新調(diào)用 LoadedApk.installSystemApplicationInfo 進(jìn)行填充花椭。

step 1.1.2.3 ContextImpl.createAppContext
android.app.ContextImpl

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
            null);
    context.setResources(packageInfo.getResources());
    return context;
}

createAppContext的工作比較簡單忽匈,利用 ActivityThread 和 LoadApk 構(gòu)造出 ContextImpl。

ContextImpl的構(gòu)造函數(shù)主要是完成了一些變量的初始化矿辽,建立起 ContextImpl 與 ActivityThread丹允、LoadApk郭厌、ContentResolver 之間的關(guān)系。
以后可以從 ContextImpl中 獲取一些變量雕蔽。

注意 createAppContext 和 上一步的 createSystemContext 中構(gòu)造 ContextImpl是一樣的

代碼簡單折柠,不再展開,注意在函數(shù)的最后建立和 ContentResolver 之間的聯(lián)系

mContentResolver = new ApplicationContentResolver(this, mainThread, user);
step 1.1.2.4 context.mPackageInfo.makeApplication

先來看一下 Application 關(guān)系圖

Application 關(guān)系圖

Android中Application類用于保存應(yīng)用的全局狀態(tài)

Activity和Service都和具體的Application綁定在一起批狐,通過繼承關(guān)系可知扇售,每個Activity和Service均加入到Android運行環(huán)境中。

android.app.ActivityThread

private void attach(boolean system) {
    ...
        // mPackageInfo是LoadApk類型嚣艇,從context中獲取LoadApk承冰,然后調(diào)用LoadApk的makeApplication函數(shù)
        // step 1.1.2.4
    mInitialApplication = context.mPackageInfo.makeApplication(true, null);
    // 調(diào)用Application的onCreate方法
    mInitialApplication.onCreate();
    ...
}
android.app.LoadedApk

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    ...

    Application app = null;

    String appClass = mApplicationInfo.className;
    // 此流程 forceDefaultAppClass == true
    if (forceDefaultAppClass || (appClass == null)) {
        // 系統(tǒng)進(jìn)程中,對應(yīng)下面的appClass
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
           initializeJavaContextClassLoader();
        }
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        //實際上最后通過反射創(chuàng)建出Application
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ...
    }
    //一個進(jìn)程支持多個Application食零,mAllApplications用于保存該進(jìn)程中的Application對象
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    // 此流程 instrumentation == null
    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    }

    // Rewrite the R 'constants' for all library apks.
    ...
    return app;
}

makeApplication 的主要工作:

  1. 創(chuàng)建 framework-res.apk 對應(yīng)的Application
  2. 調(diào)用Application的onCreate函數(shù)

總結(jié) createSystemContext

至此困乒,createSystemContext函數(shù)介紹完畢。

當(dāng) SystemServer 調(diào)用 createSystemContext 完畢后:

  1. 得到一個 ActivityThread 對象贰谣,它代表當(dāng)前進(jìn)程(系統(tǒng)進(jìn)程)的主線程
  2. 得到一個 Context娜搂,對于 SystemServer 而言,它包含 Application 運行環(huán)境 和 framework-res.apk(名為"android"的LoadedAPK) 有關(guān)吱抚。

思考

Q:為什么啟動所有的服務(wù)前百宇,SystemServer先要調(diào)用createSystemContext?
A:眾所周知频伤,Android是以Java為基礎(chǔ)的恳谎,Java運行在進(jìn)程中芝此。
但是憋肖,Android想努力構(gòu)筑一個自己的運行環(huán)境,組件的運行和它們之間的交互均在該環(huán)境中實現(xiàn)婚苹。

createSystemContext 函數(shù)就是為* SystemServer系統(tǒng)進(jìn)程* 搭建一個和 普通應(yīng)用進(jìn)程 一樣的 Android環(huán)境岸更。

Android運行環(huán)境,是在進(jìn)程的基礎(chǔ)上構(gòu)建的膊升,但是把 進(jìn)程的概念被模糊化怎炊,所以應(yīng)用程序一般只和Android運行環(huán)境交互。

基于同樣的道理廓译,Android 希望 SystemServer進(jìn)程內(nèi)部運行的應(yīng)用评肆,也通過Android運行環(huán)境交互,因此才調(diào)用了 createSystemContext 函數(shù)非区。

創(chuàng)建Android運行環(huán)境時瓜挽,
由于SystemServer的特殊性,SystemServer.main() 調(diào)用了 ActivityThread.systemMain() 函數(shù)
對于普通的應(yīng)用程序征绸,將在自己的主線程匯中調(diào)用 ActivityThread.main() 函數(shù)

進(jìn)程 的 Android運行環(huán)境 涉及的主要類之間的關(guān)系如下圖久橙,其中核心類是ContextImpl 俄占,通過它可以得到 ContentResolver、系統(tǒng)資源Resources淆衷、應(yīng)用信息Application缸榄、當(dāng)前進(jìn)程的主線程ActivityThread、Apk信息LoadedApk等祝拯。

Android 運行環(huán)境涉及的主要類之前的關(guān)系

Step 2 AMS初始化

Step 1 創(chuàng)建完Android運行環(huán)境和創(chuàng)建系統(tǒng)服務(wù)管理后甚带,創(chuàng)建了SystemServiceManager,并將其加入到了 LocalServices 中佳头。

com.android.server.SystemServer

private void run() {
    // Step 1
    createSystemContext();
    // Create the system service manager.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    ...
    // Step 2
    startBootstrapServices();
}

之后欲低,SystemServer 就調(diào)用了 startBootstrapServices
正式進(jìn)入AMS的創(chuàng)建和啟動過程

偽代碼如下:

com.android.server.SystemServer

private void startBootstrapServices() {
    Installer installer = mSystemServiceManager.startService(Installer.class);
    ...
   
    // Activity manager runs the show.
    // 啟動AMS畜晰,然后獲取AMS保存到變量中
    // Step 2.1
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();

    //以下均是將變量存儲到AMS中
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer); 
    ...
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mPackageManager = mSystemContext.getPackageManager();
    ...
    // Set up the Application instance for the system process and get started.
    // Step 2.2
   mActivityManagerService.setSystemProcess();
   ...
   mPackageManagerService.systemReady();
   ...
   mActivityManagerService.systemReady(()->{ ... });
   ...

}

注意上面代碼 mSystemServiceManager 并沒有直接啟動 AMS 砾莱,而是啟動 AMS 的內(nèi)部類ActivityManagerService.Lifecycle.
由于 AMS 并沒有繼承 SystemService ,因此不能通過 SystemServiceManager.startService() 直接啟動(內(nèi)部實現(xiàn)采用反射的方式)凄鼻,例如可以直接啟動Installer腊瑟。

AMS 的內(nèi)部類 Lifecycle 繼承 SystemService ,像一個適配器來間接操作 AMS块蚌。讓 AMS 能夠 SystemService 一樣被 SystemServiceManager 通過反射的方式啟動闰非。

Lifecycle類簡單如下:

com.android.server.am.ActivityManagerService

public static final class Lifecycle extends SystemService {
   private final ActivityManagerService mService;

   public Lifecycle(Context context) {
        super(context);
        // step 2.1.1 調(diào)用AMS的構(gòu)造函數(shù)
        mService = new ActivityManagerService(context);
   }

   @Override
   public void onStart() {
        // step 2.1.2 調(diào)用AMS的start函數(shù)
        mService.start();
   }

   @Override
   public void onCleanupUser(int userId) {
        mService.mBatteryStatsService.onCleanupUser(userId);
   }

   public ActivityManagerService getService() {
        return mService;
   }
}
Step 2.1.1 AMS 構(gòu)造函數(shù)

構(gòu)造函數(shù)較長但簡單,主要初始化了一些變量峭范,可以過一遍

public ActivityManagerService(Context systemContext) {
    //AMS的運行上下文與SystemServer一致
    mContext = systemContext;
    ............
    //取出的是ActivityThread的靜態(tài)變量sCurrentActivityThread
    //這意味著mSystemThread與SystemServer中的ActivityThread一致
    mSystemThread = ActivityThread.currentActivityThread();
    ............
    mHandlerThread = new ServiceThread(TAG,
            android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    mHandlerThread.start();
    //處理AMS中消息的主力
    mHandler = new MainHandler(mHandlerThread.getLooper());

    //UiHandler對應(yīng)于Android中的UiThread
    mUiHandler = new UiHandler();

    if (sKillHandler == null) {
        sKillThread = new ServiceThread(TAG + ":kill",
                android.os.Process.THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
        sKillThread.start();
        //用于接收消息财松,殺死進(jìn)程
        sKillHandler = new KillHandler(sKillThread.getLooper());
    }

    //創(chuàng)建兩個BroadcastQueue,前臺的超時時間為10s纱控,后臺的超時時間為60s
    mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "foreground", BROADCAST_FG_TIMEOUT, false);
    mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "background", BROADCAST_BG_TIMEOUT, true);
    mBroadcastQueues[0] = mFgBroadcastQueue;
    mBroadcastQueues[1] = mBgBroadcastQueue;

    //創(chuàng)建變量辆毡,用于存儲信息
    mServices = new ActiveServices(this);
    mProviderMap = new ProviderMap(this);
    mAppErrors = new AppErrors(mContext, this);

    //這一部分,分析BatteryStatsService時提過甜害,進(jìn)行BSS的初始化
    File dataDir = Environment.getDataDirectory();
    File systemDir = new File(dataDir, "system");
    systemDir.mkdirs();
    mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
    mBatteryStatsService.getActiveStatistics().readLocked();
    mBatteryStatsService.scheduleWriteToDisk();
    mOnBattery = DEBUG_POWER ? true
            : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
    mBatteryStatsService.getActiveStatistics().setCallback(this);

    //創(chuàng)建ProcessStatsService舶掖,感覺用于記錄進(jìn)程運行時的統(tǒng)計信息,例如內(nèi)存使用情況尔店,寫入/proc/stat文件
    mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));

    //啟動Android的權(quán)限檢查服務(wù)眨攘,并注冊對應(yīng)的回調(diào)接口
    mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
    mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null,
            new IAppOpsCallback.Stub() {
                @Override public void opChanged(int op, int uid, String packageName) {
                    if (op == AppOpsManager.OP_RUN_IN_BACKGROUND && packageName != null) {
                        if (mAppOpsService.checkOperation(op, uid, packageName)
                                != AppOpsManager.MODE_ALLOWED) {
                            runInBackgroundDisabled(uid);
                        }
                    }
                }
            });

    //用于定義ContentProvider訪問指定Uri對應(yīng)數(shù)據(jù)的權(quán)限,aosp中似乎沒有這文件
    mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"));

    //創(chuàng)建多用戶管理器
    mUserController = new UserController(this);

    //獲取OpenGL版本
    GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
            ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
    ............
    //資源配置信息置為默認(rèn)值
    mConfiguration.setToDefaults();
    mConfiguration.setLocales(LocaleList.getDefault());
    mConfigurationSeq = mConfiguration.seq = 1;

    //感覺用于記錄進(jìn)程的CPU使用情況
    mProcessCpuTracker.init();

    //解析/data/system/packages-compat.xml文件嚣州,該文件用于存儲那些需要考慮屏幕尺寸的APK的一些信息
    //當(dāng)APK所運行的設(shè)備不滿足要求時鲫售,AMS會根據(jù)xml設(shè)置的參數(shù)以采用屏幕兼容的方式運行該APK
    mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);

    //用于根據(jù)規(guī)則過濾一些Intent
    mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);

    //以下的類,似乎用于管理和監(jiān)控AMS維護(hù)的Activity Task信息
    //ActivityStackSupervisor是AMS中用來管理Activity啟動和調(diào)度的核心類
    mStackSupervisor = new ActivityStackSupervisor(this);
    mActivityStarter = new ActivityStarter(this, mStackSupervisor);
    mRecentTasks = new RecentTasks(this, mStackSupervisor);

    //創(chuàng)建線程用于統(tǒng)計進(jìn)程的CPU使用情況
    mProcessCpuThread = new Thread("CpuTracker") {
        @Override
        public void run() {
            while (true) {
                try {
                    try {
                        //計算更新信息的等待間隔
                        //同時利用wait等待計算出的間隔時間
                        ......
                    } catch(InterruptedException e) {
                    }
                    //更新CPU運行統(tǒng)計信息
                    updateCpuStatsNow();
                } catch (Exception e) {
                    ..........
                }
            }
        }
    };

    //加入Watchdog的監(jiān)控
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);
}
Step 2.1.2 AMS 的 start 函數(shù)
private void start() {
    //完成統(tǒng)計前的復(fù)位工作
    Process.removeAllProcessGroups();

    //開始監(jiān)控進(jìn)程的CPU使用情況
    mProcessCpuThread.start();

    //注冊電池狀態(tài)服務(wù)
    mBatteryStatsService.publish(mContext);

    //注冊一些應(yīng)用信息和控制的服務(wù)该肴,比如權(quán)限等
    mAppOpsService.publish(mContext);
    
    // ActivityManagerInternal 是 activity manager 本地管理服務(wù)的接口
    LocalServices.addService(ActivityManagerInternal.class, new LocalService());
}

start() 函數(shù)的主要工作:

  1. 啟動CPU監(jiān)控線程情竹,該線程將會開始統(tǒng)計不同進(jìn)程使用CPU的情況
  2. 發(fā)布一些服務(wù),如BatteryStatsService沙庐、AppOpsService(權(quán)限管理相關(guān))和本地實現(xiàn)的LocalService繼承ActivityManagerInternal的服務(wù)

至此鲤妥,AMS 初始化完成
下一步將 SystemServer 納入AMS的管理體系

step 2.2 AMS#setSystemProcess

public void setSystemProcess() {
   try {
        // step 2.2.1 以下幾個向ServiceManager注冊幾個服務(wù)
        // AMS自己佳吞,在這里注冊,以后通過ServiceManager獲取棉安,最常見的獲取key為"activity"的服務(wù)
       ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
       //注冊進(jìn)程統(tǒng)計信息的服務(wù)
       ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
       //用于打印內(nèi)存信息用的
       ServiceManager.addService("meminfo", new MemBinder(this));
       //用于輸出進(jìn)程使用硬件渲染方面的信息
       ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
       //用于輸出數(shù)據(jù)庫相關(guān)的信息
       ServiceManager.addService("dbinfo", new DbBinder(this));
       //MONITOR_CPU_USAGE默認(rèn)為true
      if (MONITOR_CPU_USAGE) {
           //用于輸出進(jìn)程的CPU使用情況
           ServiceManager.addService("cpuinfo", new CpuBinder(this));
       }
       //注冊權(quán)限管理服務(wù)
       ServiceManager.addService("permission", new PermissionController(this));
        //注冊獲取進(jìn)程信息的服務(wù)
       ServiceManager.addService("processinfo", new ProcessInfoService(this));

        // step 2.2.2 通過 PMS 查詢 package 名為 "android" 的應(yīng)用的ApplicationInfo底扳,即系統(tǒng)應(yīng)用
       ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
               "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
               
        // step 2.2.3 通過查詢的結(jié)果進(jìn)行安裝
       mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

        // step 2.2.4 以下與AMS的進(jìn)程管理
       synchronized (this) {
           ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
           app.persistent = true;
           app.pid = MY_PID;
           app.maxAdj = ProcessList.SYSTEM_ADJ;
           app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
           synchronized (mPidsSelfLocked) {
               mPidsSelfLocked.put(app.pid, app);
           }
           updateLruProcessLocked(app, false, null);
           updateOomAdjLocked();
       }
   } catch (PackageManager.NameNotFoundException e) {
       throw new RuntimeException(
               "Unable to find android system package", e);
   }
}

AMS的setSystemProcess有四個主要功能:

  1. ServiceManager 注冊服務(wù)統(tǒng)一管理,如 AMS 本身贡耽。
  2. 獲取 package 名為 "android" 的應(yīng)用的 ApplicationInfo衷模,即系統(tǒng)應(yīng)用 framework-res.apk
  3. 調(diào)用 ActivityThreadinstallSystemApplicationInfo蒲赂,回憶之前創(chuàng)建的 LoadedApk 是一個空殼阱冶,沒有實際的 ApplicationInfo
  4. AMS 進(jìn)程管理相關(guān)的操作
step 2.2.1 注冊服務(wù) ServiceManager.addService()
com.android.server.am.ActivityManagerService # setSystemProcess()

ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);

注意平時常用的 AMS 獲取滥嘴,要知道是在這里進(jìn)行 添加 的木蹬。

Step 2.2.2 獲取系統(tǒng)應(yīng)用信息 getApplicationInfo
com.android.server.am.ActivityManagerService 

public void setSystemProcess() {
    ApplicationInfo info = mContext.getPackageManager() // Step 2.2.2.1
               .getApplicationInfo( "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY); // Step 2.2.2.2
}
Step 2.2.2.1 mContext.getPackageManager()

Context 的實現(xiàn)類是 ContextImpl

android.app.ContextImpl

public PackageManager getPackageManager() {
   if (mPackageManager != null) {
       return mPackageManager;
   }
    // 依賴于ActivityThread,此時為系統(tǒng)進(jìn)程的主線程若皱,調(diào)用ActivityThread的getPackageManager()函數(shù)
   IPackageManager pm = ActivityThread.getPackageManager();
   if (pm != null) {
       // Doesn't matter if we make more than one instance.
       // 利用PMS的代理對象镊叁,構(gòu)建ApplicationPackageManager對象(繼承PackageManager)
       // Note:PackageManager不繼承IPackageManager。IPackageManager繼承IInterface走触,屬于Binder接口
       return (mPackageManager = new ApplicationPackageManager(this, pm));
   }
   return null;
}

跟進(jìn)一下ActivityThread的getPackageManager:

android.app.ActivityThread

public static IPackageManager getPackageManager() {
   if (sPackageManager != null) {
       return sPackageManager;
   }
   // 依賴于Binder通信晦譬,并通過ServiceManager獲取到PMS對應(yīng)的BpBinder
   IBinder b = ServiceManager.getService("package");
   //得到PMS對應(yīng)的Binder服務(wù)代理
   sPackageManager = IPackageManager.Stub.asInterface(b);
   return sPackageManager;
}

從上面我們可以看到,獲取 PMS 用到了Binder通信互广。方式和獲取 AMS 一樣敛腌。

實際上,PMSSystemServer 創(chuàng)建惫皱,與 AMS 運行在同一一個進(jìn)程像樊,且初始化比 AMS 早,但是比構(gòu)建 Android 運行環(huán)境晚逸吵,所以之前構(gòu)建的系統(tǒng) LoadedApk 是一個空殼凶硅,實際內(nèi)容需要從 PMS 中獲取。

實際上扫皱,AMS 完全可以不經(jīng)過 ContextActivityThread捷绑、Binder 來獲取 PMS韩脑,直接在 SystemServer 中取 mPackageManagerService 屬性即可

但是源碼通過 ActivityThread.getPackageManager 等之前和之后一系列操作獲取 PMS 的原因是:
SystemServer 進(jìn)程中的服務(wù),也通過之前構(gòu)建的 Android 運行環(huán)境來交互粹污,保證了組件之間交互接口的統(tǒng)一段多,為未來的系統(tǒng)保留了可擴展性。

step 2.2.2.2 通過 PMS 獲取 getApplicationInfo()

得到 PMS 服務(wù)的代理對象后壮吩,AMS 調(diào)用 PMSgetApplicationInfo 接口进苍,獲取 package 名為 "android" 的 ApplicationInfo加缘。

AMSsetSystemProcess 被調(diào)用前,PMS 已經(jīng)啟動了觉啊。
PMS 的構(gòu)造函數(shù)中拣宏,它將解析手機中所有的AndroidManifest.xml,然后形成各種數(shù)據(jù)結(jié)構(gòu)以維護(hù)應(yīng)用的信息杠人。

getApplicationInfo 就是通過 package 名勋乾,從對應(yīng)的數(shù)據(jù)結(jié)構(gòu)中取出對應(yīng)的應(yīng)用信息。這部分內(nèi)容主要就是查詢數(shù)據(jù)結(jié)構(gòu)的內(nèi)容嗡善,不作深入分析辑莫。

2.2.3 installSystemApplicationInfo

在上一步得到 framework-res.apkApplicationInfo 后,需要將該 ApplicationInfo 保存到 SystemServer 對應(yīng)的ActivityThread 中罩引。

com.android.server.am.ActivityMagerService

mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

AMS 中的 mSystemThread 就是 SystemServer 中創(chuàng)建出的 ActivityThread各吨。

跟進(jìn)一下 ActivityThreadinstallSystemApplicationInfo 函數(shù)

com.android.app.ActivityThread

public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
   synchronized (this) {
        //調(diào)用SystemServer中創(chuàng)建出的ContextImpl的installSystemApplicationInfo函數(shù)        
       getSystemContext().installSystemApplicationInfo(info, classLoader);
       getSystemUiContext().installSystemApplicationInfo(info, classLoader);

       // give ourselves a default profiler
       // 創(chuàng)建一個Profiler對象,用于性能統(tǒng)計
       mProfiler = new Profiler();
   }
}

繼續(xù)跟進(jìn) ContextImplinstallSystemApplicationInfo 函數(shù)

com.android.app.ContextImpl

void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
    // mPackageInfo 的類型為 LoadedApk
   mPackageInfo.installSystemApplicationInfo(info, classLoader);
}

繼續(xù)跟進(jìn) LoadedApkinstallSystemApplicationInfo 函數(shù)

com.android.app.LoadedApk

/**
* Sets application info about the system package.
*/
void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
    // 這個接口僅供系統(tǒng)進(jìn)程調(diào)用袁铐,故這里斷言了一下
   assert info.packageName.equals("android");
   mApplicationInfo = info;
   mClassLoader = classLoader;
}

至此绅你,我們知道了 installSystemApplicationInfo 的真相就是:
將包名為 "android" 對應(yīng)的 ApplicationInfo (framework-res.apk),加入到之前創(chuàng)建的系統(tǒng) LoadedApk 中(SystemServer#run#createSystemContext)

原因是:在此之前創(chuàng)建 SystemContext 時昭躺,PMS 還沒有執(zhí)行對手機中的文件進(jìn)行解析的操作忌锯,因此初始化的 LoadApk 并沒有持有有效的 ApplicationInfo(僅實例化了一個空 ApplicationInfo 對象,設(shè)置了 packageName 屬性為"android"领炫,其他并沒有設(shè)置)偶垮。


在此基礎(chǔ)上,AMS 下一步的工作就呼之欲出了

因為 AMS 是專門用于進(jìn)程管理和調(diào)度的帝洪,但是framework.apk 運行在 SystemServer 進(jìn)程中似舵,所以SystemServer 進(jìn)程也應(yīng)該在 AMS 有對應(yīng)的管理結(jié)構(gòu)。(SystemServer 創(chuàng)建了 AMS葱峡,但是 AMS 還想管理SystemServer ^ - ^ )

于是砚哗,AMS 的下一步工作就是將 SystemServer 的運行環(huán)境和一個進(jìn)程管理結(jié)構(gòu)對應(yīng)起來,并進(jìn)行統(tǒng)一的管理砰奕。

2.2.4 AMS進(jìn)程的管理

ProcessRecord 該類定義一個進(jìn)程的詳細(xì)信息
mLruProcess列表保存進(jìn)程
進(jìn)程對應(yīng)的oom_adj值將決定進(jìn)程是否被kill掉

AMS#setSystemProcess函數(shù)中蛛芥,進(jìn)程管理相關(guān)的代碼如下:

com.android.server.am.ActivityManagerServer

public void setSystemProcess() {
    ...
    synchronized (this) {
        // 創(chuàng)建進(jìn)程管理對應(yīng)的結(jié)構(gòu) ProcessRecord
        ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
        
        // 由于此時創(chuàng)建的是SystemServer進(jìn)程對應(yīng)的ProcessRecord,因此設(shè)置了一些特殊值
        app.persistent = true;
        app.pid = MY_PID;
        app.maxAdj = ProcessList.SYSTEM_ADJ;
        // 將SystemServer對應(yīng)的ApplicationThread保存到ProcessRecord中
        app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
        synchronized (mPidsSelfLocked) {
            // 按pid將ProcessRecord保存到mPidsSelfLocked中
            mPidsSelfLocked.put(app.pid, app);
        }
        // TODO 調(diào)整 mLruProcess 列表的位置军援,最近活動過的進(jìn)程總是位于前列仅淑,同時擁有Activity的進(jìn)程總是前于只有Service的進(jìn)程
        updateLruProcessLocked(app, false, null);
        // TODO 更新進(jìn)程對應(yīng)的oom_adj值,oom_adj將決定進(jìn)程是否被kill掉
        updateOomAdjLocked();
    }
    ...
}

這里我們僅分析一下創(chuàng)建進(jìn)程管理結(jié)構(gòu)的函數(shù)newProcessRecordLocked胸哥。
updateLruProcessLocked和updateOomAdjLocked函數(shù)比較復(fù)雜涯竟,等對AMS有更多的了解后,再做分析。

com.android.server.am.ActivityManagerServer

final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess, boolean isolated, int isolatedUid) {
    //進(jìn)程的名稱
    String proc = customProcess != null ? customProcess : info.processName;

    //將用于創(chuàng)建該進(jìn)程的電源統(tǒng)計項
    BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();

    final int userId = UserHandle.getUserId(info.uid);
    //isolated此時為false
    if (isolated) {
        ...
    }
    //創(chuàng)建出對應(yīng)的存儲結(jié)構(gòu)
    final ProcessRecord r = new ProcessRecord(stats, info, proc, uid);

    //判斷進(jìn)程是否常駐
    if (!mBooted && !mBooting
            && userId == UserHandle.USER_SYSTEM
            && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
        r.persistent = true;
    }

    //按進(jìn)程名將ProcessRecord存入到AMS的變量mProcessNames中
    //該變量的類型為ProcessMap<ProcessRecord> 
    //結(jié)合前面的代碼庐船,我們知道AMS有兩種方式可以取到ProcessRecord银酬,一是根據(jù)進(jìn)程名,二是根據(jù)進(jìn)程名稱
    addProcessNameLocked(r);
    return r;
}

跟進(jìn)一下 ProcessRecord 的構(gòu)造函數(shù)

com.android.server.am.ProcessRecord

ProcessRecord(BatteryStatsImpl _batteryStats, ApplicationInfo _info,
        String _processName, int _uid) {
    mBatteryStats = _batteryStats; //用于電量統(tǒng)計
    info = _info;  //保存ApplicationInfo
    ...........
    processName = _processName;  //保存進(jìn)程名

    //一個進(jìn)程能運行多個Package筐钟,pkgList用于保存package名
    pkgList.put(_info.packageName, new ProcessStats.ProcessStateHolder(_info.versionCode));

    //以下變量和進(jìn)程調(diào)度優(yōu)先級有關(guān)
    maxAdj = ProcessList.UNKNOWN_ADJ;
    curRawAdj = setRawAdj = ProcessList.INVALID_ADJ;
    curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;

    //決定進(jìn)程是否常駐內(nèi)存(即使被殺掉揩瞪,系統(tǒng)也會重啟它)
    persistent = false;

    removed = false;
    lastStateTime = lastPssTime = nextPssTime = SystemClock.uptimeMillis();
}

總結(jié)
AMS#setSystemProcess 函數(shù)主要完成任務(wù):

  1. ServiceManager 添加注冊了一些服務(wù),包括 AMS 自身盗棵。
  2. 通過 PMS 獲取 "android" 系統(tǒng)服務(wù)的 ApplicationInfo 信息壮韭,并安裝到系統(tǒng)服務(wù)對應(yīng)的 LoadedApk 中。
  3. 構(gòu)建 SystemServer 進(jìn)程對應(yīng)的 ProcessRecord纹因,將SystemServer 納入到 AMS 的管理中喷屋。

Step 3 SystemServer#startOtherServices

接下來AMS啟動相關(guān)的操作,在SystemServer的startOtherServices函數(shù)中

com.android.server.SystemServer

private void startOtherServices() {
    ...
    // Step 3.1
    mActivityManagerService.installSystemProviders();
    ...
    // Step 3.2
    mActivityManagerService.systemReady(new Runnable() {
        ...
    });
}

繼續(xù)跟進(jìn)AMS的installSystemProviders函數(shù)

Step 3.1 AMS # installSystemProviders

com.android.server.am.ActivityManagerServer

public final void installSystemProviders() {
    List<ProviderInfo> providers;
    synchronized (this) {
        // AMS 根據(jù)進(jìn)程名取出對應(yīng)的ProcessRecord
      ProcessRecord app = mProcessNames.get("system", SYSTEM_UID);
      // 得到該ProcessRecord對應(yīng)的ProviderInfo
      // Step 3.1.1
      providers = generateApplicationProvidersLocked(app);
      // 僅處理系統(tǒng)級的Provider瞭恰,取出非系統(tǒng)
      if (providers != null) {
          for (int i=providers.size()-1; i>=0; i--) {
              ProviderInfo pi = (ProviderInfo)providers.get(i);
              if ((pi.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
                  Slog.w(TAG, "Not installing system proc provider " + pi.name
                          + ": not system .apk");
                  providers.remove(i);
              }
          }
      }
    }
    if (providers != null) {
      // 安裝Provider
       // Step 3.1.2
      mSystemThread.installSystemProviders(providers);
    }
    
    mConstants.start(mContext.getContentResolver());
    // 監(jiān)控Settings數(shù)據(jù)庫中的secure屯曹、System和Global表的變化
    mCoreSettingsObserver = new CoreSettingsObserver(this);
    // 創(chuàng)建監(jiān)控數(shù)據(jù)庫中字體大小的變化
    mFontScaleSettingObserver = new FontScaleSettingObserver();
    
    // Now that the settings provider is published we can consider sending
    // in a rescue party.
    RescueParty.onSettingsProviderPublished(mContext);
    
    //mUsageStatsService.monitorPackages();
}

從上面的代碼可以看出,AMS # installSystemProviders主要是加載運行在 SystemServer 進(jìn)程中的 ContentProvider惊畏,即SettingProvider.apk(frameworks/base/packages/SettingsProvider)

framework-res.apk 源碼的位置:frameworks/base/core/res
SettingProvider.apk 源碼的位置:frameworks/base/packages/SettingsProvider

framework-res.apk 源碼
SettingProvider.apk

上面有兩個比較重要的函數(shù):

  1. generateApplicationProvidersLocked 返回一個進(jìn)程對應(yīng)的 ProviderInfo 列表恶耽。
  2. ActivityThread 可以看做進(jìn)程Android運行環(huán)境,因此它的 installSystemProviders 表示為對應(yīng)進(jìn)程安裝ContentProvider颜启。
  3. 當(dāng) SettingProvider 被加載到 SystemServer 進(jìn)程中運行后偷俭,AMS 就注冊了兩個 ContentObserver 監(jiān)控SettingsProvider 中的字段變化

AMS 監(jiān)控的字段影響范圍比較廣,例如字體發(fā)生變化時缰盏,很多應(yīng)用的顯示界面需要作出調(diào)整涌萤,這也許就是讓 AMS來 負(fù)責(zé)監(jiān)控這些字段的原因

接下來,我們看上面比較重要的兩個函數(shù)

Step 3.1.1
com.android.server.am.ActivityServiceManager

private final List<ProviderInfo> generateApplicationProvidersLocked(ProcessRecord app) {
   List<ProviderInfo> providers = null;
   try {
        // 利用 PMS 根據(jù)進(jìn)程名及權(quán)限口猜,從數(shù)據(jù)結(jié)構(gòu)中得到進(jìn)程對應(yīng)的ProviderInfo
       providers = AppGlobals.getPackageManager()
               .queryContentProviders(app.processName, app.uid,
                       STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS
                               | MATCH_DEBUG_TRIAGED_MISSING, /*metadastaKey=*/ null)
               .getList();
   } catch (RemoteException ex) {
   }
   if (DEBUG_MU) Slog.v(TAG_MU,
           "generateApplicationProvidersLocked, app.info.uid = " + app.uid);
   int userId = app.userId;
   if (providers != null) {
   
        // 通常而言负溪,我們逐漸向容器加入數(shù)據(jù)時,容器只有在數(shù)據(jù)超出當(dāng)前存儲空間時
        // 才會運行內(nèi)存的重新分配(一般乘2)和數(shù)據(jù)的拷貝
        // 因此若待加入數(shù)據(jù)總量很大济炎,在逐步向容器加入數(shù)據(jù)的過程川抡,容器將會有多次重新分配和拷貝的過程
        // 或許整體的開銷并不是很驚人,但事先將內(nèi)存一次分配到位须尚,體現(xiàn)了對極致的追求
        // 建議學(xué)習(xí)
       int N = providers.size();
       app.pubProviders.ensureCapacity(N + app.pubProviders.size());
       
       for (int i=0; i<N; i++) {
           // TODO: keep logic in sync with installEncryptionUnawareProviders
           ProviderInfo cpi =
               (ProviderInfo)providers.get(i);
               // 判斷是否為單例的
           boolean singleton = isSingleton(cpi.processName, cpi.applicationInfo,
                   cpi.name, cpi.flags);
                   // 針對多用戶的處理
                   // 若一個Provider是單例的崖堤,但當(dāng)前進(jìn)程不屬于默認(rèn)用戶,那么這個Provider將不被處理
                   // 簡單來說恨闪,就是兩個用戶都啟動一個進(jìn)程時(有了兩個進(jìn)程)
                   // 定義于進(jìn)程Package中單例的Provider僅運行在默認(rèn)用戶啟動的進(jìn)程中
           if (singleton && UserHandle.getUserId(app.uid) != UserHandle.USER_SYSTEM) {
               // This is a singleton provider, but a user besides the
               // default user is asking to initialize a process it runs
               // in...  well, no, it doesn't actually run in this process,
               // it runs in the process of the default user.  Get rid of it.
               providers.remove(i);
               N--;
               i--;
               continue;
           }

            // 包名和類名組成ComponentName
           ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
           // 創(chuàng)建ContentProvider對應(yīng)的ContentProviderRecord
           // 加入到AMS的MProviderMap中
           ContentProviderRecord cpr = mProviderMap.getProviderByClass(comp, userId);
           if (cpr == null) {
               cpr = new ContentProviderRecord(this, cpi, app.info, comp, singleton);
               mProviderMap.putProviderByClass(comp, cpr);
           }
           // 將ContentProviderRecord保存在ProcessRecord中
           app.pubProviders.put(cpi.name, cpr);
           if (!cpi.multiprocess || !"android".equals(cpi.packageName)) {
               // Don't add this if it is a platform component that is marked
               // to run in multiple processes, because this is actually
               // part of the framework so doesn't make sense to track as a
               // separate apk in the process.
               // 當(dāng)ContentProvider僅屬于當(dāng)前進(jìn)程時倘感,還需要統(tǒng)計該Provider的運行信息
               app.addPackage(cpi.applicationInfo.packageName, cpi.applicationInfo.versionCode,
                       mProcessStats);
           }
           //通知PMS記錄該Provider對應(yīng)包被使用的時間
           notifyPackageUse(cpi.applicationInfo.packageName,
                            PackageManager.NOTIFY_PACKAGE_USE_CONTENT_PROVIDER);
       }
   }
   return providers;
}

generateApplicationProvidersLocked 函數(shù)實現(xiàn)的主要功能:

  1. PMS 中得到應(yīng)用對應(yīng)的 ContentProvider
  2. 利用應(yīng)用信息和對應(yīng)的 ContentProvider 組成ContentProviderRecord咙咽。
  3. ContentProviderRecord 按包名保存到 AMSmProviderMap 中。原因:AMS 需要管理淤年。ContentProvider钧敞,當(dāng)一個進(jìn)程退出時蜡豹,AMS 需要將其中運行的 ContentProvider 信息從系統(tǒng)中移除。
  4. ContentProviderRecord 按包名保存到 ProcessRecord 中溉苛。原因:最終需要落實到一個進(jìn)程中镜廉。
Step 3.1.2 ActivityThread # installSystemProviders
com.android.app.ActivityThread

public final void installSystemProviders(List<ProviderInfo> providers) {
    if (providers != null) {
          //對于SystemServer進(jìn)程而言,mInitialApplication是framework-res.apk對應(yīng)的Application
      installContentProviders(mInitialApplication, providers);
    }
}

####### Step 3.1.2.1 ActivityThread # installContentProviders

com.android.app.ActivityThread

private void installContentProviders(
       Context context, List<ProviderInfo> providers) {
   final ArrayList<ContentProviderHolder> results = new ArrayList<>();

   for (ProviderInfo cpi : providers) {
       ...
       // Step 3.1.2.1.1 初始化并保存ContentProvider
       ContentProviderHolder cph = installProvider(context, null, cpi,
               false /*noisy*/, true /*noReleaseNeeded*/, true /*stable*/);
       if (cph != null) {
           cph.noReleaseNeeded = true;
           results.add(cph);
       }
   }

   try {
        // Step 3.1.2.1.2 向AMS注冊ContentProvider
       ActivityManager.getService().publishContentProviders(
           getApplicationThread(), results);
   } catch (RemoteException ex) {
       throw ex.rethrowFromSystemServer();
   }
}

installContentProviders 是安裝 ContentProvider 的通用程序愚战,主要包括兩方面的工作:

  1. 調(diào)用 installProvider 得到 ContentProviderHolder 對象娇唯,其間完成了對應(yīng) ContentProvider 的初始化等工作。
  2. AMS 發(fā)布 ContentProviderHolder寂玲。

####### Step 3.1.2.1.1 ActivityThread # installProvider

com.android.app.ActivityThread
private ContentProviderHolder installProvider(Context context,
        ContentProviderHolder holder, ProviderInfo info,
        boolean noisy, boolean noReleaseNeeded, boolean stable) {
    ContentProvider localProvider = null;
    IContentProvider provider;
    if (holder == null || holder.provider == null) {
        // 此時holder==null塔插,進(jìn)入這個分支
        ...
        Context c = null;
        ApplicationInfo ai = info.applicationInfo;
        
        // 下面判斷的作用是:為待安裝的ContentProvider找到對應(yīng)的Application
        // 在 AndroidManifest中,ContentProvider是Application的子標(biāo)簽拓哟,因此ContentPro與Application有一種對應(yīng)關(guān)系
        // 本次流程中想许,傳入的context是mInitApplication,代表的是framework-res.apk
        // 而 ai 是從ProviderInfo中獲取的断序,代表的是SettingProvider流纹,SettingProvider.apk所對應(yīng)的Application還未創(chuàng)建
        // 所有進(jìn)入最后的else判斷中
        if (context.getPackageName().equals(ai.packageName)) {
            c = context;
        } else if (mInitialApplication != null &&
                mInitialApplication.getPackageName().equals(ai.packageName)) {
            c = mInitialApplication;
        } else {
            try {
                // 以下將重新創(chuàng)建一個Context,指向SettingProvider.apk
                // ai.packageName = "com.android.provider.settings"

                // createPackageContext方法中利用package對應(yīng)的LoadedApk信息违诗,創(chuàng)建新的ContextImpl
                // 其內(nèi)部通過 mMainThread.getPackageInfo 取出LoadedApk漱凝,在這個過程中,如果已經(jīng)加載過就直接從存儲變量中取诸迟,否則同PMS重新構(gòu)建
                c = context.createPackageContext(ai.packageName,
                        Context.CONTEXT_INCLUDE_CODE);
            } catch (PackageManager.NameNotFoundException e) {
                // Ignore
            }
        }
        
        ...

        try {
            // 上面必須找到ContentProvider對應(yīng)的Context的原因:
            // 1. ContentProvider和Application有對應(yīng)關(guān)系茸炒,而Application繼承Context
            // 2. 只有正確的Context才能加載對應(yīng)APK的Java字節(jié)碼,從而通過反射創(chuàng)建出ContentProvider實例

            // 得到對應(yīng)的ClassLoader
            final java.lang.ClassLoader cl = c.getClassLoader();
            // 反射創(chuàng)建實例
            localProvider = (ContentProvider)cl.
                loadClass(info.name).newInstance();

            // ContentProvider的mTransport對象
            // 變現(xiàn)類型為IContentProvider亮蒋,實際為ContentProviderNative扣典,即ContentProvider的Binder通信服務(wù)端BbBinder
            // Tansport 繼承 ContentProviderNative
            provider = localProvider.getIContentProvider();

            ...

            // 初始化ContentProvider,內(nèi)部會調(diào)用ContentProvider的onCreate函數(shù)
            localProvider.attachInfo(c, info);

        } catch (java.lang.Exception e) {
            ...
            return null;
        }
    } else {
        provider = holder.provider;
        ...
    }

    ContentProviderHolder retHolder;

    synchronized (mProviderMap) {
        ...
        // 調(diào)用ContentProviderNative的asBinder慎玖,得到服務(wù)端的Binder對象
        IBinder jBinder = provider.asBinder();
        if (localProvider != null) {
            ComponentName cname = new ComponentName(info.packageName, info.name);
            ProviderClientRecord pr = mLocalProvidersByName.get(cname);
            if (pr != null) {
                ...
                provider = pr.mProvider;
            } else {
                // 根據(jù)ProviderInfo創(chuàng)建ContenProviderHolder
                holder = new ContentProviderHolder(info);
                // 使持有provider
                holder.provider = provider;
                holder.noReleaseNeeded = true;

                // 構(gòu)造ProviderClientRecord贮尖,并按authority將其保存在mProviderMap中
                pr = installProviderAuthoritiesLocked(provider, localProvider, holder);
                // 將 pr 按 jBinder 保存在 mLocalProviders 中
                mLocalProviders.put(jBinder, pr);
                // 將 pr 按 cname 保存在 mLocalProvidersByName 中
                mLocalProvidersByName.put(cname, pr);
            }
            retHolder = pr.mHolder;
        } else {
            ...
        }
    }
    return retHolder;
}

installProvider 的代碼較長,但實際思想很簡單趁怔,就是環(huán)環(huán)相扣的三步:

  1. 創(chuàng)建出 ContentProvider 對應(yīng)的 ContextImpl(代表對應(yīng)的運行環(huán)境)
  2. 利用 ContextImpl 得到對應(yīng)的 ClassLoader湿硝,完成 ContentProvider 的初始化和啟動
  3. 得到與 ContentProvider 通信的 BBinder,然后按名稱和 BBinder润努,將 ContentProvider 保存到對應(yīng)的存儲結(jié)構(gòu)中“
ActivityThread 與 ContenProvider 的關(guān)系圖

ActivityThread 與 ContenProvider 的關(guān)系大概如上圖所示关斜。

ContentProvider 本身只是一個容器,其內(nèi)部持有的 Transport 類才是能提供跨進(jìn)程調(diào)用的支持铺浇。

Transport 類繼承自 ContentProviderNative 類痢畜,作為ContentProviderBinder 通信服務(wù)端 BBinder
ContentProviderNative 中定義的 ContentProviderProxy 類將作為 Binder 通信的服務(wù)端代理,為客戶端提供交互

在上面的代碼中丁稀,ActivityThreadmLocalProviders 保存運行在本地的 ContentProvider吼拥,使用的鍵值的key為 ContentProvider的Binder 通信服務(wù)端。

####### Step 3.1.2.1.1 publishContentProviders
ContentProvider 初始化完成后线衫,我們需要向 AMS 注冊它凿可。

com.android.app.ActivityThread

private void installContentProviders(
    ...
    ActivityManager.getService().publishContentProviders(
                getApplicationThread(), results);
    ...
}

這段代碼是注冊ContentProvider的通用代碼.

因此即使我們現(xiàn)在的流程運行在AMS中,此處仍然將通過Binder通信進(jìn)行調(diào)用授账。

com.android.server.app.ActivityManagerService

public final void publishContentProviders(IApplicationThread caller,
        List<ContentProviderHolder> providers) {
    if (providers == null) {
        return;
    }

    enforceNotIsolatedCaller("publishContentProviders");
    synchronized (this) {
        //找到調(diào)用者對應(yīng)的ProcessRecord對象
        final ProcessRecord r = getRecordForAppLocked(caller);
        ...

        final long origId = Binder.clearCallingIdentity();

        final int N = providers.size();
        for (int i = 0; i < N; i++) {
            // ProcessRecord的pubProviders中保存了ContentProviderRecord信息
            // 這是根據(jù)PMS解析出的Package信息生成的
            // 此處主要發(fā)布的ContentProvider枯跑,必須是該Packager已經(jīng)聲明的
            ContentProviderHolder src = providers.get(i);
            ContentProviderRecord dst = r.pubProviders.get(src.info.name);
            ...
            if (dst != null) {
                ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
                // 按名稱保存到MProviderMap
                mProviderMap.putProviderByClass(comp, dst);
                
                String names[] = dst.info.authority.split(";");
                for (int j = 0; j <  names.length; j++) {
                    // 按 authority保存到mProviderMap
                    mProviderMap.putProviderByName(names[j], dst);
                }
                // mLaunchingProviders 保存處于啟動狀態(tài)的Provider
                int launchingCount = mLaunchingProviders.size();
                int j;
                boolean wasInLaunchingProviders = false;
                for (j = 0; j < launchingCount; j++) {
                    if (mLaunchingProviders.get(j) == dst) {
                        // 啟動完成后,從列表中移除
                        mLaunchingProviders.remove(j);
                        wasInLaunchingProviders = true;
                        j--;
                        launchingCount--;
                    }
                }
                if (wasInLaunchingProviders) {
                    // 取消啟動超時的消息
                    mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, r);
                }
                synchronized (dst) {
                    dst.provider = src.provider;
                    dst.proc = r;
                    // 通知
                    dst.notifyAll();
                }
                // 沒發(fā)布一個ContentProvider白热,均調(diào)整對應(yīng)進(jìn)程的oom_adj
                updateOomAdjLocked(r, true);
                // 判斷敛助,并在需要的時候更新ContentProvider相關(guān)的統(tǒng)計信息
                maybeUpdateProviderUsageStatsLocked(r, src.info.packageName,
                        src.info.authority);
            }
        }

        Binder.restoreCallingIdentity(origId);
    }
}

publishContentProvider 函數(shù)結(jié)束后,一個 ContentProvider 就算正式在系統(tǒng)中注冊了棘捣。
AMS 的啟動過程中辜腺,此處注冊的是 SettingProvider
此后,Setting數(shù)據(jù)庫相關(guān)的操作均由它來管理乍恐。

注意到上面的 ContentProvider 注冊到 AMS 后评疗,進(jìn)行了notifyAll 的操作。
舉例來說:進(jìn)程需要查詢一個數(shù)據(jù)庫茵烈,需要通過進(jìn)程B中的某個 ContentProvider 來實施百匆。如果 B 還未啟動,那么 AMS 就需要先啟動 B呜投。在這段時間內(nèi)加匈,A需要等待B注冊啟動對應(yīng)的 ContentProvider。B一旦完成 ContentProvider 的注冊仑荐,就需要告知A退出等待繼續(xù)后續(xù)的查詢工作雕拼。

Step SystemServer # systemReady

接下來,我們看看AMS啟動的最后一部分:systemReady

com.android.server.SystemServer

private void startOtherServices() {
    ...
    // Step 3.1
    mActivityManagerService.installSystemProviders();
   ...
   mPackageManagerService.systemReady();
    ...
    // Step 3.2
    mActivityManagerService.systemReady(new Runnable() {
        ...
    });
}

在SystemServer中的startOtherServices的最后調(diào)用了AMS的systemReady函數(shù)
可以看到第一個參數(shù)為Runnable粘招。

由于此處代碼量很大啥寇,所以先分段查看 AMSsystemReady 的處理流程,然后再查看 Runnable 中的處理流程洒扎。

Step 3.2.1 階段一
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    traceLog.traceBegin("PhaseActivityManagerReady");
    synchronized(this) {
        // 第一次mSystemReady=false
        if (mSystemReady) {
            // If we're done calling all the receivers, run the next "boot phase" passed in
            // by the SystemServer
            if (goingCallback != null) {
                goingCallback.run();
            }
            return;
        }

        // 這一部分主要是調(diào)用一些關(guān)鍵服務(wù)systemReady相關(guān)的函數(shù)

        mLocalDeviceIdleController
                = LocalServices.getService(DeviceIdleController.LocalService.class);
        mAssistUtils = new AssistUtils(mContext);
        mVrController.onSystemReady();
        // Make sure we have the current profile info, since it is needed for security checks.
        mUserController.onSystemReady();
        mRecentTasks.onSystemReadyLocked();
        mAppOpsService.systemReady();

        // 系統(tǒng)準(zhǔn)備完畢
        mSystemReady = true;
    }

    try {
        sTheRealBuildSerial = IDeviceIdentifiersPolicyService.Stub.asInterface(
                ServiceManager.getService(Context.DEVICE_IDENTIFIERS_SERVICE))
                .getSerial();
    } catch (RemoteException e) {}

    ArrayList<ProcessRecord> procsToKill = null;
    synchronized(mPidsSelfLocked) {
        for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
            // mPidsSelfLocked中保存當(dāng)前正在運行的所有進(jìn)程的信息
            ProcessRecord proc = mPidsSelfLocked.valueAt(i);
            // isAllowedWhileBooting中判斷FLAG_PERSISTENT標(biāo)志
            // 在AMS啟動完成前辑甜,如果沒有 FLAG_PERSISTENT 標(biāo)志的進(jìn)程已經(jīng)啟動了,將其加入到procsToKill列表中
            if (!isAllowedWhileBooting(proc.info)){
                if (procsToKill == null) {
                    procsToKill = new ArrayList<ProcessRecord>();
                }
                procsToKill.add(proc);
            }
        }
    }

    synchronized(this) {
        if (procsToKill != null) {
            for (int i=procsToKill.size()-1; i>=0; i--) {
                ProcessRecord proc = procsToKill.get(i);
                Slog.i(TAG, "Removing system update proc: " + proc);
                // 關(guān)閉 procsToKill中的進(jìn)程
                removeProcessLocked(proc, true, false, "system update done");
            }
        }

        // Now that we have cleaned up any update processes, we
        // are ready to start launching real processes and know that
        // we won't trample on them any more.
        
        // 進(jìn)程準(zhǔn)備完畢
        mProcessesReady = true;
    }

    ...

    // 根據(jù)數(shù)據(jù)庫和資源文件袍冷,獲取一些配置參數(shù)
    retrieveSettings();
    final int currentUserId;
    synchronized (this) {
        // 得到當(dāng)前的用戶Id
        currentUserId = mUserController.getCurrentUserIdLocked();
        // 讀取 urigrant.xml磷醋,為其中定義的 ContentProvider 配置對指定Uri數(shù)據(jù)的訪問/修改權(quán)限
        // 原生的代碼中,似乎沒有 urigrants.xmls
        // 實際使用的 grant-uri-permission 是分布式定義的
        readGrantedUriPermissionsLocked();
    }


    if (goingCallback != null) goingCallback.run();
    traceLog.traceBegin("ActivityManagerStartApps");

    ...

}

這部分的主要工作:
這一部分的工作主要是

  1. 調(diào)用一些關(guān)鍵服務(wù)的初始化函數(shù)
  2. 殺死那些沒有 FLAG_PERSISTENT 卻在AMS啟動完成前已經(jīng)存在的進(jìn)程
  3. 獲取一些配置參數(shù)胡诗。

只有Java進(jìn)程才會向AMS注冊邓线,而一般的Native進(jìn)程不會向AMS注冊淌友,因此這里殺死的進(jìn)程時Java進(jìn)程

Step 3.2.2 階段二
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    
    ...

    // 調(diào)用參數(shù)傳入的 Runnable對象,SystemServer中有具體的定義
    // Step 3.2.2.1
    if (goingCallback != null) goingCallback.run();
    traceLog.traceBegin("ActivityManagerStartApps");
    
    ...
    
    // 內(nèi)部循環(huán)遍歷所有的系統(tǒng)服務(wù)的onStartUser接口
    mSystemServiceManager.startUser(currentUserId);

    synchronized (this) {
        // Only start up encryption-aware persistent apps; once user is
        // unlocked we'll come back around and start unaware apps
        // 啟動persistent為1的Application所在的進(jìn)程
        // Step 3.2.2.2
        startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);

        // Start up initial activity.
        mBooting = true;
        // Enable home activity for system user, so that the system can always boot. We don't
        // do this when the system user is not setup since the setup wizard should be the one
        // to handle home activity in this case.
        // 當(dāng)isSplitSystemUser返回true時褂痰,意味著system user和primary user是分離的
        // 這里應(yīng)該是讓system user也有啟動 home activity 的權(quán)限吧
        if (UserManager.isSplitSystemUser() &&
                Settings.Secure.getInt(mContext.getContentResolver(),
                     Settings.Secure.USER_SETUP_COMPLETE, 0) != 0) {
            ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
            try {
                AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
                        UserHandle.USER_SYSTEM);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }

        // Step 3.2.2.3 啟動 Home
        startHomeActivityLocked(currentUserId, "systemReady");

        try {
            // 發(fā)送消息亩进,觸發(fā)處理Uid錯誤的Application
            if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
                ...
                mUiHandler.obtainMessage(SHOW_UID_ERROR_UI_MSG).sendToTarget();
            }
        } catch (RemoteException e) {
        }

        // 發(fā)送一些廣播信息
        ...

        // 這里暫不深入症虑,屬于Activity的啟動過程缩歪,onResume
        mStackSupervisor.resumeFocusedStackTopActivityLocked();

        ... 
    }
}

這部分代碼的主要工作:

  1. 通知所有的系統(tǒng)服務(wù)執(zhí)行onStartUser()
  2. 啟動persistent=1的Application所在的進(jìn)程
  3. 啟動Home
  4. 執(zhí)行Activity的onResume
Step 3.2.2.1 SystemServer.systemReady的Runnable回調(diào)函數(shù)

回調(diào)函數(shù)定義在 ServerServer#startOtherServices 中雁社,其中會調(diào)用大量服務(wù)的 onBootPhase 函數(shù)绊含、一些對象的systemReady 函數(shù)或 systemRunning 函數(shù)泽台。

com.android.server.SystemServer

mActivityManagerService.systemReady(() -> {

    // 遍歷系統(tǒng)服務(wù)startBootPhase啟動階段代碼
    mSystemServiceManager.startBootPhase(
            SystemService.PHASE_ACTIVITY_MANAGER_READY);


    try {
        // AMS 啟動 NativeCrashListener皱蹦,監(jiān)聽“/data/system/ndebugsocket”中的信息
        // 實際上就是監(jiān)聽 debuggerd(調(diào)試工具) 傳入的信息
        mActivityManagerService.startObservingNativeCrashes();
    } catch (Throwable e) {
        reportWtf("observing native crashes", e);
    }


    // No dependency on Webview preparation in system server. But this should
    // be completed before allowring 3rd party
    final String WEBVIEW_PREPARATION = "WebViewFactoryPreparation";
    Future<?> webviewPrep = null;
    if (!mOnlyCore) {
        webviewPrep = SystemServerInitThreadPool.get().submit(() -> {
            Slog.i(TAG, WEBVIEW_PREPARATION);
            TimingsTraceLog traceLog = new TimingsTraceLog(
                    SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
            traceLog.traceBegin(WEBVIEW_PREPARATION);
            ConcurrentUtils.waitForFutureNoInterrupt(mZygotePreload, "Zygote preload");
            mZygotePreload = null;
            mWebViewUpdateService.prepareWebViewInSystemServer();
            traceLog.traceEnd();
        }, WEBVIEW_PREPARATION);
    }

    if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
        traceBeginAndSlog("StartCarServiceHelperService");
        mSystemServiceManager.startService(CarServiceHelperService.class);
        traceEnd();
    }

    // 啟動 SystemUi
    try {
        startSystemUi(context, windowManagerF);
    } catch (Throwable e) {
        reportWtf("starting System UI", e);
    }
    
    // 一系列 systemReady
    try {
        if (networkScoreF != null) networkScoreF.systemReady();
    } catch (Throwable e) {
        reportWtf("making Network Score Service ready", e);
    }
    ...
    ...

    // 啟動Watchdog
    Watchdog.getInstance().start();

    // Wait for all packages to be prepared
    mPackageManagerService.waitForAppDataPrepared();

    // confirm webview completion before starting 3rd party
    if (webviewPrep != null) {
        ConcurrentUtils.waitForFutureNoInterrupt(webviewPrep, WEBVIEW_PREPARATION);
    }

    mSystemServiceManager.startBootPhase(
            SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);


    // 一系列 systemRunning
    try {
        if (locationF != null) locationF.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying Location Service running", e);
    }
    ...
    ...

}, BOOT_TIMINGS_TRACE_LOG);
Step 3.2.2.2 AMS # startPersistentApps

啟動 persistent 標(biāo)志的進(jìn)程

com.android.server.am.ActivityManagerService

private void startPersistentApps(int matchFlags) {
    ...

    synchronized (this) {
        try {
            //從PMS中得到persistent為1的ApplicationInfo
            final List<ApplicationInfo> apps = AppGlobals.getPackageManager()
                    .getPersistentApplications(STOCK_PM_FLAGS | matchFlags).getList();
            for (ApplicationInfo app : apps) {
                //由于framework-res.apk已經(jīng)由系統(tǒng)啟動雄右,所以此處不再啟動它
                if (!"android".equals(app.packageName)) {
                    //  addAppLocked中將啟動application所在進(jìn)程
                    addAppLocked(app, false, null /* ABI override */);
                }
            }
        } catch (RemoteException ex) {
        }
    }
}

跟進(jìn)一下 addAppLocked 函數(shù)

com.android.server.am.ActivityManagerService

final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated,
        String abiOverride) {
    //以下是取出或構(gòu)造出ApplicationInfo對應(yīng)的ProcessRecord
    ProcessRecord app;
    if (!isolated) {
        app = getProcessRecordLocked(info.processName, info.uid, true);
    } else {
        app = null;
    }

    if (app == null) {
        app = newProcessRecordLocked(info, null, isolated, 0);
        updateLruProcessLocked(app, false, null);
        updateOomAdjLocked();
    }
    ...
    // This package really, really can not be stopped.
    try {
        //通過PKMS將package對應(yīng)數(shù)據(jù)結(jié)構(gòu)的StoppedState置為fasle
        AppGlobals.getPackageManager().setPackageStoppedState(
                info.packageName, false, UserHandle.getUserId(app.uid));
    } catch (RemoteException e) {
    } catch (IllegalArgumentException e) {
    }

    if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) {
        app.persistent = true;
        app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
    }

    if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
        mPersistentStartingProcesses.add(app);
        //啟動應(yīng)用所在進(jìn)程粟害,將發(fā)送消息給zygote柿祈,后者fork出進(jìn)程
        startProcessLocked(app, "added application", app.processName, abiOverride,
                null /* entryPoint */, null /* entryPointArgs */);
    }

    return app;
}

這里最終通過 startProcessLocked 函數(shù)屯远,啟動實際的應(yīng)用進(jìn)程苫昌。
Zygote 進(jìn)程中的 server socket 將接受消息颤绕,然后為應(yīng)用fork出進(jìn)程

Step 3.2.2.3 AMS # startHomeActivityLocked

啟動Home Activity

com.android.server.am.ActivityManagerService

boolean startHomeActivityLocked(int userId, String reason) {
    ...
    Intent intent = getHomeIntent();
    //根據(jù)intent中攜帶的ComponentName,利用PMS得到ActivityInfo
    ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
    if (aInfo != null) {
        intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        aInfo = new ActivityInfo(aInfo);
        aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);

        //此時home對應(yīng)進(jìn)程應(yīng)該還沒啟動祟身,app為null
        ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                aInfo.applicationInfo.uid, true);
        if (app == null || app.instrumentationClass == null) {
            intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
            //啟動home
            mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
        }
    } else {
        ...
    }
    return true;
}

這里暫時不深究Home Activity啟動的具體過程奥务。當(dāng)啟動成功后,會調(diào)用Activity#handleResumeActivity方法袜硫,最終調(diào)用到 ActivityStackSupervisor#activityIdleInternalLocked氯葬。

com.android.server.am.ActivityStackSupervisor

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
        Configuration config) {
    ...
    if (isFocusedStack(r.task.stack) || fromTimeout) {
        booting = checkFinishBootingLocked();
    }
    ...
}

跟進(jìn)一下 checkFinishBootingLocked 函數(shù)

com.android.server.am.ActivityStackSupervisor

private boolean checkFinishBootingLocked() {
    //mService為AMS,mBooting變量在AMS回調(diào)SystemServer中定義的Runnable時婉陷,置為了true
    final boolean booting = mService.mBooting;
    boolean enableScreen = false;
    mService.mBooting = false;
    if (!mService.mBooted) {
        mService.mBooted = true;
        enableScreen = true;
    }
    if (booting || enableScreen) {帚称、
        //調(diào)用AMS的接口,發(fā)送消息
        mService.postFinishBooting(booting, enableScreen);
    }
    return booting;
}

最終秽澳,AMSfinishBooting 函數(shù)將被調(diào)用:

com.android.server.am.ActivityManagerService

final void finishBooting() {
    ...
    //以下是注冊廣播接收器闯睹,用于處理需要重啟的package
    IntentFilter pkgFilter = new IntentFilter();
    pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
    pkgFilter.addDataScheme("package");
    mContext.registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
            if (pkgs != null) {
                for (String pkg : pkgs) {
                    synchronized (ActivityManagerService.this) {
                        if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
                                0, "query restart")) {
                            setResultCode(Activity.RESULT_OK);
                            return;
                        }
                    }
                }
            }
       }
    }, pkgFilter);
    ...
    // Let system services know.
    mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);

    //以下是啟動那些等待啟動的進(jìn)程
    synchronized (this) {
        // Ensure that any processes we had put on hold are now started
        // up.
        final int NP = mProcessesOnHold.size();
            if (NP > 0) {
                ArrayList<ProcessRecord> procs =
                        new ArrayList<ProcessRecord>(mProcessesOnHold);
                for (int ip=0; ip<NP; ip++) {
                    ...
                    startProcessLocked(procs.get(ip), "on-hold", null);
                }
            }
        }
    }
    ...
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        // Start looking for apps that are abusing wake locks.
        //每5min檢查一次系統(tǒng)各應(yīng)用進(jìn)程使用電量的情況,如果某個進(jìn)程使用WakeLock的時間過長
        //AMS將關(guān)閉該進(jìn)程
        Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG);
        mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY);

        // Tell anyone interested that we are done booting!
        SystemProperties.set("sys.boot_completed", "1");
        ...
        //此處從代碼來看發(fā)送的是ACTION_LOCKED_BOOT_COMPLETED廣播
        //在進(jìn)行unlock相關(guān)的工作后担神,mUserController將調(diào)用finishUserUnlocking楼吃,發(fā)送SYSTEM_USER_UNLOCK_MSG消息給AMS
        //AMS收到消息后,調(diào)用mUserController的finishUserUnlocked函數(shù)杏瞻,經(jīng)過相應(yīng)的處理后所刀,
        //在mUserController的finishUserUnlockedCompleted中,最終將會發(fā)送ACTION_BOOT_COMPLETED廣播
        mUserController.sendBootCompletedLocked(...);
        ...
    }
}

最終AMS啟動 HomeActivity 結(jié)束捞挥,并發(fā)送 ACTION_BOOT_COMPLETED 廣播時浮创,AMS的啟動過程告一段落。


總結(jié)
對于整個AMS
啟動過程來說砌函,本文涉及的內(nèi)容只是其中極小一部分斩披。
整個過程溜族,可以將AMS的啟動過程分為四步

  1. 創(chuàng)建出 SystemServer 進(jìn)程的 Android 運行環(huán)境
    這個流程,創(chuàng)建SystemServer進(jìn)程對應(yīng)的ActivityThread和ContextImpl垦沉,構(gòu)成Android運行環(huán)境
    AMS后續(xù)工作依賴SystemServer在此創(chuàng)建出的運行環(huán)境

  2. 完成AMS的初始化和啟動
    這個流程煌抒,調(diào)用了AMS的構(gòu)造函數(shù)和start函數(shù),完成AMS一些初始化工作

  3. 將SystemServer進(jìn)程納入到AMS的管理體系
    這個流程厕倍,AMS加載了SystemServer中framework-res.apk的信息寡壮,并啟動和注冊了SettingsProvider.apk。涉及了ContentProvider的安裝讹弯。

  4. AMS啟動完畢后才能進(jìn)行的工作
    這個流程况既,AMS調(diào)用 systemReady函數(shù),通知系統(tǒng)的其他服務(wù)和進(jìn)程组民,可以進(jìn)行對應(yīng)的工作棒仍。
    并且,Home Activity被啟動了臭胜,當(dāng)Home Activity被加載完成后莫其,最終會觸發(fā)ACTION_BOOT_COMPLETED廣播。

AMS 流程
  1. 創(chuàng)建 system 進(jìn)程的運行環(huán)境耸三,一個 ActivityThread 主線程乱陡,一個和系統(tǒng)進(jìn)程相關(guān)的 Context 對象
  2. 調(diào)用 AMS 的構(gòu)造方法,對必要的內(nèi)容進(jìn)行初始化
  3. 將 AMS 注冊到 ServiceManager 中吕晌,同時對 system 進(jìn)程創(chuàng)建一個 ProcessRecord 對象蛋褥,并設(shè)置 Contextapplicationframework-resapplication 對象。由于 AMSAndroid 世界的進(jìn)程管理和調(diào)度中心睛驳,盡管 system 貴為系統(tǒng)進(jìn)程烙心,也要將其并入 AMS 的管理范圍
  4. system 進(jìn)程加載 SettingProvider
  5. 調(diào)用 systemReady 方法做系統(tǒng)啟動完畢前的最后一些掃尾工作。最 HomeActivity 將呈現(xiàn)在用戶面前

參考資料

Android-0.AMS初始化和啟動簡介

Android 7.0 ActivityManagerService(1) AMS的啟動過程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乏沸,一起剝皮案震驚了整個濱河市淫茵,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蹬跃,老刑警劉巖匙瘪,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蝶缀,居然都是意外死亡丹喻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門翁都,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碍论,“玉大人,你說我怎么就攤上這事柄慰△⒂疲” “怎么了税娜?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長藏研。 經(jīng)常有香客問我敬矩,道長,這世上最難降的妖魔是什么蠢挡? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任弧岳,我火速辦了婚禮,結(jié)果婚禮上袒哥,老公的妹妹穿的比我還像新娘缩筛。我一直安慰自己,他們只是感情好堡称,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著艺演,像睡著了一般却紧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胎撤,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天晓殊,我揣著相機與錄音,去河邊找鬼伤提。 笑死巫俺,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肿男。 我是一名探鬼主播介汹,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼舶沛!你這毒婦竟也來了嘹承?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤如庭,失蹤者是張志新(化名)和其女友劉穎叹卷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坪它,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡骤竹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了往毡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒙揣。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖卖擅,靈堂內(nèi)的尸體忽然破棺而出鸣奔,到底是詐尸還是另有隱情墨技,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布挎狸,位于F島的核電站扣汪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏锨匆。R本人自食惡果不足惜崭别,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恐锣。 院中可真熱鬧茅主,春花似錦、人聲如沸土榴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玷禽。三九已至赫段,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矢赁,已是汗流浹背糯笙。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留撩银,地道東北人给涕。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像额获,于是被迫代替她去往敵國和親够庙。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容