歡迎光臨
每天分享高質量文章

按下電源鍵後竟然發生了這一幕 —— Android 系統啟動流程分析

來自:程式亦非猿(微訊號:chengxuyifeiyuan)

作者:guanpj

連結:https://juejin.im/post/5c3832e66fb9a049e308510b

作為一名 Android 程式員,你有沒有想過:那麼複雜的 Android 系統,它是怎樣執行起來的,我們的 App 又是怎樣被 Android 系統載入後呈現在螢幕上的呢?Android 系統的啟動是一個比較複雜的過程,涉及到了一些我們沒有接觸過的知識,本文基於 Android Nougat 最新的程式碼上講述 Android 系統的啟動流程。

Bootloader —— 第一個程式

當按下電源鍵(加電)或者系統重啟(複位)的時候,引導晶片會從 ROM(這裡一般指 Flash ROM,即快閃記憶體)中預定義的位置將 Bootloader 載入到 RAM 中,接著,Bootloader 將會把 Linux 核心載入到 RAM 中並啟動。

ROM

Bootloader 是在系統核心執行之前執行的一段小程式,也是系統執行的第一個程式,它的主要作用是:

  1. 初始化 RAM(一般指記憶體)

  2. 初始化硬體裝置

  3. 載入內核和記憶體空間影像圖

  4. 跳轉到核心

init 行程 —— 1 號行程

Linux 核心啟動過程中會建立 init 行程,init 行程是使用者空間的第一個行程(pid=1),對應的可執行程式的源檔案檔案為 /system/core/init/Init.cpp,它的 main 方法如下:

int main(int argc, char** argv) {
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_main(argc, argv);
    }
    if (!strcmp(basename(argv[0]), "watchdogd")) {
        return watchdogd_main(argc, argv);
    }
    umask(0);
    add_environment("PATH", _PATH_DEFPATH);
    bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
    // 建立檔案並掛載
    if (is_first_stage) {...
    }
    ...    if (!is_first_stage) {
        // Indicate that booting is in progress to background fw loaders, etc.
        close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
        // 初始化屬性相關資源
        property_init();    }    ...
    // 啟動屬性服務
    start_property_service();
    const BuiltinFunctionMap function_map;
    Action::set_function_map(&function;_map);
    Parser& parser = Parser::GetInstance();
    parser.AddSectionParser("service",std::make_unique());
   ...   // 解析init.rc配置檔案
    parser.ParseConfig("/init.rc");
    ...   
    while (true) {
        ...
        int timeout = -1;
        epoll_event ev;
        int nr = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd, &ev;, 1, timeout));
        if (nr == -1) {
            ERROR("epoll_wait failed: %s
", strerror(errno));
        } else if (nr == 1) {
            ((void (*)()) ev.data.ptr)();
        }
    }
    return 0;
}

init 行程的職責主要有四個:

  1. 解析和執行所有 init.rc 檔案

  2. 生成裝置驅動節點

  3. 處理子行程的終結

  4. 提供屬性服務

這裡重點看第一點,init.rc 是一個配置檔案,它由 Android 初始化語言編寫,zygote 行程和 servicemanager 行程都是由 init 行程解析 init.rc 中特定的陳述句啟動的,比如,啟動 zygote 行程的程式碼格式如下:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media    writepid /dev/cpuset/foreground/tasks

事實上,在 system/core/rootdir 目錄下,有多個 init.rc 檔案,在不同的硬體環境下,相應的 init.rc 檔案會被匯入,比如在 64 位作業系統中,上面啟動 zygote 行程的程式碼是從 init.zygote64.rc 檔案中匯入的。

servicemanager 行程 —— Binder 服務的總管

我在藉助 AIDL 理解 Android Binder 機制——Binder 來龍去脈中講到“Binder 通訊模型和通訊過程”的時候提到過 ServerManager,它是 Binder IPC 的核心,是背景關係的管理者,Binder 服務端必須先向 ServerManager 註冊才能夠為客戶端提供服務,Binder 客戶端在與服務端通訊之前需要從 ServerManager 中查詢並獲取 Binder 服務端的取用。然而 ServerManager 在向 Binder 驅動申請成為背景關係管理者的時候又涉及到了 Binder IPC 過程,這時候應該怎麼處理呢?

