AMS系列①—AMS的啟動(dòng)

AMS作為Android FrameWork中最核心的一個(gè)部分,是應(yīng)用層開發(fā)者進(jìn)階的里程碑,本文是AMS專欄的第一篇文章,介紹AMS的啟動(dòng)相關(guān):

在學(xué)習(xí)AMS之前破加,需要掌握一些基礎(chǔ)知識(shí):

在學(xué)習(xí)完上面的內(nèi)容后,我們可以知道AMS的啟動(dòng)是由SystemServer進(jìn)程發(fā)起的:

AMS的入口方法SystemServer的main()做了兩件事:

  • 調(diào)用CreateSystemContext()創(chuàng)建SystemContext
  • 開啟三類服務(wù):引導(dǎo)服務(wù)雹嗦,核心服務(wù)范舀,其他服務(wù)

1. SystemServer.createSystemContext():

    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
    }

ActivityThread.systemMain():

    public static ActivityThread systemMain() {
        ActivityThread thread = new ActivityThread();
        thread.attach(true, 0);
        return thread;
    }

在SystemMain中,首先創(chuàng)建了一個(gè)SystemServer進(jìn)程的ActivityThread了罪,沒錯(cuò)锭环,這就是用戶進(jìn)程的入口main的那個(gè)ActivityThread,所以從某種意義上講泊藕,我們也可以將SystemServer進(jìn)程看成一個(gè)App辅辩;

調(diào)用了ActivityThread的attach(),注意娃圆,這里傳入的是true玫锋,而我們正常的App傳入的是false,這個(gè)字段表示是否是系統(tǒng)進(jìn)程(SystemServer進(jìn)程):

ActivityThread.attach():

    private void attach(boolean system, long startSeq) {
...
        if (!system) {    //  如果是正常App進(jìn)程讼呢,傳入false
...
            final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread, startSeq);
            } 
...
        } else {   //  如果是SystemServer進(jìn)程撩鹿,傳入true
...
            try {
                mInstrumentation = new Instrumentation();
                mInstrumentation.basicInit(this);
                ContextImpl context = ContextImpl.createAppContext(
                        this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
            } 
        }
    }

如果是正常的APP,那么進(jìn)入if邏輯悦屏,調(diào)用AMS的代理發(fā)起一次Binder消息节沦,實(shí)際調(diào)用AMS的attachApplication();
在本次情況中是由SystemServer進(jìn)程發(fā)起的键思,進(jìn)入else邏輯:

  • 調(diào)用ContextImpl.createAppContext()創(chuàng)建App Context
  • 注意上一個(gè)方法,傳入了一個(gè)getSystemContext().mPackageInfo參數(shù)
  • 調(diào)用makeApplication創(chuàng)建Application

我們先來看傳入的參數(shù):

ActivityThread.getSystemContext()

    public ContextImpl getSystemContext() {
        synchronized (this) {
                mSystemContext = ContextImpl.createSystemContext(this);
    }

getSystemContext()調(diào)用了ContextImpl的createSystemContext():

ContextImpl.createSystemContext():

    static ContextImpl createSystemContext(ActivityThread mainThread) {
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(packageInfo.getResources());
        return context;
    }

ContextImpl有一系列的創(chuàng)建Context的static 方法:



在這里創(chuàng)建了SystemContext甫贯,Context的具體作用就是用來獲取資源吼鳞,比如你的Activity需要使用apk里面的資源,而系統(tǒng)SystemServer也需要使用系統(tǒng)預(yù)設(shè)的資源文件叫搁,所以在這里也創(chuàng)建了一個(gè)Context對(duì)象;

那么Context是如何獲取資源的呢赔桌?答案是LoadedApk這個(gè)類,LoadedApk是apk文件在內(nèi)存中的存在形式
所以一般ApplicationContext或者ActivityContext都會(huì)持有它對(duì)應(yīng)的apk文件的內(nèi)存形式LoadedApk對(duì)象常熙;那么我們的SystemServer是跟哪個(gè)APK綁定呢纬乍??裸卫?看下面這張圖就明白了:

雖然它是一個(gè)LoadedAPK對(duì)象,但是并沒有對(duì)應(yīng)apk文件纽竣,它存在的意義就是為SystemContext服務(wù)墓贿,為它提供獲取系統(tǒng)資源的能力;注意倒數(shù)第二第三行蜓氨,SystemClassLoader聋袋,SystemResource,如果是通過其他構(gòu)造方法創(chuàng)建的LoadedApk穴吹,就不會(huì)有這個(gè)值幽勒,他們是通過對(duì)應(yīng)apk文件解析出來的數(shù)據(jù);

至此港令,我們的SystemContext創(chuàng)建完畢啥容,回到ActivityThread.attach():這一步,參數(shù)看好了顷霹,參數(shù)就是SystemContext的LoadedApk咪惠,就是那個(gè)沒有apk的LoadedAPK;

ContextImpl.CreateAppContext:

    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;
    }

