Android14 - SystemServer进程的启动与工作流程分析

SystemServer进程主要用于创建系统服务,我们比较熟知的AMS、PMS和WMS都是由它创建的。

环境参数:

  • android-14.0.0_r27
  • Ubuntu 22.04.5 LTS

在线源码网址:xrefandroid

Zygote处理SystemServer进程

Zygote进程的主要任务之一就是启动SystemServer进程,那SystemServer是如何被启动的呢?先看Zygote进程的main函数:

csharp 复制代码
@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#main
public static void main(String[] argv) {
    ZygoteServer zygoteServer = null;
    ...
    Runnable caller;
    try {
        ...
        zygoteServer = new ZygoteServer(isPrimaryZygote);
        //默认为ture,用于启动SystemServer
        if (startSystemServer) {
            //fork出SystemServer进程并启动
            //在子进程中返回Runnable对象用于在SystemServer进程中去启动执行
            //在父进程中返回null
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

            if (r != null) {
                //表示当前代码逻辑在子进程SystemServer中
                r.run();
                return;
            }
        }
        ...
    } 
    ...
}

在Zygote进程的main()函数中,通过forkSystemServer()方法去创建SystemServer进程,并在子进程中返回了一个Runnable对象。直接走进forkSystemServer()方法:

typescript 复制代码
@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#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,"
                    + "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 {
        ...
        /* Request to fork the system server process */
        //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);
    }
    /* For child process */
    //1
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
        //关闭zygote进程创建的Socket
        zygoteServer.closeServerSocket();
        return handleSystemServerProcess(parsedArgs);
    }
    return null;
}

forkSystemServer()方法中,定义了参数数组args,其中com.android.server.SystemServer非常重要;后面通过Zygote.forkSystemServer()方法fork出SystemServer进程,根据fork机制,返回来的pid为0则表示当前逻辑位于fork出来的进程。

注释1处的代码只会在SystemServer进程中运行,首先会根据判断,去启动32位的Secondary Zygote。其次因为SystemServer进程复制了Zygote进程的地址空间,所以会得到Zygote进程创建的Socket,但是这个Socket对于SystemServer进程没有用处,因此在System进程中调用closeServerSocket()方法去关闭该Socket。随后通过handleSystemServerProcess()方法去处理SystemServer进程后续的事务。

如何fork出SystemServer进程

根据前文,Zygote进程通过Zygote.forkSystemServer()方法fork出SystemServer进程,具体如下:

csharp 复制代码
@frameworks/base/core/java/com/android/internal/os/Zygote.java#forkSystemServer
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
        int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
    ZygoteHooks.preFork();

    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;
}

private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
        int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

核心点在于方法nativeForkSystemServer(),找到其对应的Native方法,位于frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

arduino 复制代码
@frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
        jlong effective_capabilities) {
  ...
  //1
  pid_t pid = zygote::ForkCommon(env, true,
                                 fds_to_close,
                                 fds_to_ignore,
                                 true);
  if (pid == 0) {
      // System server prcoess does not need data isolation so no need to
      // know pkg_data_info_list.
      SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities,
                       effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
                       false, nullptr, nullptr, /* is_top_app= */ false,
                       /* pkg_data_info_list */ nullptr,
                       /* allowlisted_data_info_list */ nullptr, false, false);
  } 
  ...
  return pid;
}

进入ForkCommon()函数

c 复制代码
@frameworks/base/core/jni/com_android_internal_os_Zygote.cpp#ForkCommon
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
                         const std::vector<int>& fds_to_close,
                         const std::vector<int>& fds_to_ignore,
                         bool is_priority_fork,
                         bool purge) {
  ...
  //fork
  pid_t pid = fork();
  ...
  return pid;
}

最终看到是通过fork()函数创建子进程,自此SystemServer进程就创建成功了。

总结:Zygote进程在Java层通过JNI定义接口调用到Native层fork()方法,创建了SystemServer进程。

上文提到通过Zygote.forkSystemServer()方法fork出SystemServer进程后,会通过handleSystemServerProcess()方法去处理SystemServer进程的后续事务:

csharp 复制代码
@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#handleSystemServerProcess
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
    ...
    if (parsedArgs.mInvokeWith != null) {
        ...
        throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
    } else {
        ...
        return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                parsedArgs.mDisabledCompatChanges,
                parsedArgs.mRemainingArgs, cl);
    }
}

继续走到ZygoteInit的静态方法zygoteInit()中去:

csharp 复制代码
@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#zygoteInit
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) {
    ...
    RuntimeInit.commonInit();
    //1.启动Binder线程池
    ZygoteInit.nativeZygoteInit();
    //返回Runnable,被调用run方法后进入SystemServer的main方法
    return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
            classLoader);
}

private static native void nativeZygoteInit();

注释1调用Native方法nativeZygoteInit(),用来启动Binder线程池。注释2用于进入SystemServer的main()方法。

启动Binder线程池

nativeZygoteInit()是一个Native方法,我们需要找到它对应的JNI文件,根据JNI的命名规则,其对应的C++方法为com_android_internal_os_ZygoteInit_nativeZygoteInit() :

typescript 复制代码
@frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntime为AndroidRunTime类型的指针,指向其子类AppRunTime,它在app_main.cpp中定义:

