Android 系統啟動流程Init、Zygote、SystemService、ServiceManager

Android系統啟動流程

操作系統本身也是一個程序,只是這個程序是用來管理我們 App 應用程序的。 從系統的角度上來講,Android系統的啟動過程可以分為 bootloader 引導,裝載和啟動 linux內核,啟動Android系統。
Bootloader 相當于電腦上的Bios 他的主要作用就是初始化基本的硬件設備,建立內存空間映射,為裝載linux內核準備好運行環境,當linux內核加載完畢之后,bootloder就會從內存中清除。
Android 系統雖然也是基于 Linux 系統的,但是由于 Android 屬于移動設備,并沒有像 PC 那樣的 BIOS 程序。 取而代之的是 BootLoader (系統啟動加載器)。 它類似于 BIOS,在系統加載前,用以初始化硬件設備,建立內存空間的映像圖,為最終調用系統內核準備好環境。 在 Android 里沒有硬盤,而是 ROM,它類似于硬盤存放操作系統,用戶程序等。 ROM 跟硬盤一樣也會劃分為不同的區域,用于放置不同的程序。當 Linux 內核啟動后會初始化各種軟硬件環境,加載驅動程序,掛載根文件系統,Linux 內核加載的準備完畢后就開始加載一些特定的程序(進程)了。
具體流程,可以參考下流程圖:

[圖片上傳失敗...(image-abada2-1632755937198)]
對于純Android應用層開發來講,了解一些Android的啟動流程的知識并不會直接提高自己的代碼質量。但是作為整個Android系統的開端,這部分的流程時刻影響著應用層的方方面面。這些知識也是作為Android開發進階必須要了解的一部分。對于前面的bootloader引導也好,裝載啟動linux文件都是很底層的東西,感興趣的可以自行了解一下,我們從啟動androng系統開始分析,第一個加載的就是 init 進程。

一:init進程

我們應該都知道不管是 Java 還是 C/C++ 去運行某一個程序(進程)都是 XXX.xxx 的 main 方法作為入口,相信有很多大佬都跟我一樣,App 開發做久了漸漸就忘記了還有個 main 方法。因此我們找到 /system/core/init/Init.cpp 的 main() 方法:

int main(int argc,char ** argv){
    
    ...
    if(is_first_stage){
        //創建和掛在啟動所需要的文件目錄
        mount("tmpfs","/dev","tmpfs",MS_NOSUID,"mode=0755");
        mkdir("/dev/pts",0755);
        //創建和掛在很多...
        ...
    }
    
    ...
    //對屬性服務進行初始化
    property_init();
    
    ...
    //用于設置子進程信號處理函數(如Zygote),如果子進程異常退出,init進程會調用該函數中設定的信號處理函數來處理
    signal_handler_init();
    
    ...

    //啟動屬性服務
    start_property_service();
    
    ...
    
    //解析init.rc配置文件
    parser.ParseConfig("/init.rc");
    
}

main 方法里面有 148 行代碼(不包括子函數代碼)具體分為四個步驟:1.創建目錄,掛載分區,2.解析啟動腳本,3.啟動解析的服務,4.守護解析的服務。init.rc 文件是 Android 系統的重要配置文件,位于 /system/core/rootdir/init.rc

import /init.environ.rc
import /init.usb.rc
// 當前硬件版本的腳本
import /init.${ro.hardware}.rc
import /init.${ro.zygote}.rc
import /init.trace.rc

on early-init
...
on init
...
// 服務 服務名稱 執行文件路徑 執行參數
// 有幾個重要的服務
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
service servicemanager /system/bin/servicemanager
service surfaceflinger /system/bin/surfaceflinger
service media /system/bin/mediaserver
service installd /system/bin/installd

在處理了繁多的任務后,init進程會進行最關鍵的一部操作: 啟動Zygote
至此 init 進程已全部分析完畢,有四個步驟:1. 創建目錄,掛載分區,2. 解析啟動腳本,3. 啟動解析的服務,4. 守護解析的服務。最需要注意的是 init 創建了 zygote(創建 App 應用的服務)、servicemanager (client 與 service 通信管理的服務)、surfaceflinger(顯示渲染服務) 和 media(多媒體服務) 等 service 進程。

