Android SystemServer进程启动源码

243 阅读3分钟

一、写在前面

  接上篇Android Zygote进程启动源码继续对SystemServer进程启动源码进行分析。

二、Zygote进程fork SystemServer进程

1、ZygoteInit.forkSystemServer

  如下代码位于ZygoteInit中,主要就是fork SystemServer前的一些参数准备以及fork成功之后的处理,整体理解不难。

private static Runnable forkSystemServer(String abiList, String socketName,
        ZygoteServer zygoteServer) {
//用于指定新进程应该具有的能力集合,以限制进程的权限并增强系统的安全性
    //具体的常量值定义于文件:bionic/libc/kernel/uapi/linux/capability.h中
   long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK,
            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_PTRACE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG,
            OsConstants.CAP_WAKE_ALARM,
            OsConstants.CAP_BLOCK_SUSPEND
    );
    /* Containers run without some capabilities, so drop any caps that are not available. */
    StructCapUserHeader header = new StructCapUserHeader(
            OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
    StructCapUserData[] data;
    try {
        data = Os.capget(header);
    } catch (ErrnoException ex) {
        throw new RuntimeException("Failed to capget()", ex);
    }
    capabilities &= Integer.toUnsignedLong(data[0].effective) |
            (Integer.toUnsignedLong(data[1].effective) << 32);
	
    //进程启动参数,比如uid、gid以及进程入口类等
    String[] args = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
                    + "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
            "com.android.server.SystemServer",
    };
    ZygoteArguments parsedArgs;
    int pid;
    try {
        ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
        try {
            //解析上述参数
            parsedArgs = ZygoteArguments.getInstance(commandBuffer);
        } catch (EOFException e) {
            throw new AssertionError("Unexpected argument error for forking system server", e);
        }
        commandBuffer.close();
        //启用JDWP调试
        //JDWP是一种用于远程调试Java虚拟机的协议,它可以让开发人员在运行中的应用程序中设置断点、监视变量和调试代码
        Zygote.applyDebuggerSystemProperty(parsedArgs);
        //指定应用程序进程启动时要使用的可执行文件路径
        Zygote.applyInvokeWithSystemProperty(parsedArgs);
        ......	
        //systemServer进程是否开启性能分析
        if (shouldProfileSystemServer()) {
            parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
        }
		
        //开始fork systemServer进程
        pid = Zygote.forkSystemServer(
                parsedArgs.mUid, parsedArgs.mGid,
                parsedArgs.mGids,
                parsedArgs.mRuntimeFlags,
                null,
                parsedArgs.mPermittedCapabilities,
                parsedArgs.mEffectiveCapabilities);
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
	
    //表示fork成功,并且当前处于SystemServer进程中
    if (pid == 0) {
        //首先判断当前设备是否存在两个Zygote进程,一般情况下不会出现
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        //关闭父进程zygote复制而来的LocalSocketServer
        zygoteServer.closeServerSocket();
        return handleSystemServerProcess(parsedArgs);
    }

    return null;
}

2、forkSystemServer

  如下最终调用到native层(native层相关讲解可参考:Android系统启动-SystemServer上篇)去执行子进程的fork操作。不过在调用到native之前需要停止Zygote进程中所有守护线程以及相关子线程。

  对于为什么需要停止所有子线程如下是来源于chatGpt的回答:在 fork 子进程时,子进程会继承父进程的状态,包括线程、文件描述符、内存映射等。如果 Zygote 进程是多线程的,子进程会继承多个线程的状态,这可能会导致子进程状态混乱,影响应用程序的正确运行。

static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
        int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
    //停止守护线程:HeapTaskDaemon、ReferenceQueueDaemon、FinalizerDaemon和FinalizerWatchdogDaemon
    //等待所有线程结束:读取文件proc/self/task以判断当前是否只有一个线程,如果不是则通过yield函数让出时间片等待其他线程执行结束
    ZygoteHooks.preFork();
    //调用到native层以执行子进程fork操作
    int pid = nativeForkSystemServer(
            uid, gid, gids, runtimeFlags, rlimits,
            permittedCapabilities, effectiveCapabilities);

    // Set the Java Language thread priority to the default value for new apps.、
    //设置当前线程优先级
    Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
    
    //重新启动守护线程
    ZygoteHooks.postForkCommon();
    return pid;
}

三、fork SystemServer进程成功

1、handleSystemServerProcess

  如下代码做了几件事情:设置SystemServer进程创建文件的访问权限、设置进程名、根据SystemServer所在dex文件创建ClassLoader,并最终调用到函数ZygoteInit.zygoteInit中。

