ActivityManagerService筆記

1.AMS 概述

AMS 是系統(tǒng)的引導(dǎo)服務(wù)衡蚂,應(yīng)用進程的啟動年叮、切換和調(diào)度、四大組件的啟動和管
理都需要 AMS 的支持啸蜜。從這里可以看出 AMS 的功能會十分的繁多裹粤,當(dāng)然它并不
是一個類承擔(dān)這個重責(zé)拇泣,它有一些關(guān)聯(lián)類,這在文章后面會講到。AMS 的涉及
的知識點非常多,這篇文章主要會講解 AMS 的以下幾個知識點:

  • AMS 的啟動流程。
  • AMS 與進程啟動。
  • AMS 主要類。

2.AMS 的啟動流程

整理了一下啟動流程:
開機啟動:


2018030813463528.png

SyetemServer在啟動時做了如下工作:

  1. 啟動Binder線程池,這樣就可以與其他進程進行通信。
  2. 創(chuàng)建SystemServiceManager用于對系統(tǒng)的服務(wù)進行創(chuàng)建、啟動和生命周期管理柑司。
  3. 啟動各種系統(tǒng)服務(wù)蟆湖。
AMS啟動.png

ActivityManagerService的構(gòu)造函數(shù)

public ActivityManagerService(Context systemContext) {
    mInjector = new Injector();
    // AMS 上下文
    mContext = systemContext;

    mFactoryTest = FactoryTest.getMode();
    // ActivityThread 對象
    mSystemThread = ActivityThread.currentActivityThread(); 
    // ContextImpl 對象
    mUiContext = mSystemThread.getSystemUiContext(); 

    mPermissionReviewRequired = mContext.getResources().getBoolean(
            com.android.internal.R.bool.config_permissionReviewRequired);

    // 線程名為 ActivityManager 的前臺線程,ServiceThread 繼承于 HandlerThread
    mHandlerThread = new ServiceThread(TAG,
            THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    mHandlerThread.start();
    // 獲取 mHandlerThread 的 Handler 對象
    mHandler = new MainHandler(mHandlerThread.getLooper());
    // 創(chuàng)建名為 android.ui 的線程
    mUiHandler = mInjector.getUiHandler(this);

    mProcStartHandlerThread = new ServiceThread(TAG + ":procStart",
            THREAD_PRIORITY_FOREGROUND, false /* allowIo */);
    mProcStartHandlerThread.start();
    mProcStartHandler = new Handler(mProcStartHandlerThread.getLooper());

    mConstants = new ActivityManagerConstants(this, mHandler);

    // 根據(jù)優(yōu)先級 kill 后臺應(yīng)用進程
    if (sKillHandler == null) {
        sKillThread = new ServiceThread(TAG + ":kill",
                THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
        sKillThread.start();
        sKillHandler = new KillHandler(sKillThread.getLooper());
    }

    // 前臺廣播隊列喉磁,超時時間為 10 秒
    mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "foreground", BROADCAST_FG_TIMEOUT, false);
    // 后臺廣播隊列,超時時間為 60 秒
    mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
            "background", BROADCAST_BG_TIMEOUT, true);
    mBroadcastQueues[0] = mFgBroadcastQueue;
    mBroadcastQueues[1] = mBgBroadcastQueue;

    // 創(chuàng)建 ActiveServices
    mServices = new ActiveServices(this);
    mProviderMap = new ProviderMap(this);
    // 創(chuàng)建 AppErrors纱皆,用于處理應(yīng)用中的錯誤
    mAppErrors = new AppErrors(mUiContext, this);

    // 創(chuàng)建 /data/system 目錄
    File dataDir = Environment.getDataDirectory();
    File systemDir = new File(dataDir, "system");
    systemDir.mkdirs();

    mAppWarnings = new AppWarnings(this, mUiContext, mHandler, mUiHandler, systemDir);

    // TODO: Move creation of battery stats service outside of activity manager service.
    // 創(chuàng)建 BatteryStatsService近迁,其信息保存在 /data/system/procstats 中
    // 這里有個 TODO搏存,打算把 BatteryStatsService 的創(chuàng)建移除 AMS
    mBatteryStatsService = new BatteryStatsService(systemContext, systemDir, mHandler);
    mBatteryStatsService.getActiveStatistics().readLocked();
    mBatteryStatsService.scheduleWriteToDisk();
    mOnBattery = DEBUG_POWER ? true
            : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
    mBatteryStatsService.getActiveStatistics().setCallback(this);

    // 創(chuàng)建 ProcessStatsService矢洲,并將其信息保存在 /data/system/procstats 中
    mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));

    mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);

    // 定義 ContentProvider 訪問指定 Uri 數(shù)據(jù)的權(quán)限
    mGrantFile = new AtomicFile(new File(systemDir, "urigrants.xml"), "uri-grants");

    // 多用戶管理
    mUserController = new UserController(this);

    mVrController = new VrController(this);

    // 獲取 OpenGL 版本
    GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
        ConfigurationInfo.GL_ES_VERSION_UNDEFINED);

    if (SystemProperties.getInt("sys.use_fifo_ui", 0) != 0) {
        mUseFifoUiScheduling = true;
    }

    mTrackingAssociations = "1".equals(SystemProperties.get("debug.track-associations"));
    mTempConfig.setToDefaults();
    mTempConfig.setLocales(LocaleList.getDefault());
    mConfigurationSeq = mTempConfig.seq = 1;
    // 創(chuàng)建 ActivityStackSupervisor 璧眠,用于管理 Activity 任務(wù)棧
    mStackSupervisor = createStackSupervisor();
    mStackSupervisor.onConfigurationChanged(mTempConfig);
    mKeyguardController = mStackSupervisor.getKeyguardController();
    mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
    mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
    mTaskChangeNotificationController =
            new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
    // 創(chuàng)建 ActivityStartController 對象,用于管理 Activity 的啟動
    mActivityStartController = new ActivityStartController(this);
    // 創(chuàng)建最近任務(wù)棧 RecentTask 對象
    mRecentTasks = createRecentTasks();
    mStackSupervisor.setRecentTasks(mRecentTasks);
    mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
    mLifecycleManager = new ClientLifecycleManager();

    // 創(chuàng)建 CpuTracker 線程,追蹤 CPU 狀態(tài)
    mProcessCpuThread = new Thread("CpuTracker") {
        @Override
        public void run() {
            synchronized (mProcessCpuTracker) {
                mProcessCpuInitLatch.countDown();
                mProcessCpuTracker.init(); // 初始化 ProcessCpuTracker责静。注意同步問題
            }
            while (true) {
                try {
                    try {
                        synchronized(this) {
                            final long now = SystemClock.uptimeMillis();
                            long nextCpuDelay = (mLastCpuTime.get()+MONITOR_CPU_MAX_TIME)-now;
                            long nextWriteDelay = (mLastWriteTime+BATTERY_STATS_TIME)-now;
                            //Slog.i(TAG, "Cpu delay=" + nextCpuDelay
                            //        + ", write delay=" + nextWriteDelay);
                            if (nextWriteDelay < nextCpuDelay) {
                                nextCpuDelay = nextWriteDelay;
                            }
                            if (nextCpuDelay > 0) {
                                mProcessCpuMutexFree.set(true);
                                this.wait(nextCpuDelay);
                            }
                        }
                    } catch (InterruptedException e) {
                    }
                    // 更新 Cpu 統(tǒng)計信息
                    updateCpuStatsNow();
                } catch (Exception e) {
                    Slog.e(TAG, "Unexpected exception collecting process stats", e);
                }
            }
        }
    };

    // hidden api 設(shè)置
    mHiddenApiBlacklist = new HiddenApiSettings(mHandler, mContext);

    // 設(shè)置 Watchdog 監(jiān)控
    Watchdog.getInstance().addMonitor(this);
    Watchdog.getInstance().addThread(mHandler);

    // bind background thread to little cores
    // this is expected to fail inside of framework tests because apps can't touch cpusets directly
    // make sure we've already adjusted system_server's internal view of itself first
    // 更新進程的 oom_adj 值
    updateOomAdjLocked();
    try {
        Process.setThreadGroupAndCpuset(BackgroundThread.get().getThreadId(),
                Process.THREAD_GROUP_BG_NONINTERACTIVE);
    } catch (Exception e) {
        Slog.w(TAG, "Setting background thread cpuset failed");
    }
}