二:Zygote

Zygote 進程是由 init 進程通過解析 init.rc 文件而創建的。

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

對應找到 /frameworks/base/cmds/app_process/app_main.cpp 源碼文件中的 main 方法

int main(int argc, char* const argv[])
{
    // AppRuntime 繼承 AndoirdRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    // 過濾第一個參數
    argc--;
    argv++;
    ...
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    ++i;  // Skip unused "parent dir" argument.
    // 解析參數
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

    ...
    //設置進程名
    if (!niceName.isEmpty()) {
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string());
    }
    // 如果 zygote ,AndroidRuntime 執行 com.android.internal.os.ZygoteInit 
    // 看上面解析的腳本參數執行的是這里。
    if (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.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
        return 10;
    }
}

上面首先是解析參數,然后來到 /frameworks/base/core/jni/AndroidRuntime.cpp 中的 start 方法:

/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ... 
    // 創建一個虛擬機的實例
    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // JNI 方法注冊
    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    // strArray= new String[options.size() + 1];
    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    // strArray[0] = "com.android.internal.os.ZygoteInit"
    classNameStr = env->NewStringUTF(className);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    // strArray[1] = "start-system-server";
    // strArray[2] = "--abi-list=系統響應的cpu架構類型";
    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    // slashClassName = "com/android/internal/os/ZygoteInit"
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        // 獲取 ZygoteInit.java 的 main 方法
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
            // 執行 ZygoteInit.java 的 main 方法,從 Native 世界進入 Java 世界
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
    ...
}

Java 代碼是跑在 Java 虛擬機上的,而 Java 與 native 通信采用的是 JNI ,從這里我們就開始進入 Java 世界:

public static void main(String argv[]) {
    try {
        // 解析參數
        boolean startSystemServer = false;
        String socketName = "zygote";
        String abiList = null;
        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]);
            }
        }
        ...
        // 為 Zygote 注冊 socket 用于通信
        registerZygoteSocket(socketName);
        // 預加載類和資源
        preload(); 
        // 啟動 system_server
        if (startSystemServer) {
            startSystemServer(abiList, socketName);
        }
        // 進入循環模式,等待孵化進程
        runSelectLoop(abiList); 
        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        caller.run();
    } catch (RuntimeException ex) {
        closeServerSocket();
        throw ex;
    }
}

private static void registerZygoteSocket(String socketName) {
    if (sServerSocket == null) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            ...
        }

        try {
            FileDescriptor fd = new FileDescriptor();
            // 設置文件描述符
            fd.setInt$(fileDesc);
            // 創建 Socket 的本地服務端
            sServerSocket = new LocalServerSocket(fd); 
        } catch (IOException ex) {
            ...
        }
    }
}

static void preload() {
    // 預加載位于 /system/etc/preloaded-classes 文件中的類
    preloadClasses();

    // 預加載資源,包含 drawable 和 color 資源
    preloadResources();

    // 預加載 OpenGL
    preloadOpenGL();

    // 通過 System.loadLibrary() 方法,
    // 預加載 "android", "compiler_rt", "jnigraphics" 這3個共享庫
    preloadSharedLibraries();

    // 預加載 文本連接符資源
    preloadTextResources();

    // 僅用于 zygote 進程,用于內存共享的進程
    WebViewFactory.prepareWebViewInZygote();
}

