android8.1启动过程(七) SystemServer

本文承接上一篇文章android8.1启动过程(六) zygote进程分析2_we1less的博客-CSDN博客

SystemServer进程主要用于创建系统服务,AMSWMSPMS都是由它来创建的


在上一篇说道启动systemserver

启动systemserver  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

if (startSystemServer) {
    Runnable r = forkSystemServer(abiList, socketName, 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;
    }
}

forkSystemServer 

private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        ...

        /* 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,1021,1023,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 */
            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);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

【1】ZygoteConnection.Arguments(args);  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java  里面的一个静态内部类 它将上述String数组中的参数传递进去

class ZygoteConnection {
    private static final String TAG = "Zygote";
    ...
    static class Arguments {
        ...
        Arguments(String args[]) throws IllegalArgumentException {
            parseArgs(args);
        }
        ...      
    }  
}

 parseArgs  传递的参数就是   

String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        };

 接下类进入循环  根据每个字符串进行参数配置  直到字符串中不存在任何匹配后跳出

parseArgs可以看出  因为参数字符串中并未出现  --preload-default  所以代码进入

remainingArgs = new String[args.length - curArg];
System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length);

arraycopyargs中剩余的参数拷贝到remainingArgs  由程序可知剩余参数为  "com.android.server.SystemServer"

private void parseArgs(String args[])
                throws IllegalArgumentException {
            int curArg = 0;

            boolean seenRuntimeArgs = false;

            for ( /* curArg */ ; curArg < args.length; curArg++) {
                String arg = args[curArg];

                if (arg.equals("--")) {
                    curArg++;
                    break;
                } else if (arg.startsWith("--setuid=")) {
                    if (uidSpecified) {
                        throw new IllegalArgumentException(
                                "Duplicate arg specified");
                    }
                    uidSpecified = true;
                    uid = Integer.parseInt(
                            arg.substring(arg.indexOf('=') + 1));
                } else if (arg.startsWith("--setgid=")) {
                    if (gidSpecified) {
                        throw new IllegalArgumentException(
                                "Duplicate arg specified");
                    }
                    gidSpecified = true;
                    gid = Integer.parseInt(
                            arg.substring(arg.indexOf('=') + 1));
                ...

                } else if (arg.equals("--preload-default")) {
                    preloadDefault = true;
                } else {
                    break;
                }
            }

            if (abiListQuery) {
                if (args.length - curArg > 0) {
                    throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
                }
            } else if (preloadPackage != null) {
                if (args.length - curArg > 0) {
                    throw new IllegalArgumentException(
                            "Unexpected arguments after --preload-package.");
                }
            } else if (!preloadDefault) {
                if (!seenRuntimeArgs) {
                    throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
                }

                remainingArgs = new String[args.length - curArg];
                System.arraycopy(args, curArg, remainingArgs, 0, remainingArgs.length);
            }
        }
    }

【2】  forkSystemServer  上一篇也讲到主要是调用fork函数进行进程复制  在子进程中返回的pid为0  因为是子进程所以不需要Zrgote的ServerSocket所以将这个关掉

if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

handleSystemServerProcess    参数为解析出来的对象

Os.getenv("SYSTEMSERVERCLASSPATH")  得出来的字符串

generic_x86_64:/ # env
...
SYSTEMSERVERCLASSPATH=/system/framework/services.jar:/system/framework/ethernet-service.jar:/system/framework/wifi-service.jar:/system/framework/com.android.location.provider.jar

 可以看到get   dalvik.vm.profilesystemserver   返回为空

127|generic_x86_64:/ # getprop dalvik.vm.profilesystemserver                   