servicemanager 行程是由 init 行程透過解析 init.rc 檔案來啟動的,對應的程式碼如下:

service servicemanager /system/bin/servicemanager
    class core
    user system
    onrestart restart healthd
    onrestart restart zygote

servicemanager 行程對應可執行程式的源檔案為 framework/native/cmds/servicemanager/service_manager.c,簡化後的程式碼如下:

int main(int argc, char **argv) {
    struct binder_state *bs;
    // 開啟binder驅動,申請 128k 位元組大小的記憶體空間
    bs = binder_open(128*1024);
    ...

    // 成為背景關係管理者
    if (binder_become_context_manager(bs)) {
        return -1;
    }

    // 驗證 selinux 許可權,判斷行程是否有權註冊或檢視指定服務
    selinux_enabled = is_selinux_enabled();
    ...
    // 進入無限迴圈,處理 client 端發來的請求 
    binder_loop(bs, svcmgr_handler);
    return 0;
}

這裡重點關註兩點,首先,在申請了一塊大小為 128k 的記憶體空間並驗證 selinux 許可權後,接著呼叫 framework/native/cmds/servicemanager/binder.c 中的 binder_become_context_manager 方法:

int binder_become_context_manager(struct binder_state *bs) {
    // 透過ioctl,傳送 BINDER_SET_CONTEXT_MGR 指令
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

然後,呼叫 binder_loop 方法進入迴圈來處理 client 發來的請求,註意第二個引數是一個方法體,用於處理各種狀態回呼:

int svcmgr_handler(...){

    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE: 
        // 獲取服務名
        s = bio_get_string16(msg, &len;); 
        // 根據名稱查詢相應服務
        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
        bio_put_ref(reply, handle);
        return 0;

    case SVC_MGR_ADD_SERVICE: 
        // 獲取服務名
        s = bio_get_string16(msg, &len;);
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
         // 註冊指定服務
        if (do_add_service(bs, s, len, handle, txn->sender_euid,
            allow_isolated, txn->sender_pid))
            return -1;
        break;
    }
}

servicemanager 行程在啟動過程的工作內容如下:

  1. 呼叫 binder_open 方法開啟 Binder 驅動,並申請分配一塊 128k 的記憶體空間

  2. 呼叫 binder_become_context_manager 方法傳送 BINDER_SET_CONTEXT_MGR 給 Binder 驅動,使自己成為背景關係管理者

  3. 驗證 selinux 許可權,判斷行程是否有註冊或檢視指定服務的許可權

  4. 呼叫 binder_loop 方法進入迴圈狀態,等待 Client 請求

  5. 根據服務名稱註冊服務·

  6. 接收 Binder 死亡通知

servicemanager

zygote 行程 —— Java 行程的始祖

透過解析 init.rc 檔案,
zygote 行程對應的可執行程式的源檔案為 frameworks/base/cmds/app_process/App_main.cpp,它的 main 方法如下:

int main(int argc, charconst argv[])
{
    ...
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    Vector args;
    if (!className.isEmpty()) {
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    } else {...
    }
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }
    if (zygote) {
        // 呼叫 AppRuntime 父類 AndroidRuntime 的 start 方法建立 zygote 行程
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr"Error: no class name or --zygote supplied.
");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

呼叫 frameworks/base/core/jni/AndroidRuntime.cpp 的 start 方法:

void AndroidRuntime::start()
{
    // 啟動 DVM
    if (startVm(&mJavaVM;, &env;, zygote) != 0) {
        return;
    }
    onVmCreated(env);
    // 註冊 JNI 方法
    if (startReg(env) 0) {
        ALOGE("Unable to register all android natives
");
        return;
    }

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    // 從 app_main 的 main 函式得知 className 為 com.android.internal.os.ZygoteInit
    classNameStr = env->NewStringUTF(className);
    .
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'
", slashClassName);
        /* keep going */
    } else {
        // 找到 ZygoteInit 的 main 函式
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'
", className);
            /* keep going */
        } else {
            // 透過 JNI 呼叫 ZygoteInit 的 main 函式
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
        }
    }
  ...
}