private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException {
    ...
    // 設置一些參數 
    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",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };

    ZygoteConnection.Arguments parsedArgs = null;
    int pid;
    try {
        ...
        // fork 創建 system_server 進程,后面會具體分析
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    //  pid == 0 代表子進程,也就是 system_server 進程
    if (pid == 0) {
        // 執行初始化 system_server 進程
        handleSystemServerProcess(parsedArgs);
    }
    return true;
}

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    // sServerSocket 是 registerZygoteSocket 中創建的,即 zygote 進程。保存到 fds[0]
    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        // 給 pollFds 設置參數,fds.size 是 1 ,也就是說 pollFds 里面只有 sServerSocket.getFileDescriptor() 
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            // 處理輪詢狀態,當 pollFds 有事件到來則往下執行,否則阻塞在這里
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            ...
        }
        
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if (i == 0) {
                // 即fds[0],代表的是 sServerSocket,則意味著有客戶端連接請求;
                // 則創建 ZygoteConnection 對象,并添加到 fds。
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                //添加到 fds.
                fds.add(newPeer.getFileDesciptor()); 
            } else {
                // i>0,則代表通過 socket 接收來自對端的數據,并執行相應操作
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    // 處理完則從fds中移除該文件描述符
                    fds.remove(i); 
                }
            }
        }
    }
}

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        // 讀取 socket 客戶端發送過來的參數列表
        args = readArgumentList();
        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        ...
        return true;
    }
    ...

    try {
        // 將 binder 客戶端傳遞過來的參數,解析成 Arguments 對象格式
        parsedArgs = new Arguments(args);
        ...
        // fork 創建一個新的進程
        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (Exception e) {
        ...
    }

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

相信很多人都跟我一樣,剛開始看這樣的代碼有一定的難度,畢竟都是大學時期學的,不涉及底層開發的,看起來有些吃力,但是仔細閱讀之后,或者通過命名,都可以大致看得懂流程。

Zygote 進程是由 init 進程解析 init.rc 腳本創建的,其具體的執行源碼是在 App_main.main 方法,首先會創建一個虛擬機實例,然后注冊 JNI 方法,最后通過 JNI 調用進入 Java 世界來到 ZygoteInit.main 方法。在 Java 世界中我們會為 Zygote 注冊 socket 用于進程間通信,預加載一些通用的類和資源,啟動 system_server 進程,循環等待孵化創建新的進程。總結一下ZygoteInit的main方法都做了哪些事情:

1.創建了一個Server端的Socket

2.預加載類和資源

3.啟動了SystemServer進程

4.等待AMS請求創建新的應用程序進程

Zygote進程啟動后,總共做了哪幾件事:

1.創建AndroidRuntime并調用其start方法,啟動Zygote進程。

2.創建Java虛擬機并為Java虛擬機注冊JNI方法。

3.通過JNI調用ZygoteInit的main函數進入Zygote的java框架層。

4.通過registerZygoteSocket方法創建服務端Socket,并通過runSelectLoop方法等待AMS的請求來創建新的應用程序進程。

5.啟動SystemServer。

三:SystemService

Zygote 進程的啟動過程中會調用 startSystemServer 方法來啟動 SystemServer 進程:

private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException {
    ...
    // 設置一些參數 
    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",
        "--capabilities=" + capabilities + "," + capabilities,
        "--nice-name=system_server",
        "--runtime-args",
        "com.android.server.SystemServer",
    };

    ZygoteConnection.Arguments parsedArgs = null;
    int pid;
    try {
        ...
        // fork 創建 system_server 進程,后面會具體分析
        pid = Zygote.forkSystemServer(
                parsedArgs.uid, parsedArgs.gid,
                parsedArgs.gids,
                parsedArgs.debugFlags,
                null,
                parsedArgs.permittedCapabilities,
                parsedArgs.effectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }

    //  pid == 0 代表子進程,也就是 system_server 進程
    if (pid == 0) {
        // 執行初始化 system_server 進程
        handleSystemServerProcess(parsedArgs);
    }
    return true;
}

1. 啟動 SystemServer

public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
  int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
    VM_HOOKS.preFork();
    int pid = nativeForkSystemServer(uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
    // Enable tracing as soon as we enter the system_server.
    if (pid == 0) {
      Trace.setTracingEnabled(true);
    }
    VM_HOOKS.postForkCommon();
    return pid;
}

// 調用的 native 方法去創建的,nativeForkSystemServer() 方法在 AndroidRuntime.cpp 中注冊的,調用 com_android_internal_os_Zygote.cpp 中的 com_android_internal_os_Zygote_nativeForkSystemServer() 方法
native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
  JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
  jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
  jlong effectiveCapabilities) {
  // fork 創建 systemserver 進程
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
    debug_flags, rlimits, permittedCapabilities, effectiveCapabilities,
    MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,NULL, NULL);
  // pid > 0 是父進程執行的邏輯
  if (pid > 0) {
      // waitpid 等待 SystemServer 進程的退出,如果退出了重啟 zygote 進程
      if (waitpid(pid, &status, WNOHANG) == pid) {
          RuntimeAbort(env);
      }
  }
  return pid;
}

