Source code analysis system server

Keywords: Android Java

I. overview

When Android starts, it will involve many system level services, such as activity manager service (AMS), package manager service (PMS), etc. when are they started?

Concepts to know:

Start process of SystemServer: zygoteinit - > SystemServer

2, System server startup sequence diagram

To be supplemented

3, Source code analysis of system server startup

Class ZygoteInit

public static void main(String argv[]) {
    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();

    try {
        // ... omit large code
        // Zygote process unmounts root storage spaces.
        Zygote.nativeUnmountStorageOnInit();

        // Open SystemServer here
        if (startSystemServer) {
            startSystemServer(abiList, socketName);
        }
        // ... omit large code
    } catch (MethodAndArgsCaller caller) {
        caller.run();// Let's pay attention here
    } catch (Throwable ex) {
        throw ex;
    }
}

/**
* Prepare the arguments and fork for the system server process.
 */
private static boolean startSystemServer(String abiList, String socketName)
        throws MethodAndArgsCaller, RuntimeException {
    // ... omit code

    /* Hardcoded command line to start the system server */
    // Parameters required to start SystemService
    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);
        ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
        ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

        /* Request to fork the system server process */
        // Zygote starts system server through 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);
    }

    /* For child process */
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        // Method of executing system server process
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

/**
 * Finish remaining work for the newly forked system server process.
 */
private static void handleSystemServerProcess(
        ZygoteConnection.Arguments parsedArgs)
        throws ZygoteInit.MethodAndArgsCaller {

    // ... omit code

    if (parsedArgs.niceName != null) {
        // niceName = system_server
        Process.setArgV0(parsedArgs.niceName);
    }
    // Get the path to the SystemServer class
    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    if (systemServerClasspath != null) {
        performSystemServerDexOpt(systemServerClasspath);
    }

    if (parsedArgs.invokeWith != null) {
        // ... omit code
    } else {
        // ... omit code

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

Class RuntimeInit

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    // Transfer the output of Java System.out and System.err to Android log system
    redirectLogStreams();

    commonInit(); //General initialization
    nativeZygoteInit(); //Initialization of native layer
    // 
    applicationInit(targetSdkVersion, argv, classLoader);
}

/**
 * Redirect System.out and System.err to the Android log.
 */
public static void redirectLogStreams() {
    System.out.close();
    System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
    System.err.close();
    System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
}

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
    // ... omit large code

    // Start the main method of the specified class (startClass is the class name of the class to start)
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

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

    try {
        // 1. Get the class object according to the class name
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }

    Method m;
    try {
        // 2. Declare the main method
        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);
    }
    // 3. Verify whether the modifier of main method is public static;
    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    }

    /* 
     * After all the above are satisfied, an exception is thrown, which is caught in ZygoteInit.main(),
     * This is what we need to pay attention to. Execute the caller.run() method where the exception is caught;
     */
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

Class methodandargscaler

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() {
        try {
            // mMethod is the SystemServer.main() method;
            mMethod.invoke(null, new Object[] { mArgs });
        } 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 new RuntimeException(ex);
        }
    }
}

4, System server source code analysis

/**
 * The main entry point from zygote.
 */
public static void main(String[] args) {
    new SystemServer().run();
}

private void run() {
    //Set the runtime path of the current virtual machine
    SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());

    // Create a Looper object for the main thread here;
    Looper.prepareMainLooper();

    /* 
     * Initialize native services.
     * This is often used in adding. so libraries;
     */ 
    System.loadLibrary("android_servers");

    /*
     * Initialize the system context.
     * 1.The Context(ContextImpl instance) of the system will be created here
     * 2.Call ActivityThread.systemMain() to generate an activitythread instance in the system process, and associate activitythread with Context;
     */
    createSystemContext();

    /*
     * Create the system service manager.
     * Create a Manager of system services, which contains list < SystemService > mservices for storing open systemservices;
     */
    mSystemServiceManager = new SystemServiceManager(mSystemContext);

    /*
     * Add the system service manager created above to the local services,
     * LocalServices An arraymap < class <? > and Object > slocalserviceobjects are held in;
     * 
     * That is, a local service can correspond to a system service manager,
     * A system service manager stores multiple system services;
     */
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

    // Services required to start the system
    try {
        // Analyze this method, similar below;
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
    } catch (Throwable ex) {
        throw ex;
    }

    //Open the Looper loop to get the messages in the message queue;
    Looper.loop();
}

private void startBootstrapServices() {
    Installer installer = mSystemServiceManager.startService(Installer.class);

    // Create an ActivityManagerService(AMS) instance
    mActivityManagerService = mSystemServiceManager.startService(
            ActivityManagerService.Lifecycle.class).getService();

    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    // Display manager is needed to provide display metrics before package manager starts up.
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

    // Create PackageManagerService instance
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

    // Set instance for application process and start
    mActivityManagerService.setSystemProcess();

    // To create a sensor service, it depends on PMS, ops service and permissions service, so it can only be created after they are initialized;
    startSensorService();
}

Posted by akillez on Fri, 03 Apr 2020 11:53:41 -0700