Android source code analysis directory

(Note: The following code analysis is based on Android-10.0.0_R30)

An overview of

Zygote is a Zygote process that starts with an RC file

system/core/rootdir/init.rc
system/core/rootdir/init.zygote64_32.rc
frameworks/base/cmds/app_process/Android.bp
frameworks/base/cmds/app_process/app_main.cpp
frameworks/base/core/jni/AndroidRuntime.cpp
system/core/libutils/include/utils/misc.h
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/Zygote.java
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
Copy the code

Two rc file analysis

2.1 the init. Rc

At the end of init, the RC file is parsed

[init.rc]

import /init.${ro.zygote}.rc
Copy the code

Because there are 32-bit and 64-bit processors, and there is 64-bit compatibility with 32-bit, there are four files for zygote.rc

  • init.zygote32.rc
  • init.zygote32_64.rc
  • init.zygote64.rc
  • init.zygote64_32.rc

Of course, the one we use most often is init.zygote64_32.rc

2.2 the init. Zygote64_32. Rc

[init.zygote64_32.rc]

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary 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
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote_secondary stream 660 root system
    socket usap_pool_secondary stream 660 root system
    onrestart restart zygote
    writepid /dev/cpuset/foreground/tasks
Copy the code

There was a brief introduction about AIL in the previous article. For details, please refer to the official documents

Start a zygote service with /system/bin/app_process64 and –zygote –start-system-server –socket-name=zygote

2.3 the Android. Bp

The zygote entry function is main in app_main. CPP, so how can app_process64 relate to app_main. CPP

In earlier versions of Android (prior to 7.0), android.mk was used as configuration information to compile the source code, but starting with Android 7.0, android.bp was introduced to replace the previous Android.mk

[Android.bp]

cc_binary {
    name: "app_process",

    srcs: ["app_main.cpp"],

    multilib: {
        lib32: {
            // TODO(b/142944043): Remove version script when libsigchain is a DSO.
            version_script: "version-script32.txt",
            suffix: "32",
        },
        lib64: {
            // TODO(b/142944043): Remove version script when libsigchain is a DSO.
            version_script: "version-script64.txt",
            suffix: "64",
        },
    },
    ...
    }
Copy the code

So, the previous app_process will end up in the app_main.cpp class

Three app_main. CPP

3.1 the main function

From the previously parsed rc file, the main method in app_main. CPP is executed and the corresponding parameters are passed: –zygote –start-system-server –socket-name=zygote

As for the main function, although it is quite long, the logic inside is relatively simple, which is to parse some parameters, and then call the corresponding Zygoteinit. Java corresponding Java world

[app_main.cpp]