private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
        ...

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
            performSystemServerDexOpt(systemServerClasspath);
            // Capturing profiles is only supported for debug or eng builds since selinux normally
            // prevents it.
            boolean profileSystemServer = SystemProperties.getBoolean(
                    "dalvik.vm.profilesystemserver", false);
            if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                try {
                    File profileDir = Environment.getDataProfilesDePackageDirectory(
                            Process.SYSTEM_UID, "system_server");
                    File profile = new File(profileDir, "primary.prof");
                    profile.getParentFile().mkdirs();
                    profile.createNewFile();
                    String[] codePaths = systemServerClasspath.split(":");
                    VMRuntime.registerAppInfo(profile.getPath(), codePaths);
                } catch (Exception e) {
                    Log.wtf(TAG, "Failed to set up system server profile", e);
                }
            }
        }

        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            if (systemServerClasspath != null) {
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }

            WrapperInit.execApplication(parsedArgs.invokeWith,
                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);

            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

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

        /* should never reach here */
    }

if (parsedArgs.invokeWith != null)    这块因为当初传递参数并没有  --invoke-with 选项所以为空 走else

else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            }

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

ZygoteInit.zygoteInit   AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

ZygoteInit.nativeZygoteInit();   据此分析这块是调用了native层的方法  用来启动binder线程池  这样SystemServer进程就可以使用Binder与其他进程进行通信

有关binder的可以查看这篇Binder 启动源码分析(一)_we1less的博客-CSDN博客

nativeZygoteInit   是一个native方法所以应该找到它的jni文件  AOSP/frameworks/base/core/jni/AndroidRuntime.cpp

int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
            (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
        methods, NELEM(methods));
}

这里面存在JNINativeMethod的对应函数映射表,可以直到这块调用了com_android_internal_os_ZygoteInit_nativeZygoteInit

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

这块的gCurRuntime 是一个AndroidRuntime类型的指针  实际上最终调用的是它的子类AppRuntime (  class AppRuntime : public AndroidRuntime  ) 它在app_main.cpp中定义  

onZygoteInit   AOSP/frameworks/base/cmds/app_process/app_main.cpp

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

proc->startThreadPool();  用来启动一个Binder线程池这样SystemServer进程就可以与其他进程进行通信了  看到这里我们知道ZygoteInit.nativeZygoteInit()主要是用来启动Binder线程池的


再回到AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java  继续分析

        这个传递链条要从  说起

        forkSystemServer

        parsedArgs = new ZygoteConnection.Arguments(args);      --->    remainingArgs = new String[args.length - curArg];

        return handleSystemServerProcess(parsedArgs);

        handleSystemServerProcess

        return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);

        这里面的parsedArgs.remainingArgs就是

       "com.android.server.SystemServer"

RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader)

applicationInit   AOSP/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java     argv = "com.android.server.SystemServer"

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        ...

        // Remaining arguments are passed to the start class's static main
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

这里的  args.startClass    这里的 args.startClass  是由这句话封装而来的
Arguments args = new Arguments(argv);

Arguments(String args[]) throws IllegalArgumentException {
            parseArgs(args);
        }

parseArgs(args) 

private void parseArgs(String args[])
                throws IllegalArgumentException {
            int curArg = 0;
            for (; curArg < args.length; curArg++) {
                String arg = args[curArg];

                if (arg.equals("--")) {
                    curArg++;
                    break;
                } else if (!arg.startsWith("--")) {
                    break;
                }
            }

            if (curArg == args.length) {
                throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
            }

            startClass = args[curArg++];
            startArgs = new String[args.length - curArg];
            System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
        }

最后startClass就为"com.android.server.SystemServer"

findStaticMain   没什么好说的这里面就是根据传递进来的参数进行反射调用main函数

private static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;

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

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

        /*
         * 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.
         */
        return new MethodAndArgsCaller(m, argv);
    }

这里的run方法里面就是反射调用 

static class MethodAndArgsCaller implements Runnable {
        ...

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            ...
        }
    }

这里就可以一直返回到

启动systemserver  AOSP/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

就是本文开头的那部分代码调用了run方法就调用到了"com.android.server.SystemServer"的main方法

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值