static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids, jint debug_flags, jobjectArray javaRlimits, jlong permittedCapabilities, jlong effectiveCapabilities, jint mount_external, jstring java_se_info, jstring java_se_name, bool is_system_server, jintArray fdsToClose, jstring instructionSet, jstring dataDir) {
  //設置子進程的 signal 信號處理函數
  SetSigChldHandler(); 
  // fork 子進程(SystemServer)
  pid_t pid = fork();
  if (pid == 0) {
    // 進入子進程
    ...
    // gZygoteClass = com/android/internal/os/Zygote
    // gCallPostForkChildHooks = GetStaticMethodIDOrDie(env, gZygoteClass, "callPostForkChildHooks", "(ILjava/lang/String;)V");
    // 等價于調用 Zygote.callPostForkChildHooks()
    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,is_system_server ? NULL : instructionSet);
    ...
  } else if (pid > 0) {
    // the parent process
  }
  return pid;
}

private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller {
  ...
  if (parsedArgs.invokeWith != null) {
    ...
  } else {
    ClassLoader cl = null;
    if (systemServerClasspath != null) {
      // 創建類加載器,并賦予當前線程
      cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
      Thread.currentThread().setContextClassLoader(cl);
    }
    // RuntimeInit.zygoteInit
    RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
  }
}

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
  ...
  // 通用的一些初始化
  commonInit();
  // 這個方法是 native 方法,主要是打開 binder 驅動,啟動 binder 線程,后面分析 binder 驅動的時候再詳解。
  nativeZygoteInit(); 
  // 應用初始化
  applicationInit(targetSdkVersion, argv, classLoader); 
}

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
  ...  
  final Arguments args;
  try {
    // 解析參數 Arguments
    args = new Arguments(argv); 
  } catch (IllegalArgumentException ex) {
    return;
  }
  ...
  invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
  Class<?> cl = Class.forName(className, true, classLoader);
  ...

  Method m;
  try {
    m = cl.getMethod("main", new Class[] { String[].class });
  } catch (NoSuchMethodException ex) {
    ...
  } catch (SecurityException ex) {
    ...
  }
  ...
  // 通過拋出異常,回到了 ZygoteInit.main() 
  // try{} catch (MethodAndArgsCaller caller) {caller.run();}
  throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

繞了一大圈我們發現是通過拋異常回到了 ZygoteInit.main() 方法中的 try…catch(){MethodAndArgsCaller.run() }

2. 創建 SystemServer

public static class MethodAndArgsCaller extends Exception implements Runnable {
  ...
  public void run() {
    try {
      // 根據傳遞過來的參數可知,此處通過反射機制調用的是 SystemServer.main() 方法
      mMethod.invoke(null, new Object[] { mArgs });
    } catch (IllegalAccessException ex) {
      ...
    }
}

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

  private void run() {
    // 主線程 looper
    Looper.prepareMainLooper();

    // 初始化系統上下文
    createSystemContext();

    // 創建系統服務管理
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    // 將 mSystemServiceManager 添加到本地服務的成員 sLocalServiceObjects,sLocalServiceObjects 里面是一個靜態的 map 集合
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

    //啟動各種系統服務
    try {
      // 啟動引導服務 
      startBootstrapServices(); 
      // 啟動核心服務 
      startCoreServices();
      // 啟動其他服務
      startOtherServices();     
    } catch (Throwable ex) {
      Slog.e("System", "************ Failure starting system services", ex);
      throw ex;
    }

    // 一直循環執行
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
  }

  private void createSystemContext() {
    // 創建系統進程的上下文信息,這個在進程啟動再詳解
    ActivityThread activityThread = ActivityThread.systemMain();
    mSystemContext = activityThread.getSystemContext();
    ...
  }