最終調(diào)用ActivityManagerService中的start方法

 private void start() {
    removeAllProcessGroups();   // 移除所有進程組
    mProcessCpuThread.start();//啟動同步CPU的線程袁滥,監(jiān)控 cpu 使用情況
    mBatteryStatsService.publish();//訂閱WIFI和mobile電量,統(tǒng)計電池信息
    mAppOpsService.publish(mContext);//訂閱app管理服務(wù)(前后臺等)
    Slog.d("AppOps", "AppOpsService published");
    LocalServices.addService(ActivityManagerInternal.class, new LocalService());//啟動本地服務(wù)
    mActivityTaskManager.onActivityManagerInternalAdded();//啟動ActivityManagerInternal灾螃,UriGrantsManagerInternal
    mUgmInternal.onActivityManagerInternalAdded();//UriGrantsManagerService啟動本地服務(wù)
    mPendingIntentController.onActivityManagerInternalAdded();//pending intent controller啟動本地服務(wù)
// 等待 mProcessCpuThread 線程中的同步代碼塊執(zhí)行完畢题翻。
    try {
        mProcessCpuInitLatch.await();
    } catch (InterruptedException e) {
        Slog.wtf(TAG, "Interrupted wait during start", e);
        Thread.currentThread().interrupt();
        throw new IllegalStateException("Interrupted wait during start");
    }
}

