Android system boot series

  1. The Android system starts the —-init process
  2. Android system start series —-Zygote process

The introduction

The Android system startup series —-init process, a general analysis of the init process startup process. The Zygote process is started by app_process using JNI to call ZygoteInit’s main method. This article will analyze what the Zygote process has done for us. (System source code analysis based on Android 6.0.1)


Zygote function

First take a look at the main method of ZygoteInit all did what (/ frameworks/base/core/Java/com/android/internal/OS/ZygoteInit. Java)

public static void main(String argv[]) {
        try {
            RuntimeInit.enableDdms();
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            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]); }}if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            registerZygoteSocket(socketName);		//  1
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload();			//  2
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());

            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // Do an initial gc to clean up after startup
            gcAndFinalize();

            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false);

            if (startSystemServer) {
                startSystemServer(abiList, socketName);	  //  3
            }

            Log.i(TAG, "Accepting command socket connections");
            runSelectLoop(abiList);   //  4

            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
            caller.run();   //  5
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throwex; }}Copy the code
  1. Note 1: Register the server for socket communication
  2. Note 2: Preloading
  3. Note 3: Start the SystemServer service
  4. Note 4: Loop waiting for socket client connection requests (such as starting a new app, etc.)
  5. Note 5: Execute the main method of the requestor running the socket client

RegisterZygoteSocket Server for socket communication

To register a socketServer named “zygote” :

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) {
                throw new RuntimeException(fullSocketName + " unset or invalid", ex);
            }

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc);
                sServerSocket = new LocalServerSocket(fd);  / / 1
            } catch (IOException ex) {
                throw new RuntimeException(
                        "Error binding to local socket '" + fileDesc + "'", ex); }}}Copy the code

Note 1: Create a ServerSocket static object

Preload (preload)

static void preload(a) {
        Log.d(TAG, "begin preload");
        preloadClasses();				// Preload some bytecode class file classes
        preloadResources();			  // Preload some resources
        preloadOpenGL();			    // Preloads OpenGL display information
        preloadSharedLibraries();	 // Preload dynamic shared so libraries, such as Android, Jnigraphics, etc
        preloadTextResources();		//   
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        WebViewFactory.prepareWebViewInZygote();
        Log.d(TAG, "end preload");
    }
Copy the code

Start the SystemServer system service

/** * Prepare the arguments and fork for the system server process. */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {.../* Hardcoded command line to start the system server */
		/ / / / / / / / / / / / / / / / / / / / / / 1
        String args[] = {
            "--setuid=1000"."--setgid=1000"."-- setgroups = 1001100 2100 3100 4100 5100 6100 7100 8100 9101 0101 8102 1103 2300 1300 2300 3300 6300 7"."--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);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
			/ / / / / / / / / / / / / / / / / / / / / / 2
            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);
            }
			/ / / / / / / / / / / / / / / / / / / / / / 3
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }
Copy the code

A. Note 1: Set some parameters to start systemServer B. Note 2: Fork a process called system_server based on the argument

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;
    }
Copy the code

The nativeForkSystemServer method is a native method that forks a SystemServer process.

C. note 3: when 2 pid = 0, said in an if statement execution, in the process of SystemServer startup com. Android. Server SystemServer class the main method.

private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {...if(parsedArgs.invokeWith ! =null) { String[] args = parsedArgs.remainingArgs; . WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, VMRuntime.getCurrentInstructionSet(),null, args);
        } else {
            ClassLoader cl = null;
            if(systemServerClasspath ! =null) {
                cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
                Thread.currentThread().setContextClassLoader(cl);
            }

            /* * Pass the remaining arguments to SystemServer. */
			 / / / / / / / / / / / / / / / / / / / / / / / / / / / / 1RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); }}Copy the code

Note 1, pass some SystemServer parameters to the runtimeinit.zygoteinit method. Let’s look at the runtimeinit.zygoteinit method:

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {... nativeZygoteInit();/ / / / / / / / / / / / / / / / / / / 1
        applicationInit(targetSdkVersion, argv, classLoader);     / / / / / / / / / / / / / / / / / / / / / / / / / 2
    }
Copy the code
  • Note 1: native to do some initialization, to have a look, in corresponding to native methods/frameworks/base/core/jni/AndroidRuntime. In Java.

    static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
    {
    	gCurRuntime->onZygoteInit();
    }
    Copy the code

    OnZygoteInit is a virtual function, so where is the implementation class? Remember the AppRuntime class in the app_main.cpp file of app_process? Runtime.start () starts Zygote. The AppRutime class inherits AndroidRuntime and implements the onZygoteInit method.

    virtual void onZygoteInit(a)
    	{
    		sp<ProcessState> proc = ProcessState::self();
    		ALOGV("App process: starting thread pool.\n");
    		proc->startThreadPool();
    	}
    Copy the code

    Here the Proc starts a thread pool for Binder, which will be examined in more detail for cross-process communication.

  • Note 2: Java Layer initialization applicationInit()

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {...// Remaining arguments are passed to the start class's static main
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }
Copy the code

Continue with the invokeStaticMain method:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller { Class<? > cl;try {
		/ / / / / / / / / / / / / / / / / / / / / 1
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
		/ / / / / / / / / / / / / / / / / / / 2
            m = cl.getMethod("main".new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }

        / / / / / / / / / / / / / / / / / / / 3
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);
    }
Copy the code

We know all the way down into the className is com refs. Android. Server SystemServer note 1: By reflecting Class. Class.forname loading out com. Android. Server. The SystemServer SystemServer. The Class object. Note 2: Get the Method object of SystemServer’s main Method from the systemServer. class object. Note 3: finished this Method also does not have the actual through reflection to invoke SystemServer main Method, but throws ZygoteInit. MethodAndArgsCaller exception object and the Method of the main Method and parameters passed in. It’s pretty obvious that this exception class is handling it. Try…. Catch the exception message and process it. You can finally see this in the original zygoteinit.main () method.

try{... }catch (MethodAndArgsCaller caller) {
            caller.run();   //  5
        } 
Copy the code
public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run(a) {
            try {
                mMethod.invoke(null.new Object[] { mArgs });  / / / / / / / / / / / 1
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw newRuntimeException(ex); }}}Copy the code

Note 1: The mMethod object is the Method object of SystemServer’s main Method above, invoking main. SystemServer then runs the main method.

Loop waiting for socket client connection requests (such as starting a new app)

I won’t go into details here, but while(true) waiting for a request from the client.

Executes the Mehod object method passed in by the caller calling the socket client

One of the handlers here was examined in the run() method handler in the MethodAndArgsCaller class above.


conclusion

  1. Start the zygoteinit.main () function with the app_process.
  2. ServerSocket is registered first.
  3. Fork Starts the SystemServer process and starts the binder thread pool by native method, which is provided to SytemServer for cross-process communication.
  4. Wait for the connection request from the socket client

Android system boot series

  1. The Android system starts the —-init process
  2. Android system start series —-Zygote process