透過 JNI 的方式進入 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:

public static void main(String argv[]) {
    try {
        // 註冊Zygote用的Socket
        registerZygoteSocket(socketName);
        ...
        // 預載入類和資源
        preload();//2
        ...
        if (startSystemServer) {
            // 啟動SystemServer行程
            startSystemServer(abiList, socketName);
        }
        // 等待客戶端請求
        runSelectLoop(abiList);
        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {}
}

ZygoteInit.java 的 registerZygoteSocket 方法:

private static void registerZygoteSocket(String socketName) {
    if (sServerSocket == null) {
        ...
        try {
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            // 建立 Socket 客戶端
            sServerSocket = new LocalServerSocket(fd);
        } catch (IOException ex) {}
    }
}

ZygoteInit.java 的 startSystemServer 方法:

private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
    // SystemServer 啟動引數
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };
    ZygoteConnection.Arguments parsedArgs = null;

    int pid;

    try {
        parsedArgs = new ZygoteConnection.Arguments(args);
        // 呼叫 Zygote.java fock 出新執行緒,名字叫 system_server
        pid = Zygote.forkSystemServer(...);
    } catch (IllegalArgumentException ex) {
    }
    // pid 為 0 則為 fock 出來的子執行緒
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        // 啟動 SystemServer 行程
        handleSystemServerProcess(parsedArgs);
    }
   return true;
}

frameworks/base/core/java/com/android/internal/os/Zygote.java 的 forkAndSpecialize 方法:

public static int forkAndSpecialize(...) {
    VM_HOOKS.preFork();
    // 呼叫 Native 層的方法 fock 出子執行緒
    int pid = nativeForkAndSpecialize(uid, gid, gids, debugFlags, rlimits, 
                mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir);
    // Enable tracing as soon as possible for the child process.
    if (pid == 0) {// fock 出來的子執行緒中執行
        Trace.setTracingEnabled(true);
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
    }
    VM_HOOKS.postForkCommon();
    return pid;
}

ZygoteInit.java 的 runSelectLoop 方法:

