Android啟動(dòng)流程(Java層)

寫在前面的話

目前打算是先把Android的啟動(dòng)流程包括luncher、Activity的啟動(dòng)以及Service啟動(dòng)断部,View的繪制,事件分發(fā)等進(jìn)行分析,后面應(yīng)該還會(huì)包括現(xiàn)階段正在使用的框架MVVM的分析券勺。可能是更新Android不會(huì)太久了没酣,有點(diǎn)迷茫Android的未來到底在哪里舀患,把握現(xiàn)在吧。
今天這部分講解的是Android系統(tǒng)啟動(dòng)后加載各種服務(wù)的過程舌剂。

1 init

init是第一個(gè)進(jìn)程济锄,我們可以說它是root進(jìn)程或者說有進(jìn)程的父進(jìn)程。init進(jìn)程有兩個(gè)責(zé)任霍转,一是掛載目錄荐绝,比如/sys、/dev避消、/proc低滩,二是運(yùn)行init.rc腳本。
init進(jìn)程可以在/system/core/init找到岩喷。
init.rc文件可以在/system/core/rootdir/init.rc找到恕沫。
readme.txt可以在/system/core/init/readme.txt找到。
對(duì)于init.rc文件纱意,Android中有特定的格式以及規(guī)則婶溯。在Android中,我們叫做Android初始化語言。


2 Zygote加載進(jìn)程

Zygote本意是受精卵迄委,Android中可以理解為孵化器褐筛。Android的應(yīng)用的進(jìn)程都是由Zygote孵化而來,因此他們都有共同的ppid(父進(jìn)程的id)


3 SystemServer啟動(dòng)

Zygote啟動(dòng)完成后叙身,Zygote創(chuàng)建新的進(jìn)程去啟動(dòng)系統(tǒng)服務(wù)死讹。我們都知道Android的進(jìn)程間通信是通過binder機(jī)制,通過binder機(jī)制可以避免對(duì)某個(gè)服務(wù)的單獨(dú)創(chuàng)建曲梗,所有的服務(wù)在系統(tǒng)啟動(dòng)后即創(chuàng)建完成赞警。但是我們通過Context.getSystemService(String name)獲的并不是我們的服務(wù)的代理類,我們獲取的是各種Manager類虏两。


3.1 SystemServer啟動(dòng)流程

打開SystemServer.java ,我們可以看到它是一個(gè)含有main方法的類愧旦,Zygote啟動(dòng)系統(tǒng)服務(wù)時(shí)會(huì)調(diào)用這個(gè)main方法。

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

main創(chuàng)建了SystemServer對(duì)象后定罢,調(diào)用其run方法笤虫,下面是具體實(shí)現(xiàn)。