private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
    //设置SystemServer进程新创建文件权限为0077,即仅仅授予文件所有者读、写以及可执行权限
    Os.umask(S_IRWXG | S_IRWXO);
    //指定当前进程名为:system_server
    if (parsedArgs.mNiceName != null) {
        Process.setArgV0(parsedArgs.mNiceName);
    }

    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    if (systemServerClasspath != null) {
        if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
            ......
            //非release版本执行
        }
    }
    //mInvokeWith对应于参数--invoke-with,但从上述分析来看启动SystemServer并没有携带该参数,因此为null
    if (parsedArgs.mInvokeWith != null) {
        String[] args = parsedArgs.mRemainingArgs;
        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.mInvokeWith,
                parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                VMRuntime.getCurrentInstructionSet(), null, args);

        throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
    } else {
        //创建对应ClassLoader
        ClassLoader cl = getOrCreateSystemServerClassLoader();
        if (cl != null) {
            Thread.currentThread().setContextClassLoader(cl);
        }

        return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                parsedArgs.mDisabledCompatChanges,
                parsedArgs.mRemainingArgs, cl);
    }

    /* should never reach here */
}

2、zygoteInit

  如下代码主要做一些进程相关的初始化工作。比如日志重定向、全局异常捕获handler设置、重置log配置以及启动Binder线程池等。

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

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
    //重定向log输出
    //将System.out和System.err日志输出重定向到Log.INFO和Log.WARN
    RuntimeInit.redirectLogStreams();
    
    //一些初始化相关动作,比如设置默认的全局异常捕获handler、时区设置、重置log配置、设置默认的HTTP User-Agent以及设置socket tag以进行流量统计
    RuntimeInit.commonInit();
    //zygote初始化,用于启动binder线程池
    ZygoteInit.nativeZygoteInit();
    //通过反射获取当前进程入口类及main函数
    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
            classLoader);
}

3、binder线程池启动

  全局搜索nativeZygoteInit,其对应native实现定义在AndroidRuntime.cpp中。代码如下:

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

  上述代码onZygoteInit函数直接通过链接点击进去发现是一个virtual函数,因此再次全局搜索onZygoteInit函数定义,最终app_main.cpp中找到其实现。代码如下:

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

4、applicationInit

  如下代码也是为了做一些初始化工作。整体代码很简单。

protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) {
    //设置SystemServer进程退出时不清理资源
    //如果为false表示需要清理资源,例如释放内存、关闭文件句柄等等,然后再退出进程
    nativeSetExitWithoutCleanup(true);
    
    //设置当前的SDK版本
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    //应用程序的兼容性限制是指针对特定版本的Android系统或者特定设备的功能限制
    //设置Android虚拟机运行时的兼容性限制,确保应用程序能够在不同的Android系统和设备上正常运行
    VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

    final Arguments args = new Arguments(argv);

    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    //通过反射查找到类com.android.server.SystemServer的main函数
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

5、findStaticMain

  如下代码就更简单了,就是通过上述创建的ClassLoader找到com.android.server.SystemServermain函数,并返回一个Runnable的子类MethodAndArgsCaller以返回到ZygoteInit.main中进行调用。

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

    try {
        //通过上述创建的Classloader查找到类com.android.server.SystemServer
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
                "Missing class when invoking static main " + className,
                ex);
    }

    Method m;
    try {
        //查找类com.android.server.SystemServer中的main函数
        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.
     */
     //返回一个Runnable的子类给到ZygoteInit的main函数进行调用
    return new MethodAndArgsCaller(m, argv);
}

6、MethodAndArgsCaller

  如下是MethodAndArgsCaller函数的定义及实现。

static class MethodAndArgsCaller implements Runnable {
    private final Method mMethod;

    private final String[] mArgs;

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

    public void run() {
        try {
            //直接通过反射调用
            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);
        }
    }
}

四、SystemServer

  后续就正式进入到SystemServer进程的执行流程,以启动Android各种系统服务。

1、main

  该函数很简单,就是创建一个SystemServer对象并调用其run函数。

public static void main(String[] args) {
    new SystemServer().run();
}

2、run

  run函数就复杂太多太多了,如下只给出启动系统服务以及loop相关代码

private void run() {
    TimingsTraceAndSlog t = new TimingsTraceAndSlog();
    ......

    // Start services.
    try {
        t.traceBegin("StartServices");
        //启动关键服务吗,比如FileIntegrityService、Installer、DeviceIdentifiersPolicyService等
        startBootstrapServices(t);
        //启动核心服务,比如SystemConfigService、BatteryService、UsageStatsService等
        startCoreServices(t);
        //启动其他服务,比如KeyChainSystemService、BinaryTransparencyService、DeviceStateManagerService等
        startOtherServices(t);
        //启动Apex相关services,ApexPackageService
        startApexServices(t);
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        t.traceEnd(); // StartServices
    }
    ......
    // Loop forever.
    //防止进程退出,因此该处无限循环
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

五、总结

  如上即为SystemServer从Zygote进程启动的源码大体流程。