Creation of Android SystemServer

Keywords: Android Java

The SystemServer process is a process that comes out of Zygote fork. Here's how the zygote process executes

frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
   // The zygote process is from the init process through fork
    AppRuntime runtime;

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");
    }
}

/frameworks/base/core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const char* options)
{
    /*
     * 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;
    jstring optionsStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(2, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    env->SetObjectArrayElement(strArray, 0, classNameStr);
    optionsStr = env->NewStringUTF(options);
    env->SetObjectArrayElement(strArray, 1, optionsStr);

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    // Get "com.android.internal.os.ZygoteInit"Class"
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
    } else {
        // main method to get ZygoteInit class
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
        } else {
            // Call main method of ZygoteInit class
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
}

Here we goCom.android.internal.Os.ZygoteInitIn the main method of.

public static void main(String argv[]) {  
    try {  
        ......  
        // Start SystemServer
        if (argv[1].equals("start-system-server")) {  
            startSystemServer();  
        }   
        ......  
    } catch (MethodAndArgsCaller caller) {  
        caller.run();  
    } catch (RuntimeException ex) {  
        ......  
    }  
} 
private static boolean startSystemServer()
        throws MethodAndArgsCaller, RuntimeException {
    long capabilities = posixCapabilitiesAsBits(
        OsConstants.CAP_KILL,
        OsConstants.CAP_NET_ADMIN,
        OsConstants.CAP_NET_BIND_SERVICE,
        OsConstants.CAP_NET_BROADCAST,
        OsConstants.CAP_NET_RAW,
        OsConstants.CAP_SYS_MODULE,
        OsConstants.CAP_SYS_NICE,
        OsConstants.CAP_SYS_RESOURCE,
        OsConstants.CAP_SYS_TIME,
        OsConstants.CAP_SYS_TTY_CONFIG
    );
    /* Hardcoded command line to start the system server */
    String args[] = {
        "--setuid=1000",
        "--setgid=1000",
        "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
        "--capabilities=" + capabilities + "," + capabilities,
        "--runtime-init",
        "--nice-name=system_server",
        "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 */
        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) {
        handleSystemServerProcess(parsedArgs);
    }

    return true;
}

The parameter to set the process is system_server, the corresponding class isCom.android.server.SystemServer.
Zygote.forkSystemServer A real fork is a process whose parameters have been set before, so the process that this fork comes out of is system_server, which is a child of zygote

Once the SystemServer process has been created, the handleSystemServerProcess method is executed below.

private static void handleSystemServerProcess(
        ZygoteConnection.Arguments parsedArgs)
        throws ZygoteInit.MethodAndArgsCaller {

    // Modify the process name to system_server  
    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }

    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                null, parsedArgs.remainingArgs);
    } else {
        //The method will eventually be called
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
    }
}

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv)
        throws ZygoteInit.MethodAndArgsCaller {
    if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

    redirectLogStreams();
    // Do some general initialization  
    commonInit();
    // Initialization of the native layer  
    nativeZygoteInit();
    // Call main method of application java layer
    applicationInit(targetSdkVersion, argv);
}
private static void applicationInit(int targetSdkVersion, String[] argv)  
            throws ZygoteInit.MethodAndArgsCaller {  
        nativeSetExitWithoutCleanup(true);  

        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);  
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);  

        final Arguments args;  
        try {  
            args = new Arguments(argv);  
        } catch (IllegalArgumentException ex) {  
            Slog.e(TAG, ex.getMessage());  
            return;  
        }  

        // Call the static main method of the class passed in
        invokeStaticMain(args.startClass, args.startArgs);  
} 
private static void invokeStaticMain(String className, String[] argv)  
            throws ZygoteInit.MethodAndArgsCaller {  
        Class<?> cl;  

        try {  
            // LoadCom.android.serverSystemServer class  
            cl = Class.forName(className);  
        } catch (ClassNotFoundException ex) {  
            throw new RuntimeException(  
                    "Missing class when invoking static main " + className,  
                    ex);  
        }  

        Method m;  
        try {  
            // Get 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);  
        }  

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

        /* 
         * This throw gets caught in ZygoteInit.main(), which responds 
         * by invoking the exception's run() method. This arrangement 
         * clears up all the stack frames that were required in setting 
         * up the process. 
         */  
        throw new ZygoteInit.MethodAndArgsCaller(m, argv);  
}  

ZygoteInit.MethodAndArgsCaller Is a class inherited from Exception, invokeStaticMain was not called directlyCom.android.serverThe main method of.SystemServer, instead, throws aZygoteInit.MethodAndArgsCalleException of type.

public static void main(String argv[]) {  
    try {  
        ......  

        if (argv[1].equals("start-system-server")) {  
            startSystemServer();  
        }   
        ......  
    } catch (MethodAndArgsCaller caller) {  
        caller.run();  
    } catch (RuntimeException ex) {  
        ......  
    }  
} 

The MethodAndArgsCaller exception is finally caught in the main function by try-catch and handled by the run function of the exception class.

public static class MethodAndArgsCaller extends Exception  
            implements Runnable {  
    /** method to call */  
    private final Method mMethod;  

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

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

        // The run function calls the main function  
    public void run() {  
            try {  
                mMethod.invoke(null, new Object[] { mArgs });  
            } catch (IllegalAccessException ex) {  
                throw new RuntimeException(ex);  
            } catch (InvocationTargetException ex) {  
                ......  
            }  
        }  
    }  
}

Reference article:
http://blog.csdn.net/hu3167343/article/details/38375167

Posted by adeelahmad on Sat, 20 Jun 2020 09:17:47 -0700