  private void startBootstrapServices() {
    // 阻塞等待與 installd 建立 socket 通道
    Installer installer = mSystemServiceManager.startService(Installer.class);

    // 啟動服務 ActivityManagerService
    mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);

    // 啟動服務 PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mPackageManager = mSystemContext.getPackageManager();

    // 設置 AMS , 把自己交給 ServiceManager. addService 去管理
    mActivityManagerService.setSystemProcess();

    ...
  }

  private void startCoreServices() {
      ...
  }

  private void startOtherServices() {
    // 啟動鬧鐘服務
    mSystemServiceManager.startService(AlarmManagerService.class); 
    // 初始化 Watchdog
    final Watchdog watchdog = Watchdog.getInstance();
    watchdog.init(context, mActivityManagerService); 
    // 輸入管理的 service
    inputManager = new InputManagerService(context);
    // WindowManagerService
    wm = WindowManagerService.main(...); 
    // InputManagerService 和 WindowManagerService 都交給 ServiceManager 管理
    ServiceManager.addService(Context.WINDOW_SERVICE, wm);
    ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
    // 啟動input
    inputManager.start(); 
    // 顯示啟動界面
    ActivityManagerNative.getDefault().showBootMessage(...); 
    // 狀態欄管理
    statusBar = new StatusBarManagerService(context, wm); 
    // JobSchedulerService
    mSystemServiceManager.startService(JobSchedulerService.class); 
    ...
    // 準備好了 wms,  pms, ams 服務
    wm.systemReady();
    mPackageManagerService.systemReady();
    mActivityManagerService.systemReady();
  }

  ...
}

我們可以看到SystemServer在啟動后,陸續啟動了各項服務,包括ActivityManagerService,PowerManagerService,PackageManagerService等等,而這些服務的父類都是SystemService。

最后總結一下SystemServer進程:

1.啟動Binder線程池

2.創建了SystemServiceManager(用于對系統服務進行創建、啟動和生命周期管理)

3.啟動了各種服務

3. 管理 SystemServer

系統服務啟動后都會交給 ServiceManager 來管理,無論是 mSystemServiceManager.startService 還是 ServiceManager.addService 都是走的 ServiceManager.addService() 方法:

public static void addService(String name, IBinder service) {
  try {
    getIServiceManager().addService(name, service, false);
  } catch (RemoteException e) {
    Log.e(TAG, "error in addService", e);
  }
}

private static IServiceManager getIServiceManager() {
  if (sServiceManager != null) {
    return sServiceManager;
  }
  sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
  return sServiceManager;
}

public abstract class ServiceManagerNative extends Binder implements IServiceManager {
  static public IServiceManager asInterface(IBinder obj)  {
    if (obj == null) {
      return null;
    }
    IServiceManager in =(IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
      return in;
    }
    // 創建 ServiceManagerProxy 對象 
    return new ServiceManagerProxy(obj);
  }
}

class ServiceManagerProxy implements IServiceManager {
    private IBinder mRemote;
    
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    ...
    // IPC binder 驅動
    public void addService(String name, IBinder service, boolean allowIsolated)
           throws RemoteException {
      Parcel data = Parcel.obtain();
      Parcel reply = Parcel.obtain();
      data.writeInterfaceToken(IServiceManager.descriptor);
      data.writeString(name);
      data.writeStrongBinder(service);
      data.writeInt(allowIsolated ? 1 : 0);
      // mRemote 是 IBinder 對象
      mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
      reply.recycle();
      data.recycle();
    }
}

最后我們再來總結一下:SystemServer 進程是由 Zygote 進程 fork 創建的,SystemServer 進程創建后會創建啟動引導服務、核心服務和其他服務,并且將所創建的服務,通過跨進程通信交給 ServiceManager 進程來管理。

哈哈,看完這么多,是不是感覺有點了解,然后又不是特別了解,有一定的了解,就會想去深入了解,花點時間,慢慢去消化,主體流程了解,具體的底層實現,有興趣可以多了解。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內容