在這里因?yàn)閭魅氲腖oadedAPK是被閹割的LoadedAPK對(duì)象淋淀,所以這個(gè)ApplicationContext遥昧,本質(zhì)上和SystemContext一樣,他們的resource都是System Resource朵纷;

context.mPackageInfo.makeApplication(true, null):

   public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
...
            ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
        } 
...
        return app;
    }

mInstrumentation.newApplication()

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }

makeApplication的邏輯就是創(chuàng)建Application對(duì)象炭臭,然后調(diào)用Application的attach方法:

    /* package */ final void attach(Context context) {
        attachBaseContext(context);
        mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
    }

    protected void attachBaseContext(Context base) {
        if (mBase != null) {
            throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

保存Application Context 和 LoadedApk到Application

至此SystemServer創(chuàng)建System Context的操作分析完畢,下面分析SystemServer的run()中開啟三類服務(wù)中關(guān)于AMS的邏輯

SystemServer.startBootstrapServices():

    private void startBootstrapServices() {
...
       mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();

       mActivityManagerService.setInstaller(installer);

        mActivityManagerService.initPowerManagement();

        mActivityManagerService.setSystemProcess();
    }

在啟動(dòng)引導(dǎo)服務(wù)startBootstrapServices這個(gè)方法中袍辞,涉及AMS的邏輯主要做了四件事:

  1. 創(chuàng)建AMS實(shí)例
  2. 設(shè)置installer鞋仍,App安裝器
  3. 初始化PMS
  4. 調(diào)用setSystemProcess()

1. startService(ActivityManagerService.Lifecycle.class).getService();

startService()傳入了一個(gè)AMS的內(nèi)部類Lifecycle的Class對(duì)象,會(huì)創(chuàng)建一個(gè)Lifecycle的實(shí)例革屠,接著這個(gè)Lifecycle會(huì)調(diào)用自己的getService方法獲取AMS實(shí)例:

        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);   
        }
        public ActivityManagerService getService() {
            return mService;
        }

下面看一下AMS的構(gòu)造方法凿试,AMS的構(gòu)造方法中排宰,做了很多事情:

   public ActivityManagerService(Context systemContext) {
...
        // 前臺(tái)服務(wù)線程 
        mHandlerThread = new ServiceThread(TAG,
                THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);

             //  后臺(tái)服務(wù)線程
            sKillThread = new ServiceThread(TAG + ":kill",
                    THREAD_PRIORITY_BACKGROUND, true /* allowIo */);

         // CPU線程
        mProcessCpuThread = new Thread("CpuTracker") ;

         //  AMS家族:
        mConstants = new ActivityManagerConstants(this, mHandler);
        mServices = new ActiveServices(this);
        mStackSupervisor = createStackSupervisor();
        mActivityStartController = new ActivityStartController(this);

        //  開啟 watch dog
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);

         // 創(chuàng)建 AppOpsService 那婉, Android原生應(yīng)用程序權(quán)限管理相關(guān)
        mAppOpsService = mInjector.getAppOpsService(new File(systemDir, "appops.xml"), mHandler);

        //創(chuàng)建進(jìn)程狀態(tài)服務(wù)板甘,監(jiān)聽進(jìn)程轉(zhuǎn)發(fā)服務(wù)
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));

        //創(chuàng)建電量狀態(tài)服務(wù)
        mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);


    }

在AMS的構(gòu)造方法中,大概做了以下幾件事:

  1. 創(chuàng)建各個(gè)工作線程详炬,前臺(tái)服務(wù)線程盐类,后臺(tái)服務(wù)線程,CPU線程
  2. 實(shí)例化AMS家族成員呛谜,ActivityManagerConstants在跳,ActiveServices,StackSupervisor隐岛,ActivityStartController猫妙,這些在后續(xù)會(huì)詳細(xì)介紹;
  3. 開啟各種服務(wù)聚凹,watch dog割坠,Appops,ProcessStatsService妒牙,BatteryStatsService
  • 軟件看門狗來監(jiān)控SystemServer中的線程彼哼。一旦發(fā)現(xiàn)問題,WatchDog會(huì)殺死SystemServer進(jìn)程湘今。SystemServer的父進(jìn)程Zygote接收到SystemServer的死亡信號(hào)后敢朱,會(huì)殺死自己。Zygote進(jìn)程死亡的信號(hào)傳遞到Init進(jìn)程后摩瞎,Init進(jìn)程會(huì)殺死Zygote進(jìn)程所有的子進(jìn)程并重啟Zygote拴签。這樣整個(gè)手機(jī)相當(dāng)于重啟一遍。通常SystemServer出現(xiàn)問題和kernel并沒有關(guān)系愉豺,所以這種“軟重啟”大部分時(shí)候都能夠解決問題篓吁。而且這種“軟重啟”的速度更快,對(duì)用戶的影響也更小蚪拦。