private static void runSelectLoop(){
    // sServerSocket 物件就是剛才在 registerZygoteSocket 方法中建立的服務端 Socket
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    // 迴圈讀取狀態
    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        
        try {
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
...        }
        for (int i = pollFds.length - 1; i >= 0; --i) {
            // 讀取的狀態不是客戶端連線或者資料請求時,進入下一次迴圈
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {// i = 0 表示跟客戶端 Socket 連線上了
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {// i > 0 表示接收到客戶端 Socket 傳送過來的請求
                // runOnce 方法建立一個新的應用程式行程
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java 的 runOnce 方法:

boolean runOnce() {
    try {
        // 讀取 socket 客戶端傳送過來的引數串列
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        // EOF reached.
        closeSocket();
        return true;
    }
    try {
        // 將 socket 客戶端傳遞過來的引數,解析成 Arguments 物件格式
        parsedArgs = new Arguments(args);
        ...
        // 同樣呼叫 Zygote.java 的 forkAndSpecialize 方法 fock 出子行程
        pid = Zygote.forkAndSpecialize(...);
    } catch (Exception e) {
        ...
    }

    try {
        if (pid == 0) {
            // 子行程執行
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            // 進入子行程流程
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
            return true;
        } else {
            // 父行程執行
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {}
}

從 App_main 開始,zygote 啟動過程的時序圖如下:

zygote

可以看到,這個過程中 zygote 首先啟動了 AndroidRuntime 並透過它反射呼叫了 ZygoteInit.main() 方法,由此進入了 Java 的世界,因此 zygote 是 Java 層的第一個行程,也是其他 Java 行程的始祖,其他 Java 行程的建立必須依賴 zygote。

zygote 行程的任務分別是:

  1. 建立 AppRuntime(繼承自 AndroidRuntime), 並呼叫它的 start 方法

  2. 呼叫 AndroidRuntime 的 startVM() 方法建立 DVM(Dalvik Virtual Machine),並呼叫 startReg() 方法為 DVM 註冊 JNI

  3. 透過 JNI 呼叫 ZygoteInit.main() 方法,第一次進入 Java 的世界

  4. 呼叫 registerZygoteSocket() 函式建立 Socket 通道,使 zygote 行程成為 Socket 服務端,並透過 runSelectLoop() 函式等待 ActivityManagerService 傳送請求建立新的應用程式行程

  5. 呼叫 startSystemServer() 函式 fock 出 system_server 行程

system_server 行程 —— 承載 framework 層核心業務

接下來分別講解 system_server 行程的啟動過程和 system_server 行程的執行過程。

1、system_server 行程的啟動過程

在上一小節中我們已經知道,zygote 行程在啟動的過程中會透過 startSystemServer 方法 fock 出了一個叫 system_server 的行程,然後再該方法內執行了 handleSystemServerProcess 方法:

private static void handleSystemServerProcess(
          ZygoteConnection.Arguments parsedArgs)
          throws ZygoteInit.MethodAndArgsCaller {
    /** 由於 fock 出來的 system_server 行程會複製 zygote 行程的地址空間,因此它也得到了 zygote
    行程中的 Socket,這個 Socket 對它來說並無用處,這裡將其關閉 **/
    closeServerSocket();
    ...
    if (parsedArgs.invokeWith != null) {
        ...
    } else {
        ClassLoader cl = null;
        if (systemServerClasspath != null) {
            cl = createSystemServerClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
            Thread.currentThread().setContextClassLoader(cl);
        }
        // 出現新的類 RuntimeInit,呼叫了它的 zygoteInit 方法
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }
}

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java 的 zygoteInit 方法:

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
    redirectLogStreams();
    commonInit();
    /** 透過 Native 層中 AndroidRuntime.cpp 的 JNI 方法最終呼叫 app_main.cpp 的 onZygoteInit 方法
    啟動 Binder 執行緒池, 使 system_server 行程可以使用 Binder 與其他行程通訊 **/
    nativeZygoteInit();
    // 繼續往下呼叫
    applicationInit(targetSdkVersion, argv, classLoader);
}

RuntimeInit 的 applicationInit 方法:

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
    ...
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

RuntimeInit 的 invokeStaticMain 方法:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
         throws ZygoteInit.MethodAndArgsCaller {
    Class> cl;
    try {
        /** className 為 ZygoteInit.java 中 startSystemServer 方法
        傳遞過來的 "com.android.server.SystemServer",這裡透過反射得到 SystemServer 類 **/
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
            "Missing class when invoking static main " + className, ex);
    }
    Method m;
    try {
        // 找到 SystemServer 類的 main 方法
        m = cl.getMethod("main"new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
      ...}
    ...
    /** 將 main 方法包裝在 ZygoteInit.MethodAndArgsCaller 類中並作為異常丟擲
    捕獲異常的地方在上一小節中 ZygoteInit.java 的 main 方法 **/
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java 的 main 方法:

public static void main(String argv[]) {
    ...
    closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        // 接收到 caller 物件後呼叫它的 run 方法
        caller.run();
    } catch (RuntimeException ex) {
        Log.e(TAG, "Zygote died with exception", ex);
        closeServerSocket();
        throw ex;
    }
}

ZygoteInit 的 MethodAndArgsCaller 類是一個 Exception 類,同時也實現了 Runnable 介面:

public static class MethodAndArgsCaller extends Exception
        implements Runnable {

    private final Method mMethod;
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }
    public void run() {
        try {
            // 呼叫傳遞過來的 mMethod
            mMethod.invoke(nullnew Object[] { mArgs });
        }   ...
        }
    }
}

這樣,system_server 行程便啟動起來併進入了 SystemServer.java 的 main 方法。

這裡需要思考一下,為什麼需要丟擲異常到 ZygoteInit 中執行?官方解釋就是丟擲異常的時候 Android 虛擬機器會清空該行程堆記憶體中的棧幀,因此前面一系列啟動 system_server 行程的過程中方法呼叫過程就被清除了,節省了堆疊的空間,使 ZygoteInit.java 的 main 方法處於所有 Java 行程的方法棧中的棧頂。另外,從最新 Android Pie 的程式碼中看,這個過程已經變成在每一步中將包裝好的 MethodAndArgsCaller 物件作為傳回值傳回,最後在  ZygoteInit 執行物件的 call 方法,這樣每個方法都執行了傳回過程,自然在堆疊中對應的棧幀也被彈出棧了。

2、system_server 行程的執行過程

檢視 frameworks/base/services/java/com/android/server/SystemServer.java 的原始碼:

/**
 * The main entry point from zygote.
 */
public static void main(String[] args) {
    // 呼叫 run 方法
    new SystemServer().run();
}
private void run() {
    ...
    // 載入 libandroid_servers.so
    System.loadLibrary("android_servers");
    ...
    // 建立 SystemServiceManager
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
    ...    
    try {
        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
        // 啟動引導服務
        startBootstrapServices();
        // 啟動核心服務
        startCoreServices();
        // 啟動其他服務
        startOtherServices();
    } catch (Throwable ex) {
        ...
    } finally {...    }
    ...
}

可以看到,在 run 方法中,主要執行了啟動引導服務、核心服務和其他服務的任務,這些服務加起來一共有 80 多個,它們對應這個各種不同的功能,部分服務如下:

引導服務 作用
Installer 系統安裝apk時的一個服務類,啟動完成Installer服務之後才能啟動其他的系統服務
ActivityManagerService 負責四大元件的啟動、切換、排程。
PowerManagerService 計算系統中和Power相關的計算,然後決策系統應該如何反應
LightsService 管理和顯示背光LED
DisplayManagerService 用來管理所有顯示裝置
UserManagerService 多使用者樣式管理
SensorService 為系統提供各種感應器服務
PackageManagerService 用來對apk進行安裝、解析、刪除、解除安裝等等操作
核心服務 作用
BatteryService 管理電池相關的服務
UsageStatsService 收集使用者使用每一個APP的頻率、使用時常
WebViewUpdateService WebView更新服務
其他服務 作用
CameraService 攝像頭相關服務
AlarmManagerService 全域性定時器管理服務
InputManagerService 管理輸入事件
WindowManagerService 視窗管理服務
VrManagerService VR樣式管理服務
BluetoothService 藍芽管理服務
NotificationManagerService 通知管理服務
DeviceStorageMonitorService 儲存相關管理服務
LocationManagerService 定位管理服務
AudioService 音訊相關管理服務

小結

system_server 行程在啟動過程中完成的工作分別是:

  1. 啟動 Binder 執行緒池,使行程可以透過 Binder 與其他行程行程通訊

  2. 建立 SystemServiceManager

  3. 使用 SystemServiceManager 對各種系統服務進行建立、啟動和生命週期管理

Launcher —— Android 系統的“桌面”

在上一節 frameworks/base/services/java/com/android/server/SystemServer.java 的 main 方法中,有一句:

private void startOtherServices() {
    ...
    // 呼叫 AMS 的 systemReady 方法
    mActivityManagerService.systemReady(new Runnable() {
        @Override
        public void run() {
            ...
        }
    }
    ...
}

繼續跟蹤:
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java:

public void systemReady(final Runnable goingCallback) {
    ...
    synchronized (this) {
        ...
        // 呼叫 ActivityStackSupervisor 的 resumeFocusedStackTopActivityLocked 方法
        mStackSupervisor.resumeFocusedStackTopActivityLocked();
        mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
    }
}

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java:

boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target,
        ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        // 呼叫 ActivityStack 的 resumeTopActivityUncheckedLocked 方法
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    ...
    return false;
}

ActivityStack:

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    //...
    boolean result = false;
    try {
        //...
        // 呼叫 resumeTopActivityInnerLocked 方法
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        mStackSupervisor.inResumeTopActivity = false;
    }
    return result;
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
   ...
   // 回到 ActivityStackSupervisor 的 resumeHomeStackTask 方法
   return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
   ...                 
}

frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java:

boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev, String reason) {
    ...
    if (r != null && !r.finishing) {
        mService.setFocusedActivityLocked(r, myReason);
        return resumeFocusedStackTopActivityLocked(mHomeStack, prev, null);
    }
    // 再次回到 AMS 的 startHomeActivityLocked 方法
    return mService.startHomeActivityLocked(mCurrentUser, myReason);
}
boolean startHomeActivityLocked(int userId, String reason) {
    if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
            && mTopAction == null) {
        return false;
    }
    // 獲取 Intent
    Intent intent = getHomeIntent();
    ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
    if (aInfo != null) {
        intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        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);
            // 使用 mActivityStarter 啟動 app,這裡不再詳細跟蹤
            mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
        }
    } else {
            Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
    }

    return true;
}