相關(guān)代碼與方法:
SystemServer
ActivityManagerService
SystemServiceManager

3.AMS 與進程啟動

Zygote 的 Java 框架層中,會創(chuàng)建一個 Server 端的 Socket腰鬼,這個 Socket 用來等待
AMS 來請求 Zygote 來創(chuàng)建新的應(yīng)用程序進程嵌赠。要啟動一個應(yīng)用程序,首先要保
證這個應(yīng)用程序所需要的應(yīng)用程序進程已經(jīng)被啟動垃喊。AMS 在啟動應(yīng)用程序時會
檢查這個應(yīng)用程序需要的應(yīng)用程序進程是否存在,不存在就會請求 Zygote 進程
將需要的應(yīng)用程序進程啟動袜炕。Service 的啟動過程中會調(diào)用 ActiveServices 的
bringUpServiceLocked 方法本谜,

 private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException {
    ...
    final String procName = r.processName;//1
    ...
    ProcessRecord app;
    if (!isolated) {
        app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);//2
        ...
        if (app != null && app.thread != null) {//3
            try {
                app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);
                realStartServiceLocked(r, app, execInFg);//4
                return null;
            }...
        }
    } else {
       ...
    }
    if (app == null && !permissionsReviewRequired) {//5
        if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                hostingRecord, false, isolated, false)) == null) {//6
           ...
        }
        if (isolated) {
            r.isolatedProc = app;
        }
    }
    ...
}

代碼:ActiveServices
在注釋 1 處得到 ServiceRecord 的 processName 的值賦值給 procName ,其中
ServiceRecord 用來描述 Service 的 android:process 屬性偎窘。
注釋 2 處將 procName和 Service 的 uid 傳入到 AMS 的 getProcessRecordLocked 方法中乌助,來查詢是否存在一個與 Service 對應(yīng)的 ProcessRecord 類型的對象 app,ProcessRecord 主要用來記錄運行的應(yīng)用程序進程的信息陌知。
注釋 5 處判斷 Service 對應(yīng)的 app 為 null 則說明用來運行 Service 的應(yīng)用程序進程不存在他托,則調(diào)用注釋 6 處的 AMS 的startProcessLocked 方法來創(chuàng)建對應(yīng)的應(yīng)用程序進程,

4.AMS 主要類

其他

補充下SystemServer啟動的服務(wù):


1715843623236.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末仆葡,一起剝皮案震驚了整個濱河市赏参,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌沿盅,老刑警劉巖把篓,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異腰涧,居然都是意外死亡韧掩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進店門窖铡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疗锐,“玉大人,你說我怎么就攤上這事费彼』” “怎么了?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵箍铲,是天一觀的道長简珠。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么聋庵? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任膘融,我火速辦了婚禮,結(jié)果婚禮上祭玉,老公的妹妹穿的比我還像新娘氧映。我一直安慰自己,他們只是感情好脱货,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布岛都。 她就那樣靜靜地躺著,像睡著了一般振峻。 火紅的嫁衣襯著肌膚如雪臼疫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天扣孟,我揣著相機與錄音烫堤,去河邊找鬼。 笑死凤价,一個胖子當(dāng)著我的面吹牛鸽斟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播利诺,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼富蓄,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了慢逾?” 一聲冷哼從身側(cè)響起立倍,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侣滩,沒想到半個月后帐萎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡胜卤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年疆导,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片葛躏。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡澈段,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出舰攒,到底是詐尸還是另有隱情败富,我是刑警寧澤,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布摩窃,位于F島的核電站兽叮,受9級特大地震影響芬骄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鹦聪,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一账阻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧泽本,春花似錦淘太、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至赌莺,卻和暖如春冰抢,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背艘狭。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工挎扰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人缓升。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓鼓鲁,卻偏偏與公主長得像蕴轨,于是被迫代替她去往敵國和親港谊。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

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