private void run() {
    try {
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitBeforeStartServices");
        //進(jìn)行時(shí)間校驗(yàn)
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
            Slog.w(TAG, "System clock is before 1970; setting to 1970.");
            SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
        }
        //語言校驗(yàn)
        if (!SystemProperties.get("persist.sys.language").isEmpty()) {
            final String languageTag = Locale.getDefault().toLanguageTag();

            SystemProperties.set("persist.sys.locale", languageTag);
            SystemProperties.set("persist.sys.language", "");
            SystemProperties.set("persist.sys.country", "");
            SystemProperties.set("persist.sys.localevar", "");
        }
        
        ......
        //設(shè)置線程優(yōu)先級(jí)
        android.os.Process.setThreadPriority(
            android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        
        //開啟了一個(gè)Looper用于消息處理祖凫,此處和ActivityThread創(chuàng)建消息隊(duì)列循環(huán)一致
        Looper.prepareMainLooper();
        //加載了android_servers.so琼蚯,里面應(yīng)該是各個(gè)server
        System.loadLibrary("android_servers");
        performPendingShutdown();
        //創(chuàng)建了系統(tǒng)的上下文Context 3.1.1
        createSystemContext();
        //將SystemServiceManager放入LocalServices中
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }

    try {
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
        //啟動(dòng)關(guān)鍵services 3.2
        startBootstrapServices();
        //啟動(dòng)核心services 3.3
        startCoreServices();
        //啟動(dòng)其他services 3.4
        startOtherServices();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }

    if (StrictMode.conditionallyEnableDebugLogging()) {
        Slog.i(TAG, "Enabled StrictMode for system server main thread.");
    }
    //開啟消息隊(duì)列循環(huán)
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

run()方法中先對(duì)時(shí)間和語言進(jìn)行校驗(yàn)后,創(chuàng)建了一個(gè)消息隊(duì)列惠况,并通過createSystemContext()方法創(chuàng)建SystemServer的上下文對(duì)象遭庶,之后開始啟動(dòng)引導(dǎo)services,接下來是核心services以及最后啟動(dòng)其他services稠屠。


3.1.1 createSystemContext()過程

從名字中我們可以知道這個(gè)方法是用來創(chuàng)建系統(tǒng)的上下文對(duì)象峦睡,createSystemContext()中代碼比較少,很容易理解权埠。

private void createSystemContext() {
    //通過ActivityThread的systemMain()進(jìn)行對(duì)象的創(chuàng)建 3.1.2
    ActivityThread activityThread = ActivityThread.systemMain();
    //將上下文對(duì)象賦值
    mSystemContext = activityThread.getSystemContext();
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}

3.1.2 Context創(chuàng)建的過程

ActivityThread創(chuàng)建的過程榨了,不得不說谷歌的代碼真是短小精悍啊。

public static ActivityThread systemMain() {
    if (!ActivityManager.isHighEndGfx()) {
        ThreadedRenderer.disable(true);
    } else {
        ThreadedRenderer.enableForegroundTrimming();
    }
    //好像注釋都不需要了攘蔽。
    ActivityThread thread = new ActivityThread();
    thread.attach(true);
    return thread;
}

接著我們來看thread.attach(true)方法龙屉。(參數(shù)我們傳入的是true),這里只展示執(zhí)行的代碼满俗。

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
       ......
    } else {
        // Don't set application object here -- if the system crashes,
        // we can't display an alert, we just want to die die die.
        //這句話挺有意思的转捕。。漫雷。
        android.ddm.DdmHandleAppName.setAppName("system_process",
                UserHandle.myUserId());
        try {
            mInstrumentation = new Instrumentation();
            //創(chuàng)建context
            ContextImpl context = ContextImpl.createAppContext(
                    this, getSystemContext().mPackageInfo);
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            //調(diào)用Application的onCreate()方法
            mInitialApplication.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }
    DropBox.setReporter(new DropBoxReporter());

    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {......});
}

//對(duì)象不重復(fù)創(chuàng)建
public ContextImpl getSystemContext() {
    synchronized (this) {
        if (mSystemContext == null) {
            //創(chuàng)建系統(tǒng)的上下文
            mSystemContext = ContextImpl.createSystemContext(this);
        }
        return mSystemContext;
    }
}

代碼比較簡單瓜富,通過createAppContext方法創(chuàng)建一個(gè)上下文對(duì)象,并通過makeApplication方法創(chuàng)建Application降盹,并調(diào)用onCreate()方法与柑,最后調(diào)用getSystemContext()將上下文賦值給mSystemContext谤辜。這邊對(duì)上下文的創(chuàng)建就到這里結(jié)束了,下面開始對(duì)各種服務(wù)啟動(dòng)的流程分析价捧。


3.2 startBootstrapServices()啟動(dòng)核心服務(wù)

啟動(dòng)核心服務(wù)的過程其實(shí)并沒有多么的復(fù)雜丑念,最開始被啟動(dòng)的是Installer,即系統(tǒng)安裝apk時(shí)的一個(gè)服務(wù)類结蟋,啟動(dòng)完成Installer服務(wù)之后才能啟動(dòng)其他的系統(tǒng)服務(wù)脯倚,之后啟動(dòng)AMSPowerManagerService嵌屎,LightsService推正,DisplayManagerService......,核心代碼如下:

private void startBootstrapServices() {
    //系統(tǒng)安裝apk時(shí)的一個(gè)服務(wù)類宝惰,啟動(dòng)完成Installer服務(wù)之后才能啟動(dòng)其他的系統(tǒng)服務(wù)
    //直接翻譯了源碼注釋(有點(diǎn)無恥哈)植榕。
    //等待installd完成啟動(dòng),以便它有機(jī)會(huì)創(chuàng)建具有適當(dāng)權(quán)限的關(guān)鍵目錄尼夺,如/ data / user尊残。 
    //在我們初始化其他服務(wù)之前,我們需要完成這個(gè)工作 startService 3.2.1
    Installer installer = mSystemServiceManager.startService(Installer.class);
    //啟動(dòng)ActivityManagerService
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    //電源管理器需要提前啟動(dòng)淤堵,因?yàn)槠渌?wù)需要它寝衫。
    //本地守護(hù)進(jìn)程可能正在注冊(cè),因此它必須立即處理傳入的綁定器調(diào)用(包括能夠驗(yàn)證這些調(diào)用的權(quán)限)拐邪。
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

    Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitPowerManagement");
    mActivityManagerService.initPowerManagement();
    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    //啟動(dòng)燈光service
    mSystemServiceManager.startService(LightsService.class);
    //啟動(dòng)顯示service
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    //在初始化package manager完成前慰毅,我們需要默認(rèn)顯示
    mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

    String cryptState = SystemProperties.get("vold.decrypt");
    if (ENCRYPTING_STATE.equals(cryptState)) {
        Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        Slog.w(TAG, "Device encrypted - only parsing core apps");
        mOnlyCore = true;
    }

    traceBeginAndSlog("StartPackageManagerService");
    //PackageManagerService開始初始化
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    
    if (!mOnlyCore) {
        boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
                false);
        if (!disableOtaDexopt) {
            traceBeginAndSlog("StartOtaDexOptService");
            try {
                OtaDexoptService.main(mSystemContext, mPackageManagerService);
            } catch (Throwable e) {
                reportWtf("starting OtaDexOptService", e);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }
        }
    }

    traceBeginAndSlog("StartUserManagerService");
    //多用戶UserManagerService
    mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
    
    Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    
    AttributeCache.init(mSystemContext);
    //把幾個(gè)service添加到ServiceManager的中
    mActivityManagerService.setSystemProcess();
    //啟動(dòng)傳感器的服務(wù),native方法
    startSensorService();
}

3.2.1 SystemServiceManager.startService的過程

啟動(dòng)service的過程比較簡單庙睡,通過反射去創(chuàng)建service對(duì)象事富,其構(gòu)造方法的參數(shù)為Context,并將其添加到SystemServiceManagermServices列表中乘陪。

/**
 * 通過反射去創(chuàng)建,其構(gòu)造方法的參數(shù)為Context
 */
public <T extends SystemService> T startService(Class<T> serviceClass) {
    try {
        final String name = serviceClass.getName();
        // Create the service.
        if (!SystemService.class.isAssignableFrom(serviceClass)) {
            throw new RuntimeException("Failed to create " + name
                    + ": service must extend " + SystemService.class.getName());
        }
        final T service;
        try {
            Constructor<T> constructor = serviceClass.getConstructor(Context.class);
            service = constructor.newInstance(mContext);
        } catch (InstantiationException ex) {......}

        // 添加到mServices列表中
        mServices.add(service);
        try {
            //調(diào)用onStart方法
            service.onStart();
        } catch (RuntimeException ex) {......}
        return service;
    } finally {
        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
    }
}

3.3啟動(dòng)核心服務(wù)

從代碼中可以看出核心服務(wù)包括了管理電池相關(guān)的服務(wù)雕擂,收集用戶使用每一個(gè)APP的頻率啡邑、使用時(shí)常的服務(wù)以及WebView更新服務(wù)的啟動(dòng)。