getHomeIntent 方法:

Intent getHomeIntent() {
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        // 新增 android.intent.category.HOME
        intent.addCategory(Intent.CATEGORY_HOME);
    }
    return intent;
}

可以看到,最後透過一個隱式 Intent 使用 Intent.FLAG_ACTIVITY_NEW_TASK 樣式啟動了一個帶 Intent.CATEGORY_HOME 標簽的 Activity,而帶有 Intent.CATEGORY_HOME 標簽的 Activity 正是 Launcher App,它的 AndroidManifest 檔案如下:

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.launcher3">
    <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="16"/>

    ...

    <application
        android:allowBackup="@bool/enable_backup"
        android:backupAgent="com.android.launcher3.LauncherBackupAgentHelper"
        android:hardwareAccelerated="true"
        android:icon="@mipmap/ic_launcher_home"
        android:label="@string/app_name"
        android:largeHeap="@bool/config_largeHeap"
        android:restoreAnyVersion="true"
        android:supportsRtl="true" >
        <activity
            android:name="com.android.launcher3.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:theme="@style/Theme"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="nosensor"
            android:configChanges="keyboard|keyboardHidden|navigation"
            android:resumeWhilePausing="true"
            android:taskAffinity=""
            android:enabled="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
            intent-filter>

activity>

