Android 系統(tǒng)服務(wù) - AMS 的啟動過程

相關(guān)文章鏈接:

1. Android Framework - 學(xué)習(xí)啟動篇
2. Android Framework - 開機啟動 SystemServer 進程

相關(guān)源碼文件:

/frameworks/base/services/java/com/android/server/SystemServer.java
/frameworks/base/services/core/java/com/android/server/SystemServiceManager.java
/frameworks/base/services/core/java/com/android/server/ServiceThread.java
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

ActivityManagerService 是 Android 中非常重要的一個服務(wù)箱残,主要功能是管理和啟動四大組件邦鲫。其源代碼大約有 2W 多行哮内,這里我們主要來分析其啟動過程百宇,后面的文章我們肯定還會分析具體的源碼細(xì)節(jié)。AMS 是由 SystemServer 進程啟動的衙吩,對于這個有不了解的同學(xué)請看這里《Android Framework - 開機啟動 SystemServer 進程》

    private void startBootstrapServices() {
      ...
      // 啟動 AMS 服務(wù) 
      mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();

      // 設(shè)置 AMS 的系統(tǒng)服務(wù)管理器
      mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
      // 設(shè)置 AMS 的 APP 安裝器
      mActivityManagerService.setInstaller(installer);
      ...

      // 設(shè)置 SystemServer 
      mActivityManagerService.setSystemProcess();
    }

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

        public Lifecycle(Context context) {
            super(context);
            // 創(chuàng)建 ActivityManagerService
            mService = new ActivityManagerService(context);
        }

        @Override
        public void onStart() {
            // 調(diào)用 start 方法
            mService.start();
        }

        // 獲取 ActivityManagerService
        public ActivityManagerService getService() {
            return mService;
        }
    }

    // Note: This method is invoked on the main thread but may need to attach various
    // handlers to other threads.  So take care to be explicit about the looper.
    public ActivityManagerService(Context systemContext) {
        mContext = systemContext;
        // 獲取 ActivityThread
        mSystemThread = ActivityThread.currentActivityThread();

        // 創(chuàng)建名為"ActivityManager"的前臺 HandlerThread
        mHandlerThread = new ServiceThread(TAG,
                android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
        // 啟動 ServiceThread
        mHandlerThread.start();
        // 創(chuàng)建一個 MainHandler 與 mHandlerThread 公用一個 looper 
        mHandler = new MainHandler(mHandlerThread.getLooper());
        // 創(chuàng)建 UiHandler 其內(nèi)部也會創(chuàng)建一個 HandlerThread
        mUiHandler = new UiHandler();
        // 前臺和后臺廣播接收隊列望抽,分別是 10s 和 60s 放棄執(zhí)行
        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)建目錄/data/system
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        systemDir.mkdirs();
        // 創(chuàng)建 BatteryStatsService,相當(dāng)于電表
        mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
        mBatteryStatsService.getActiveStatistics().readLocked();
        mBatteryStatsService.scheduleWriteToDisk();
        mBatteryStatsService.getActiveStatistics().setCallback(this);
        // 創(chuàng)建進程統(tǒng)計服務(wù)塞耕,信息保存在目錄 /data/system/procstats,
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
        ...
        // 創(chuàng)建 ActivityStackSupervisor 對象
        mStackSupervisor = new ActivityStackSupervisor(this, mRecentTasks);
        mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, mRecentTasks);
        // 創(chuàng)建名為 "CpuTracker" 的線程
        mProcessCpuThread = new Thread("CpuTracker") {
            @Override
            public void run() {
                while (true) {
                    try {
                        ...
                        updateCpuStatsNow();
                    } catch (Exception e) {
                        Slog.e(TAG, "Unexpected exception collecting process stats", e);
                    }
                }
            }
        };
        // 看門狗
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
    }