至此杖剪,第一步AMS的實(shí)例化分析完畢,步驟2 和 步驟3 是設(shè)置APk安裝器和初始化PMS驰贷,不做過多介紹盛嘿,下面詳細(xì)看下步驟4setSystemProcess()

4 mActivityManagerService.setSystemProcess();

    public void setSystemProcess() {
        try {
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
                    DUMP_FLAG_PRIORITY_HIGH);
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this),
                        /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));

            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            synchronized (this) {
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
            }
        } 

        // Start watching app ops after we and the package manager are up and running.
        mAppOpsService.startWatchingMode(AppOpsManager.OP_RUN_IN_BACKGROUND, null);
    }

在AMS的setSystemProcess()中主要做了四件事:

  1. 添加各種服務(wù)到ServiceManager中:this(自己AMS服務(wù)),內(nèi)存括袒,圖像次兆,權(quán)限,cpu锹锰,進(jìn)程芥炭,相關(guān)服務(wù)
  2. installSystemApplicationInfo
  3. 創(chuàng)建ProcessRecord對(duì)象
  4. 調(diào)用AppOps服務(wù)的startWatch方法開啟對(duì)應(yīng)用程序包給定權(quán)限的監(jiān)聽漓库;
步驟2:installSystemApplicationInfo():
    public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
        synchronized (this) {
            getSystemContext().installSystemApplicationInfo(info, classLoader);
            getSystemUiContext().installSystemApplicationInfo(info, classLoader);

            // give ourselves a default profiler
            mProfiler = new Profiler();
        }
    }

步驟2做了兩件事:

  • 將ApplicationInfo對(duì)象設(shè)置給SystemContext
  • 創(chuàng)建Profiler對(duì)象,用于性能統(tǒng)計(jì)

至此SystemService開啟引導(dǎo)服務(wù)中AMS相關(guān)的邏輯分析完畢园蝠;


SystemServer.startOtherServices():

mActivityManagerService.systemReady(() -> {
            mSystemServiceManager.startBootPhase(
            try {
                mActivityManagerService.startObservingNativeCrashes();
            }  
    public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {


            mVrController.onSystemReady();
            mUserController.onSystemReady();
            mRecentTasks.onSystemReadyLocked();
            mAppOpsService.systemReady();
            mSystemReady = true;

            startHomeActivityLocked(currentUserId, "systemReady");
    }

在startOtherServices()中渺蒿,AMS的主要邏輯就是調(diào)用了SystemReady()開啟一個(gè)Activity,開啟Activity的內(nèi)容后期再講彪薛,會(huì)設(shè)計(jì)AMS的大家族茂装;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市善延,隨后出現(xiàn)的幾起案子少态,更是在濱河造成了極大的恐慌,老刑警劉巖易遣,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彼妻,死亡現(xiàn)場離奇詭異,居然都是意外死亡豆茫,警方通過查閱死者的電腦和手機(jī)澳骤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澜薄,“玉大人,你說我怎么就攤上這事摊册》艟” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵茅特,是天一觀的道長忘分。 經(jīng)常有香客問我,道長白修,這世上最難降的妖魔是什么妒峦? 我笑而不...
    開封第一講書人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮兵睛,結(jié)果婚禮上肯骇,老公的妹妹穿的比我還像新娘。我一直安慰自己祖很,他們只是感情好笛丙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著假颇,像睡著了一般胚鸯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笨鸡,一...
    開封第一講書人閱讀 51,624評(píng)論 1 305
  • 那天姜钳,我揣著相機(jī)與錄音坦冠,去河邊找鬼。 笑死哥桥,一個(gè)胖子當(dāng)著我的面吹牛辙浑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播泰讽,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼例衍,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了已卸?” 一聲冷哼從身側(cè)響起佛玄,我...
    開封第一講書人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎累澡,沒想到半個(gè)月后梦抢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愧哟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年奥吩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蕊梧。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡霞赫,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肥矢,到底是詐尸還是另有隱情端衰,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布甘改,位于F島的核電站旅东,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏十艾。R本人自食惡果不足惜抵代,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望忘嫉。 院中可真熱鬧荤牍,春花似錦、人聲如沸榄融。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽愧杯。三九已至涎才,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背耍铜。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來泰國打工邑闺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人棕兼。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓陡舅,卻偏偏與公主長得像,于是被迫代替她去往敵國和親伴挚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子靶衍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355