Android開機啓動的那些事

以前知道AMS、PMS這些概念及其功能,開發的過程中也會用到,就是不知道其來源,好奇心害死貓,扒着扒着扒到系統開機啓動這個知識層面上來了,好吧,那今天就說說這個吧!

系統開機啓動過程

Android系統的啓動,主要是指Android手機關機後,長按電源鍵後,Android手機開機的過程。從系統角度看,Android的啓動程序可分爲:

  1. bootloader引導
  2. 裝載與啓動Linux內核
  3. 啓動Android系統

其中啓動Android系統過程又有以下過程:

  1. 啓動Init進程
  2. 啓動Zygote
  3. 啓動SystemServer
  4. 啓動Launcher

android啓動過程圖示:
Android系統啓動過程

zygote

我們知道,Android系統是基於Linux內的。而在Linux系統中,所有的進程都是init進程的子孫進程,也就是說,所有的進程都是直接或者間接地由init進程fork出來的。

系統啓動的時候執行系統啓動腳本system/core/rootdir/init.rc文件,進而觸發app_process程序(system/bin/app_process,它的源代碼位於frameworks/base/cmds/app_process/app_main.cpp文件中,入口函數是main)創建Zygote進程,Zygote進程負責後續Android應用程序框架層的其它進程的創建和啓動工作。

Zygote進程最大意義是作爲一個Socket的Server端,接收着四面八方的進程創建請求。Android中所有的應用進程的創建都是通過Binder機制請求SystemServer進程,SystemServer進程發送socket消息給Zygote進程,統一由Zygote進程創建出來的。
Zygote啓動時序圖

SystemServer

SystemServer也是一個進程,而且是由zygote進程fork出來的。SystemServer主要用於開啓系統重要的一些相關服務,例如:ActivityManagerService(AMS)、PackageManagerService(PMS)、WindowManagerService(WMS)等等,是不是都很熟悉呢?所以SystemServer和Zygote重要級別可以說是平分秋色了。

什麼時候開啓SystemServer

在zygote開啓的時候,會調用ZygoteInit.main()進行初始化:

public static void main(String argv[]) {
    
     ...ignore some code...
    
    //在加載首個zygote的時候,會傳入初始化參數,一旦捕獲到參數是“start-system-server”,即可開啓fork SystemServer指令
     boolean startSystemServer = false;
     for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }
            
            ...ignore some code...
            
         //開始fork我們的SystemServer進程
     if (startSystemServer) {
                startSystemServer(abiList, socketName);
         }

     ...ignore some code...

}

接下來看一下startSystemServer具體做了什麼

/**
 * Prepare the arguments and fork for the system server process.
 */
private static boolean startSystemServer(String abiList, String socketName)
        throws MethodAndArgsCaller, RuntimeException {
    
     ...ignore some code...
    
    //上面ZygoteInit.main(String argv[])裏面的argv就是通過這種方式傳遞進來的
    /* Hardcoded command line to start the system server */
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
        "--capabilities=" + capabilities + "," + capabilities,
        "--runtime-init",
        "--nice-name=system_server",
        "com.android.server.SystemServer",
    };

    int pid;
    try {
        parsedArgs = new ZygoteConnection.Arguments(args);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        //fork SystemServer
        /* Request to fork the system server process */
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    /* For child process */
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }

        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

這個方法主要是爲了開啓SystemServer,這裏做了三件事:

  1. 準備fork SystemServer相關參數,例如SystemServer進程的進程Id和組Id均爲爲1000,進程名稱爲system_server等。
  2. fork SystemServer,如果返回pid爲0則創建成功,否者返回-1或者錯誤;
  3. 調用handleSystemServerProcess()完成SystemServer進程的初始化工作;

SystemServer進程初始化

上邊也說了SystemServer主要用於開啓系統重要的一些相關服務,例如:ActivityManagerService(AMS)、PackageManagerService(PMS)、WindowManagerService(WMS)等等,我們看一下代碼具體的內部走法:

public final class SystemServer {

    //zygote的主入口
    public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }
    
    private void run() {
        
        ...ignore some code...
        
        //創建主線程looper 在當前線程運行
        android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
        android.os.Process.setCanSelfBackground(false);
        Looper.prepareMainLooper();
        
        //加載本地系統服務庫,並進行初始化 
        System.loadLibrary("android_servers");
        nativeInit();
        
        // 創建系統上下文
        createSystemContext();
        
        //初始化SystemServiceManager對象,下面的系統服務開啓都需要調用SystemServiceManager.startService(Class<T>),這個方法通過反射來啓動對應的服務
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
        
        //開啓服務
        try {
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        }
       
        ...ignore some code...
    
    }

    //初始化系統上下文對象mSystemContext,並設置默認的主題,mSystemContext實際上是一個ContextImpl對象。調用ActivityThread.systemMain()的時候,會調用ActivityThread.attach(true),而在attach()裏面,則創建了Application對象,並調用了Application.onCreate()。
    private void createSystemContext() {
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
    }

    //在這裏開啓了幾個核心的服務,因爲這些服務之間相互依賴,所以都放在了這個方法裏面。
    private void startBootstrapServices() {
        
        ...ignore some code...
        
        //初始化ActivityManagerService
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        
        //初始化PowerManagerService,因爲其他服務需要依賴這個Service,因此需要儘快的初始化
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

        // 現在電源管理已經開啓,ActivityManagerService負責電源管理功能
        mActivityManagerService.initPowerManagement();

        // 初始化DisplayManagerService
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    
    //初始化PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
       mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
       
    //開啓消息循環
    Looper.loop();
    
    ...ignore some code...
    
    }
}