在 SystemService 進程的啟動過程中會調(diào)用 startBootstrapServices 方法郊艘,其內(nèi)部會啟動 AMS 服務(wù)荷科,在 ActivityManagerService 的構(gòu)造函數(shù)中會創(chuàng)建三個線程分別是 ActivityManager 、UI 和 CpuTracker纱注。我們接著看 start 方法:

    private void start() {
        // 移除所有的進程組
        Process.removeAllProcessGroups();
        // 啟動 CpuTracker 線程
        mProcessCpuThread.start();
        // 把電表服務(wù)注冊添加到 ServiceManager
        mBatteryStatsService.publish(mContext);
        mAppOpsService.publish(mContext);
        Slog.d("AppOps", "AppOpsService published");
        LocalServices.addService(ActivityManagerInternal.class, new LocalService());
    }

    public void setSystemProcess() {
        try {
            // 把自己加到 ServiceManager ,然后注冊額外的一些服務(wù)
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));
            // 通過 pms 獲取 ApplicationInfo 信息
            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS);
            // 初始化 ApplicationInfo 和 ClassLoader
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            synchronized (this) {
                // 創(chuàng)建 ProcessRecord 對象
                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);
        }
    } 

    private void startOtherServices() {
      ...
      // 安裝系統(tǒng) Provider 
      mActivityManagerService.installSystemProviders();
      ...

      mActivityManagerService.systemReady(new Runnable() {
       public void run() {
             // 啟動 WebView
             WebViewFactory.prepareWebViewInSystemServer();
             // 啟動 SystemUi
             startSystemUi(context);
             // 調(diào)用一系列服務(wù)的 systemReady 方法
             ...
             // 調(diào)用一系列服務(wù)的 systemRunning 方法
             ...
        }
      }
    }

    public void systemReady(final Runnable goingCallback) {
        ...
        // 執(zhí)行 Callback 的 run 方法
        if (goingCallback != null) goingCallback.run();
        // Start up initial activity.
        mBooting = true;
        // 啟動桌面 Activity 進程
        startHomeActivityLocked(mCurrentUserId, "systemReady");
    }

    static final void startSystemUi(Context context) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.OWNER);
    }

關(guān)于 AMS 的啟動流程還是很簡單的胆胰,調(diào)用構(gòu)造函數(shù)會初始化三個線程狞贱;調(diào)用 setSystemProcess 方法中會向 ServcieManager 進程額外發(fā)布一些服務(wù):procstats(進程信息)、meminfo(內(nèi)存信息)蜀涨、gfxinfo(圖形信息)瞎嬉、cpuinfo(cpu信息)、permission(權(quán)限)厚柳、processinfo(應(yīng)用使用情況)等氧枣;調(diào)用 systemReady 方法首先會啟動 SystemUIService,然后執(zhí)行一系列服務(wù)的 systemReady 和 systemRunning 方法别垮,最后啟動桌面 Activity 進程便监。

視頻地址:https://pan.baidu.com/s/1dM3K9bPRuepFUJIASIDeQg
視頻密碼:af97

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碳想,隨后出現(xiàn)的幾起案子烧董,更是在濱河造成了極大的恐慌,老刑警劉巖胧奔,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逊移,死亡現(xiàn)場離奇詭異,居然都是意外死亡龙填,警方通過查閱死者的電腦和手機胳泉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來岩遗,“玉大人扇商,你說我怎么就攤上這事〈龋” “怎么了钳吟?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長窘拯。 經(jīng)常有香客問我红且,道長坝茎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任暇番,我火速辦了婚禮嗤放,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘壁酬。我一直安慰自己次酌,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布舆乔。 她就那樣靜靜地躺著岳服,像睡著了一般。 火紅的嫁衣襯著肌膚如雪希俩。 梳的紋絲不亂的頭發(fā)上吊宋,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音颜武,去河邊找鬼璃搜。 笑死,一個胖子當(dāng)著我的面吹牛鳞上,可吹牛的內(nèi)容都是我干的这吻。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼篙议,長吁一口氣:“原來是場噩夢啊……” “哼唾糯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涡上,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤趾断,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吩愧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體芋酌,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年雁佳,在試婚紗的時候發(fā)現(xiàn)自己被綠了脐帝。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡糖权,死狀恐怖堵腹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情星澳,我是刑警寧澤疚顷,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響腿堤,放射性物質(zhì)發(fā)生泄漏阀坏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一笆檀、第九天 我趴在偏房一處隱蔽的房頂上張望忌堂。 院中可真熱鬧,春花似錦酗洒、人聲如沸士修。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棋嘲。三九已至,卻和暖如春箫老,著一層夾襖步出監(jiān)牢的瞬間封字,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工耍鬓, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人流妻。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓牲蜀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绅这。 傳聞我的和親對象是個殘疾皇子涣达,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348