csharp 复制代码
@frameworks/base/cmds/app_process/app_main.cpp#onZygoteInit
virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self();
    ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool();
}

startThreadPool()方法用于启动一个Binder线程池,SystemServer进程可以通过使用Binder与其他进程进行通信。

SystemServer进程首先会去启动一个Binder线程池的,主要是方便与其他进程进程通信。

进入SystemServer的main方法

回到ZygoteInit.java#zygoteInit()方法,启动Binder线程池后,会调用RuntimeInitapplicationInit()方法,向上返回一个Runnable对象:

csharp 复制代码
@frameworks/base/core/java/com/android/internal/os/RuntimeInit.java#applicationInit
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
        String[] argv, ClassLoader classLoader) {
    ...
    // Remaining arguments are passed to the start class's static main
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

继续进入到findStaticMain()方法

php 复制代码
@frameworks/base/core/java/com/android/internal/os/RuntimeInit.java#findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
        ClassLoader classLoader) {
    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 {
        //得到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.
     */
    return new MethodAndArgsCaller(m, argv);
}

参数className为前面提到com.android.server.SystemServer,通过反射创建SystemServer对象,然后找到main函数,随后封装为一个Runnable类型的MethodAndArgsCaller对象返回,最终会返回到ZygoteInit.java的main函数中:

csharp 复制代码
@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#main
public static void main(String[] argv) {
    ...
    try {
        ...
        //默认为ture,用于启动SystemServer
        if (startSystemServer) {
            //fork出SystemServer进程并启动
            //在子进程中返回Runnable对象用于在SystemServer进程中去启动执行
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

            if (r != null) {
                //表示当前代码逻辑在子进程SystemServer中
                r.run();
                return;
            }
        }
        ...
    } 
    ...
}

调用MethodAndArgsCaller的run()方法

php 复制代码
static class MethodAndArgsCaller 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 {
            //调用传进来的方法,也就是前面的main方法
            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);
        }
    }
}

当run()方法被调用,SystemServer进程就会走到SystemServer.java的main()方法中去。

注意 :最后将SystemServer.javamain()函数调用逻辑封装成Runnable类型的MethodAndArgsCaller对象,该对象作为ZygoteInit.javaforkSytemServer()函数的返回值,在ZygoteInit.javamain()函数中调用其run()函数去启动,主要是为了让SystemServer的main()方法看起来像是SystemServer进程的入口函数。

因此SystemServer进程由Zygote进程调用本地方法fork而出,随后SystemServer首先去开启了Binder线程池,便于与其他进程通信,然后再通过反射创建SystemSever对象,随后进入SystemServe的main()方法。

解析SystemServer进程

下面来看SystemSever的main()方法:

typescript 复制代码
@frameworks/base/services/java/com/android/server/SystemServer.java#main
public static void main(String[] args) {
    new SystemServer().run();
}

直接new了一个对象后进入到run方法:

scss 复制代码
private void run() {
    try {
        ...
        //创建消息Looper
        Looper.prepareMainLooper();
        ...
        //加载动态库android_serves.so
        // Initialize native services.
        System.loadLibrary("android_servers");
        
        //初始化系统上下文
        // Initialize the system context.
        createSystemContext();
        ...
        //创建SystemServiceManager
        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext);
    }
    // Start services.
    try {
        t.traceBegin("StartServices");
        //启动引导服务
        startBootstrapServices(t);
        //启动核心服务
        startCoreServices(t);
        //启动其他服务
        startOtherServices(t);
        //启动Apex相关服务
        startApexServices(t);
    } 
    ...
    //进入loop()循环等待和处理请求
    // Loop forever.
    Looper.loop();
}

总结

SystemServer进程相关内容可以大致分为3步:

  1. Zygote进程fork出SystemServer进程
  2. SystemServer进程做一些准备工作,比如启动Binder线程池,然后再去找到执行下一步的入口,SystemServer的main函数
  3. 进入SystemServer的main函数:
    • 创建消息Looper
    • 加载动态库lib android_servers.so
    • 初始化了系统的上下文
    • 创建SystemServiceManager
    • 启动各种服务(AMS,PMS,WMS等)
相关推荐
2501_916008892 小时前
Web 前端开发常用工具推荐与团队实践分享
android·前端·ios·小程序·uni-app·iphone·webview
我科绝伦(Huanhuan Zhou)3 小时前
MySQL一键升级脚本(5.7-8.0)
android·mysql·adb
怪兽20144 小时前
Android View, SurfaceView, GLSurfaceView 的区别
android·面试
龚礼鹏5 小时前
android 图像显示框架二——流程分析
android
消失的旧时光-19435 小时前
kmp需要技能
android·设计模式·kotlin
帅得不敢出门6 小时前
Linux服务器编译android报no space left on device导致失败的定位解决
android·linux·服务器
雨白6 小时前
协程间的通信管道 —— Kotlin Channel 详解
android·kotlin
TimeFine8 小时前
kotlin协程 容易被忽视的CompletableDeferred
android
czhc11400756639 小时前
Linux1023 mysql 修改密码等
android·mysql·adb
GOATLong10 小时前
MySQL内置函数
android·数据库·c++·vscode·mysql