private void startCoreServices() {
    //管理電池相關(guān)的服務(wù)
    mSystemServiceManager.startService(BatteryService.class);

    //收集用戶使用每一個(gè)APP的頻率井赌、使用時(shí)常
    mSystemServiceManager.startService(UsageStatsService.class);
    mActivityManagerService.setUsageStatsManager(
            LocalServices.getService(UsageStatsManagerInternal.class));

    //WebView更新服務(wù)
    mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
}

3.4 啟動(dòng)其他服務(wù)

啟動(dòng)其他服務(wù)谤逼,包括藍(lán)牙,攝像頭相關(guān)服務(wù)仇穗,管理輸入事件等服務(wù)流部,這里不贅述。

/**
 * 其他服務(wù)纹坐,包括藍(lán)牙枝冀,攝像頭相關(guān)服務(wù),管理輸入事件等服務(wù),這里不贅述
 */
private void startOtherServices() {
    ......
    //劃重點(diǎn)果漾,這里會(huì)啟動(dòng)HomeActivity球切,下篇講HomeActivity啟動(dòng)流程,這里mark下
    mActivityManagerService.systemReady(new Runnable() {
       @Override
        public void run() {
            ......
        }
    });
}

不過绒障,里面有個(gè)重要的地方是關(guān)于HomeActivity的啟動(dòng)吨凑,調(diào)用了mActivityManagerService.systemReady(new Runnable()后,會(huì)啟動(dòng)HomeActivity户辱,下篇講解下鸵钝。


寫在后面的話

今天的分析好像并沒有過多的流程,代碼看起來也比較簡單庐镐,后面的會(huì)比較復(fù)雜蒋伦,我會(huì)將時(shí)序圖上傳,方便自己以后復(fù)習(xí)焚鹊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痕届,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子末患,更是在濱河造成了極大的恐慌研叫,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,080評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件璧针,死亡現(xiàn)場離奇詭異嚷炉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)探橱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,422評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門申屹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人隧膏,你說我怎么就攤上這事哗讥。” “怎么了胞枕?”我有些...
    開封第一講書人閱讀 157,630評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵杆煞,是天一觀的道長。 經(jīng)常有香客問我腐泻,道長决乎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,554評(píng)論 1 284
  • 正文 為了忘掉前任派桩,我火速辦了婚禮构诚,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘铆惑。我一直安慰自己范嘱,他們只是感情好送膳,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,662評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著彤侍,像睡著了一般肠缨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盏阶,一...
    開封第一講書人閱讀 49,856評(píng)論 1 290
  • 那天晒奕,我揣著相機(jī)與錄音,去河邊找鬼名斟。 笑死脑慧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的砰盐。 我是一名探鬼主播闷袒,決...
    沈念sama閱讀 39,014評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼岩梳!你這毒婦竟也來了囊骤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,752評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤冀值,失蹤者是張志新(化名)和其女友劉穎也物,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體列疗,經(jīng)...
    沈念sama閱讀 44,212評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡滑蚯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,541評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抵栈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片告材。...
    茶點(diǎn)故事閱讀 38,687評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖古劲,靈堂內(nèi)的尸體忽然破棺而出斥赋,到底是詐尸還是另有隱情,我是刑警寧澤绢慢,帶...
    沈念sama閱讀 34,347評(píng)論 4 331
  • 正文 年R本政府宣布灿渴,位于F島的核電站,受9級(jí)特大地震影響胰舆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蹬挤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,973評(píng)論 3 315
  • 文/蒙蒙 一缚窿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧焰扳,春花似錦倦零、人聲如沸误续。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,777評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蹋嵌。三九已至,卻和暖如春葫隙,著一層夾襖步出監(jiān)牢的瞬間栽烂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,006評(píng)論 1 266
  • 我被黑心中介騙來泰國打工恋脚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腺办,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,406評(píng)論 2 360
  • 正文 我出身青樓糟描,卻偏偏與公主長得像怀喉,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子船响,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,576評(píng)論 2 349

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