--zygote --start-system-server --socket-name=zygote int main(int argc, char* const argv[]) {// Print if (! LOG_NDEBUG) { String8 argv_String; for (int i = 0; i < argc; ++i) { argv_String.append("\""); argv_String.append(argv[i]); argv_String.append("\" "); } ALOGV("app_process main with argv: %s", argv_String.string()); } // Create an AppRuntime object AppRuntime Runtime (argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++; const char* spaced_commands[] = { "-cp", "-classpath" }; // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s). bool known_command = false; int i; for (i = 0; i < argc; i++) { if (known_command == true) { runtime.addOption(strdup(argv[i])); // The static analyzer gets upset that we don't ever free the above // string. Since the allocation is from main, leaking it doesn't seem // problematic. NOLINTNEXTLINE ALOGV("app_process main add known option '%s'", argv[i]); known_command = false; continue; } for (int j = 0; j < static_cast<int>(sizeof(spaced_commands) / sizeof(spaced_commands[0])); If (STRCMP (argv[I], spaced_commands[j]) == 0) {known_command = true; ALOGV("app_process main found known command '%s'", argv[i]); If (argv[I][0]!) {if (argv[I][0]! = '-') { break; } if (argv[i][1] == '-' && argv[i][2] == 0) { ++i; // Skip --. break; } runtime.addOption(strdup(argv[i])); // The static analyzer gets upset that we don't ever free the above // string. Since the allocation is from main, leaking it doesn't seem // problematic. NOLINTNEXTLINE ALOGV("app_process main add option '%s'", argv[i]); } bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className; --zygote --start-system-server --socket-name=zygote ++ 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) ! Classname.setto (arg); break; } else { --i; break; } } Vector<String8> args; if (! Classname.isempty ()) {// If className is not empty, zygote args.add(application? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); if (! LOG_NDEBUG) { String8 restOfArgs; char* const* argv_new = argv + i; int argc_new = argc - i; for (int k = 0; k < argc_new; ++k) { restOfArgs.append("\""); restOfArgs.append(argv_new[k]); restOfArgs.append("\" "); } ALOGV("Class name = %s, args = %s", className.string(), restOfArgs.string()); }} else {// start zygote // create Dalvik cache maybeCreateDalvikCache(); If (startSystemServer) {args.add(String8("start-system-server")); } // Set the corresponding ABI information char prop[PROP_VALUE_MAX]; if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) { LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY); return 11; } String8 abiFlag("--abi-list="); abiFlag.append(prop); args.add(abiFlag); // In zygote mode, pass all remaining arguments to the zygote // main() method. for (; i < argc; ++i) { args.add(String8(argv[i])); ZYGOTE_NICE_NAME if (! niceName.isEmpty()) { runtime.setArgv0(niceName.string(), true /* setProcName */); } / / if the zygote if (zygote) {runtime. Start (" com. Android. Internal. OS. ZygoteInit ", args, zygote); } else if (className) {/ / if not zygote runtime. The 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."); }}Copy the code

So, how do we get from the native world to the Java world, so we need to talk about this class AppRuntime

3.2 AndroidRuntime

The AppRuntime class, which inherits from AndroidRuntime, is a class defined in the app_main. CPP function. When you execute the start method, the start method in AndroidRuntime is called first

There are a few things you do with this start method

  1. Start the Java VM
  2. Register jNI methods
  3. Call ZygoteInit into a Java class

[AndroidRuntime.cpp]

/ / the className is com. The android. Internal. OS. ZygoteInit,  void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { static const String8 startSystemServer("start-system-server"); // Whether this is the primary zygote, meaning the zygote which will fork system server. bool primary_zygote = false; /* * 'startSystemServer == true' means runtime is obsolete and not run from * init.rc anymore, so we print out the boot start event here. */ for (size_t i = 0; i < options.size(); ++i) { if (options[i] == startSystemServer) { primary_zygote = true; /* track our progress through the boot sequence */ const int LOG_BOOT_PROGRESS_START = 3000; LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); ANDROID_ROOT const char* rootDir = getenv("ANDROID_ROOT"); If (rootDir == NULL) {// Add a rootDir = "/system" if there is no ANDROID_ROOT in the environment variable; if (! hasDir("/system")) { LOG_FATAL("No root directory specified, and /system does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); } const char* artRootDir = getenv("ANDROID_ART_ROOT"); if (artRootDir == NULL) { LOG_FATAL("No ART directory specified with ANDROID_ART_ROOT environment variable."); return; } const char* i18nRootDir = getenv("ANDROID_I18N_ROOT"); if (i18nRootDir == NULL) { LOG_FATAL("No runtime directory specified with ANDROID_I18N_ROOT environment variable."); return; } const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT"); if (tzdataRootDir == NULL) { LOG_FATAL("No tz data directory specified with ANDROID_TZDATA_ROOT environment variable.");  return; } //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack); // Start the Java INVOCATION jni_Invocation; jni_invocation.Init(NULL); // Create a pointer to JNIEnv and start the Java virtual machine JNIEnv* env; if (startVm(&mJavaVM, &env, zygote, primary_zygote) ! = 0) { return; } // Call the virtual machine created callback onVmCreated(env); // Register jNI function if (startReg(env) < 0) {ALOGE("Unable to register all Android natives\n"); return; } // create the corresponding Java parameter, convert the C layer parameter to the Java layer parameter jClass stringClass; jobjectArray strArray; jstring classNameStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass ! = NULL); strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); assert(strArray ! = NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr ! = NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); for (size_t i = 0; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert(optionsStr ! = NULL); env->SetObjectArrayElement(strArray, i + 1, optionsStr); ZygoteInit char* slashClassName = toSlashClassName(className! = NULL ? className : ""); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { 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 { env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } free(slashClassName); ALOGD("Shutting down VM\n"); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n"); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly\n"); }Copy the code

3.3 Registration of JNI functions

StartReg (env) is used to register jNI functions

[AndroidRuntime.cpp]

/*static*/ int AndroidRuntime::startReg(JNIEnv* env) { ATRACE_NAME("RegisterAndroidNatives"); androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); ALOGV("--- registering native functions ---\n"); env->PushLocalFrame(200); If (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); return 0; } static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env) { for (size_t i = 0; i < count; i++) { if (array[i].mProc(env) < 0) { #ifndef NDEBUG ALOGD("----------!!! %s failed to load\n", array[i].mName); #endif return -1; } } return 0; }Copy the code

[misc.h]

#ifndef NELEM
# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
#endif
Copy the code

Register_jni_procs (gRegJNI, NELEM(gRegJNI), env) is the logic of registration. It passes two arguments, one is gRegJNI, which is an array, and the other is the length of the array

With regard to gRegJNI, its specific definition is as follows

[AndroidRuntime.cpp]

static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), ... } int register_com_android_internal_os_RuntimeInit(JNIEnv* env) { const JNINativeMethod methods[] = { {"nativeFinishInit", "()V", (void*)com_android_internal_os_RuntimeInit_nativeFinishInit}, {"nativeSetExitWithoutCleanup", "(Z)V", (void*)com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup}, }; / / process dynamically register return jniRegisterNativeMethods (env, "com/android/internal/OS/RuntimeInit", the methods, NELEM (the methods)); } #ifdef NDEBUG #define REG_JNI(name) { name } struct RegJNIRec { int (*mProc)(JNIEnv*); }; #else #define REG_JNI(name) { name, #name } struct RegJNIRec { int (*mProc)(JNIEnv*); const char* mName; }; #endifCopy the code

Because the array is very long, we are only taking the fragment here. From this we can see that register_jni_procs is actually passing in an array of RegJNIRec and its length. This structure has a function pointer inside it, Register_jni_procs processes this structure by repeatedly calling functions in the structure, the end of which is the dynamic registration we use in JNI

Four ZygoteInit. Java

After a series of logic in the native layer, we finally get to the relevant logic in the Java world, starting with the main function in the ZygoteInit class, which was passed as a parameter

[ZygoteInit.java]

ZygoteServer = null; ZygoteServer = null; ZygoteServer = null; / / enable NoThread, make sure there are no other threads run, because the Zygote must ensure that the single thread ZygoteHooks. StartZygoteNoThreadCreation (); // Set Zygote pid try {os.setpgid (0, 0); } catch (ErrnoException ex) {throw new RuntimeException("Failed to setpgid(0,0)", ex); } // define a Runnable Runnable caller; try { // Report Zygote start time to tron unless it is a runtime restart if (!" 1".equals(SystemProperties.get("sys.boot_completed"))) { MetricsLogger.histogram(null, "boot_zygote_init", (int) SystemClock.elapsedRealtime()); } String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); / / enable Trace: ZygoteInit bootTimingsTraceLog. TraceBegin (" ZygoteInit "); RuntimeInit.preForkInit(); Boolean startSystemServer = false; String zygoteSocketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; For (int I = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = 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)) { zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME); if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } // if lazy loading is not enabled EnableLazyPreload) {/ / enable TraceLog: ZygotePreload bootTimingsTraceLog. TraceBegin (" ZygotePreload "); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); // Preload preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); / / stop TraceLog: ZygotePreload bootTimingsTraceLog. TraceEnd (); // ZygotePreload} // Do an initial gc to clean up after startup PostZygoteInitGC bootTimingsTraceLog.traceBegin("PostZygoteInitGC"); gcAndFinalize(); / / stop TraceLog: PostZygoteInitGC bootTimingsTraceLog. TraceEnd (); / / PostZygoteInitGC / / stop TraceLog: ZygoteInit bootTimingsTraceLog. TraceEnd (); // ZygoteInit Zygote.initNativeState(isPrimaryZygote); / / stop NoThread ZygoteHooks. StopZygoteNoThreadCreation (); ZygoteServer = new ZygoteServer(isPrimaryZygote); // If it is startSystemServer, If (startSystemServer) {// Start forkSystemServer [4.2] Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); // {@code r == null} in the parent (zygote) process, and {@code r ! = null} in the // child (system_server) process. if (r ! = null) { r.run(); return; } } Log.i(TAG, "Accepting command socket connections"); A more important method in / / zygoteServer caller = zygoteServer. RunSelectLoop (abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { if (zygoteServer ! = null) { zygoteServer.closeServerSocket(); } } // command. if (caller ! = null) {// start loop caller.run(); }}Copy the code

4.1 Zygote preloading

[ZygoteInit.java]

static void preload(TimingsTraceLog bootTimingsTraceLog) { Log.d(TAG, "begin preload"); bootTimingsTraceLog.traceBegin("BeginPreload"); beginPreload(); bootTimingsTraceLog.traceEnd(); // BeginPreload bootTimingsTraceLog.traceBegin("PreloadClasses"); // preload class preloadClasses(); bootTimingsTraceLog.traceEnd(); // PreloadClasses bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders"); cacheNonBootClasspathClassLoaders(); bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders bootTimingsTraceLog.traceBegin("PreloadResources"); // preloadResources preloadResources(); bootTimingsTraceLog.traceEnd(); // PreloadResources Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs"); nativePreloadAppProcessHALs(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver"); maybePreloadGraphicsDriver(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); // Preload Libraries preloadSharedLibraries(); // Preload text-related preloadTextResources(); // Ask the WebViewFactory to do any initialization that must run in the zygote process, // for memory sharing purposes. WebViewFactory.prepareWebViewInZygote(); endPreload(); warmUpJcaProviders(); Log.d(TAG, "end preload"); sPreloadComplete = true; }Copy the code

Zygote system preloaded things are very many, here is a simple list of resources and Class two to illustrate

4.1.1 Preloading Resources

When we use App, we often use some resource files such as com.android.r.xx. These resource files are preloaded in Zygote. Here is a simple list

[ZygoteInit.java]

Private static void preloadResources() {final VMRuntime Runtime = final VMRuntime VMRuntime.getRuntime(); try { mResources = Resources.getSystem(); mResources.startPreloading(); if (PRELOAD_RESOURCES) { Log.i(TAG, "Preloading resources..." ); long startTime = SystemClock.uptimeMillis(); TypedArray ar = mResources.obtainTypedArray( com.android.internal.R.array.preloaded_drawables); int N = preloadDrawables(ar); ar.recycle(); Log.i(TAG, "... preloaded " + N + " resources in " + (SystemClock.uptimeMillis() - startTime) + "ms."); startTime = SystemClock.uptimeMillis(); ar = mResources.obtainTypedArray( com.android.internal.R.array.preloaded_color_state_lists); N = preloadColorStateLists(ar); ar.recycle(); . } mResources.finishPreloading(); } catch (RuntimeException e) { Log.w(TAG, "Failure preloading resources", e); }}Copy the code

4.1.2 Preloading a Class

The preloading of a Class is the loading of a Class defined in a file that is generated by the tool

private static void preloadClasses() { final VMRuntime runtime = VMRuntime.getRuntime(); InputStream is; Is = new FileInputStream(PRELOADED_CLASSES); } catch (FileNotFoundException e) { Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + "."); return; }... try { BufferedReader br = new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE); int count = 0; String line; While ((line = br.readline ())! = null) { line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line); Try {// load class class. forName(line, true, null); count++; } catch (ClassNotFoundException e) { Log.w(TAG, "Class not found for preloading: " + line); } catch (UnsatisfiedLinkError e) { Log.w(TAG, "Problem preloading " + line + ": " + e); } catch (Throwable t) { ... } Trace.traceEnd(Trace.TRACE_TAG_DALVIK); } Log.i(TAG, "... preloaded " + count + " classes in " + (SystemClock.uptimeMillis() - startTime) + "ms."); } catch (IOException e) { Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e); } finally { IoUtils.closeQuietly(is); Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadDexCaches"); // Populate the dex cache with preloaded classes, fields, and methods. runtime.preloadDexCaches(); Trace.traceEnd(Trace.TRACE_TAG_DALVIK); . // Some finishing touches}}Copy the code

4.2 Starting the SystemServer

Zygote also has an important role in starting SystemServer, which is the core process of the framework

[ZygoteInit.java]

private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer ZygoteServer) {// Long capabilities = posixCapabilitiesAsBits(...) ; . String args[] = { ... , "com.android.server.SystemServer", }; ZygoteArguments parsedArgs = null; ZygoteArguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteArguments(args); . // Call the real fork, which is a native layer method, //com_android_internal_os_Zygote_nativeForkSystemServer PID = Zygote. ForkSystemServer (parsedargs.muid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, null, parsedArgs.mPermittedCapabilities, parsedArgs.mEffectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } if (pid == 0) {// If a second Zygote is required, wait for the second socket if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName); } / / the child will inherit the parent process related resources, there needs to be closed zygoteServer. CloseServerSocket (); / / return processing SystemServer related parameters handleSystemServerProcess (parsedArgs); } return null; }Copy the code

[com_android_internal_os_Zygote.cpp]

static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) { ... Pid_t pid = ForkCommon(env, true, fds_to_close, fds_to_ignore); If (pid == 0) {// Parent process's logic SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr); } else if (pid > 0) {// gSystemServerPid = pid; . } return pid; }Copy the code

  • First of all, forkSystemServer is called in ZygoteInit and nativeForkSystemServer is called in Zygote,
  • This is a native method that has been dynamically registered in the previous init process (see init process Startup), so com_android_internal_os_Zygote_nativeForkSystemServer is called in the corresponding native layer
  • ForkCommon is then called in this method. ForkCommon encapsulates the fork and does some SIGCHLD operations
  • ForkCommon binds the Zygote process with the SystemServer process and kills the Zygote process when it receives a signal that the SystemServer process has died

The SystemServer process has already been started, but there are still a lot of details about SystemServer, which will be discussed before.

Five summarizes

Here, Zygote start process is basically complete, but about Zygote do some things there are a lot of things, such as how to communicate with AMS, how to fork the child process, Zygote loop is how to do and so on, this will need to be detailed, Android system source larger, This article can only identify some important processes to illustrate, if there are omissions or errors, welcome to add corrections