application>
manifest>

Launcher 啟動後會將所有已安裝的應用圖示展示在一個網格佈局的 RecyclerView 裡面,這時候使用者就可以透過點選這些圖示來啟動相應的 app 了。

整個過程的時序圖如下:

Launcher

關於 Launcher 如何將 App 圖示顯示出來等更多工作細節,可以參考Android M Launcher3主流程原始碼淺析 和 Android系統啟動流程(四)Launcher啟動過程與系統啟動流程這兩篇文章。

總結

最後,從整體上來看 Android 系統的啟動流程:

  1. 按下電源,固化在 ROM 中預定位置的 Bootloader 將會被載入到記憶體中

  2. Bootloader 初始化完軟硬體環境後將 Linux 核心啟動起來

  3. Linux 核心啟動時會做設定快取、被保護儲存器、計劃串列和載入驅動等一些列操作,核心啟動完成後會啟動 init 行程

  4. init 行程會初始化並啟動屬性服務,並且解析並執行所有 init.rc 檔案

  5. init 透過執行特定的 init.rc 檔案啟動 servermanager 行程,servermanager 被啟動後會向 Binder 驅動傳送命令讓自己成為守護行程並管理所有背景關係

  6. init 透過解析 init.rc 檔案啟動 zygote 行程

  7. zygote 行程啟動的過程會建立 DVM 併為其註冊 JNI 函式,然後建立服務端 Socket、啟動 system_server 行程

  8. 啟動 system_server 行程的過程會建立 Binder 執行緒池使其具有 IPC 能力,然後啟動 AMS 等各種系統服務

  9. AMS 啟動 Launcher,Launcher 被啟動後會將已安裝應用的圖示顯示在介面上

原來,一個複雜的 Android 系統就這麼被執行起來了,礙於本人有限的水平,描述這個過程其實也還簡化了很多操作,下麵這個圖比較全面地總結了這個流程:

android 系統啟動流程

已同步到看一看
贊(0)

分享創造快樂