SystemServer初始化過程中主要做了以下幾個重大工作:

  1. 加載本地系統服務庫,系統底層初始化。
  2. 創建消息循環體Looper,這個就是爲什麼我們在主線程裏面不用寫Looper,就可以處理UI視圖,原來系統已經爲我們做了這件事。
  3. 創建系統級上下文,在這個過程中創建我們的主線程ActivityThread,獲取系統上下文對象mSystemContext,並設置系統默認主題。
  4. 創建SystemServiceManager對象,開啓系統服務三連——引導服務、核心服務以及其他服務。

系統級上下文和我們常用的Context是有區別的,主要是用於服務端(系統級主題和其他服務相關的引導),Context到底是個什麼玩意?我在前邊的一篇文章中也有總結,這裏在闡述一遍,Context英文原意是上下文的意思,在平時開發中涉及到的四大組件及資源操作基本上都離不開Context對象。

服務三連開發者我們最關心的就是引導服務,因爲這裏面開啓的都是我們在日常開發中最容易用到的幾個服務:

  1. ActivityManagerService AMS在Android系統中扮演很重要的角色,主要負責系統中四大組件的啓動、切換、調度及應用進程的管理和調度等工作,其職責與操作系統中的進程管理和調度模塊相類似。
  2. PowerManagerService PowerManagerService主要服務Android系統電源管理工作,這樣講比較籠統,就具體細節上大致可以認爲PowerManagerService集中處理用戶活動(如點擊屏幕,按電源鍵等)、電量變化、用戶設置(如在Setting中設置省電模式,飛行模式)、插拔充電器(無線衝,有線衝)等。當發生以上事件時,PowerManagerService都要進行各種狀態的更新。
  3. DisplayManagerService DisplayManagerService用來管理顯示的生命週期,它決定如何根據當前連接的物理顯示設備控制其邏輯顯示,並且在狀態更改時,向系統和應用程序發送通知等等。
  4. PackageManagerService PackageManagerService(簡稱PMS),是Android系統中核心服務之一,管理着所有跟package相關的工作,常見的比如安裝、卸載應用。
  5. UserManagerService UserManagerService的主要功能是創建和刪除用戶,以及查詢用戶信息。Android可以支持多個用戶使用系統,通常第一個在系統中註冊的用戶將默認成爲系統管理員。不同用戶的設置各不相同,並且不同用戶安裝的應用及應用數據也不相同。

Launcher

Launcher即桌面,是Android智能設備的窗口,用戶使用最頻繁的軟件之一。Launhcer是Android所有應用的入口,也提供窗口小部件等功能。

Launcher本身就是一個APP,一個提供桌面的APP,Laucher有很多和普通APP不同的地方:

  • Launcher是頂部APP,即任何應用返回後都是到Launcher,不能再繼續返回;
  • Launcher是所有應用的入口,可以管理應用;
  • Launcher是Android系統啓動後就要顯示給用戶的應用。

Launcher是由ActivityManagerService啓動的,在SystemServer.java的startOtherServices()方法裏面的調用 mActivityManagerService.systemReady()進行Launcher的啓動之旅,在systemReady方法執行過程中調了用startHomeActivityLocked方法,方法內部通過getHomeIntent拿到Launcher對應的Intent,最後調用startHomeActivity來啓動Launcher。

    boolean startHomeActivityLocked(int userId, String reason) {
        if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
                && mTopAction == null) {
            // We are running in factory test mode, but unable to find
            // the factory test app, so just sit around displaying the
            // error message and don't try to start anything.
            return false;
        }
        Intent intent = getHomeIntent();
        ActivityInfo aInfo =
            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
        if (aInfo != null) {
            intent.setComponent(new ComponentName(
                    aInfo.applicationInfo.packageName, aInfo.name));
            // Don't do this if the home app is currently being
            // instrumented.
            aInfo = new ActivityInfo(aInfo);
            aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
            ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                    aInfo.applicationInfo.uid, true);
            if (app == null || app.instrumentationClass == null) {
                intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
                mStackSupervisor.startHomeActivity(intent, aInfo, reason);
            }
        }

        return true;
    }

ActivityManagerService和PackageManagerService一樣,都是在開機時由SystemServer組件啓動,Launcher在啓動的時候會通過PackageManagerServic把系統中已經安裝好的應用程序以快捷圖標的形式展示在桌面上,這樣用戶就可以使用這些應用程序了。另外程序安裝的時候SystemServer組件會通過PackageManagerServic來安裝應用程序,應用程序安裝好了以後會以通知的形式通知launcher展示應用圖標,卸載同理。

總結

本篇簡單分析了一下系統從開機啓動到桌面展示這個過程,這裏簡單總結一下:

  1. 系統啓動時init進程會創建Zygote進程,Zygote進程負責後續Android應用程序框架層的其它進程的創建和啓動工作。
  2. Zygote進程會首先創建一個SystemServer進程,SystemServer進程負責啓動系統的關鍵服務(服務三連),例如ActivityThread、AMS、PMS等。
  3. Android中所有的應用進程的創建都是通過Binder機制請求SystemServer進程,SystemServer進程發送socket消息給Zygote進程,統一由Zygote進程創建出來的。
  4. AMS啓動Launcher程序,Launcher展示系統相關應用快捷方式。

開機啓動我們重在瞭解過程,明確知道系統幾個重要的服務,瞭解過程中雖然很枯燥但是對開發很有幫助,例如以後的插件化學習,下篇我會着重分析一下Launcher的構造以及Activity的啓動過程,加油,期待。

參考:

  • https://blog.csdn.net/luoshengyang/article/details/6768304
  • https://www.jianshu.com/p/327f583f970b
  • https://www.jianshu.com/p/6037f6fda285
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章