安卓13启动流程分析Android13

安卓通过bootloader加载到系统后,首先通过rc文件,启动系统服务

init.rc 复制代码
  service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
  socket zygote stream 666

rc文件中,首先启动了primary_zygote,使用app_process启动

注意:安卓中的zygote有三个称呼,分别是zygote,zygote_secondary,primary_zygote

安卓源码中,用zygote等价于primary_zygote,而zygote_secondary是另一种

primary_zygote通过fork产生system_server后,变为zygote_secondary

D:\AOSP\android-13.0.0_r9\frameworks\base\cmds\app_process\app_main.cpp

cpp 复制代码
class AppRuntime : public AndroidRuntime
{
public:
    AppRuntime(char* argBlockStart, const size_t argBlockLength)
        : AndroidRuntime(argBlockStart, argBlockLength)
        , mClass(NULL){}
    String8 mClassName;
    Vector<String8> mArgs;
    jclass mClass;
};
int main(int argc, char* const argv[])
{
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    maybeCreateDalvikCache();
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    }
}

D:\AOSP\android-13.0.0_r9\frameworks\base\core\jni\AndroidRuntime.cpp

cpp 复制代码
// 开始安卓运行时,这里会启动虚拟机,并调用className传入的java类的main方法
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
            className != NULL ? className : "(unknown)", getuid());

    static const String8 startSystemServer("start-system-server");
    // 判断是primary_zygote还是zygote
    bool primary_zygote = false;

    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    // 说实话这段注释我看的不是很懂
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
            primary_zygote = true;
           ...
        }
    }

    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        setenv("ANDROID_ROOT", rootDir, 1);
    }

    const char* artRootDir = getenv("ANDROID_ART_ROOT");
    // i18n是Internationalization,也就是国际化支持
    const char* i18nRootDir = getenv("ANDROID_I18N_ROOT");
    // tz是TimeZone,也就是时区
    const char* tzdataRootDir = getenv("ANDROID_TZDATA_ROOT");

    //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
    //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

    /* start the virtual machine */
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    onVmCreated(env);

    // 注册android的functions
    startReg(env);

    // 把class_name和option_string包装传入java的mian
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    classNameStr = env->NewStringUTF(className);
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).c_str());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    // 启动虚拟机。同时当前线程将会变成虚拟机的主线程,知道虚拟机退出时才返回。
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
        "([Ljava/lang/String;)V");
    if (startMeth == NULL) {
        ALOGE("JavaVM unable to find main() in '%s'\n", className);
        /* keep going */
    } else {
        env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }
    free(slashClassName);

    ALOGD("Shutting down VM\n");
    if (mJavaVM->DetachCurrentThread() != JNI_OK)
        ALOGW("Warning: unable to detach main thread\n");
    if (mJavaVM->DestroyJavaVM() != 0)
        ALOGW("Warning: VM did not shut down cleanly\n");
}

转到了java层

ZygoteInit

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

java 复制代码
	/**
	* 这是Zygote进程的入口,在这里会创建Zygote服务,加载资源,处理和启动应用有关的任务。
	* 这个进程将会以-20的优先级(最高)运行,因此新进程的所有路径都需要将优先级设置为默认值
	* 或者在指向任何非系统代码前终止。
	* native端在SpecializeCommon中修改,而java端在ZygoteInit.handleSystemServerProcess,
	* ZygoteConnection.handleChildProc, and Zygote.childMain.
	*/
    @UnsupportedAppUsage
    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;

        // 设置标志位,当创建java线程时,如果是zygote则不创建。
        ZygoteHooks.startZygoteNoThreadCreation();

        // 将Zygote设置到他自己的进程组
        Os.setpgid(0, 0);

        Runnable caller;
        try {
            RuntimeInit.preForkInit();
            // 这个preForkInit中做了曾经的RuntimeInit.enableDdms
            // 同时调用MimeMap.setDefaultSupplier(DefaultMimeMapFactory::create);

            boolean startSystemServer = false;
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;
                } else if ("--enable-lazy-preload".equals(argv[i])) {
                    enableLazyPreload = true;
                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
                    abiList = argv[i].substring(ABI_LIST_ARG.length());
                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
            // 懒加载模式下,不在这里加载资源和类
            if (!enableLazyPreload) {
                preload(bootTimingsTraceLog);
            }

            gcAndFinalize();

            Zygote.initNativeState(isPrimaryZygote);
            
            ZygoteHooks.stopZygoteNoThreadCreation();

            zygoteServer = new ZygoteServer(isPrimaryZygote);

            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

				// 当返回null时是父进程,返回不为null时,是system_server的入口
                if (r != null) {
                    r.run();
                    return;
                }
            }

            Log.i(TAG, "Accepting command socket connections");

            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            caller.run();
        }
    }

创建zygoteServer,分化出system_server

  • 如果是system_server,则仅调用zygoteServer.closeServerSocket();
  • 如果是zygote_secondary,则调用zygoteServer.closeServerSocket();后,调用zygoteServer.runSelectLoop(abiList);

下面先看未分化前的步骤

Zygote.initNativeState

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\Zygote.java

java 复制代码
	// 初始化Zygote的native状态,包括如下:
	// 1. 取出环境变量中的socket FDs
	// 2. 初始化安全属性
	// 3. 根据情况进行存储空间解挂载
	// 4. 加载必要的性能配置信息
    static void initNativeState(boolean isPrimary) {
        nativeInitNativeState(isPrimary);
    }

ZygoteServer

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\ZygoteServer.java

java 复制代码
/**
 * zygote进程们的socket服务类
 */
class ZygoteServer {
    private LocalServerSocket mZygoteSocket;
    /**
    * USAP(Unspecialized App Process),这是安卓10(Q)引入的机制
    * 通过prefork的方式提前创建好一批进程,当有应用启动时,直接将已经创建好的进程分配给它
    * 省去了fork的动作,因此可以提升性能
    */
    private final LocalServerSocket mUsapPoolSocket;

    ZygoteServer(boolean isPrimaryZygote) {
        // 调用nativeGetUsapPoolEventFD,将fd转为java的FileDescriptor
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

        if (isPrimaryZygote) {
            // Zygote.PRIMARY_SOCKET_NAME = "zygote"
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
            // Zygote.USAP_POOL_PRIMARY_SOCKET_NAME = "usap_pool_primary"
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
        } else {
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
            mUsapPoolSocket =
                    Zygote.createManagedSocketFromInitSocket(
                            Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
        }

        mUsapPoolSupported = true;
        fetchUsapPoolPolicyProps();
    }
}

对于Zygote.getUsapPoolEventFD

Zygote.createManagedSocketFromInitSocket
java 复制代码
	// 使用init.rc中指定的fd来创建LocalServerSocket对象
	// 在init.rc中指定的fd,他的名字可以在system/core/rootdir中找到。同时这个fd也会绑定到/dev/sockets/目录下,fd在值会以ANDROID_SOCKET_<socketName>形式共享到环境变量中。
    static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
        int fileDesc;
        final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;

        try {
            String env = System.getenv(fullSocketName);
            fileDesc = Integer.parseInt(env);
        } catch (RuntimeException ex) {
            throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
        }

        try {
            FileDescriptor fd = new FileDescriptor();
            fd.setInt$(fileDesc);
            return new LocalServerSocket(fd);
        } catch (IOException ex) {
            throw new RuntimeException(
                "Error building socket from file descriptor: " + fileDesc, ex);
        }
    }

重量级forkSystemServer

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

java 复制代码
	// 相当于unix的fork,当返回null时是父进程,返回不为null时,是system_server的入口
    private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        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
        );
        // 删掉一些不可用的'能力'Capabilities
        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);

        // 硬编码启动system
        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();
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            // 实际调用并返回int pid = nativeForkSystemServer();
            // Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        // 实际上就是unix的fork,但是在这里进行了Runnable的映射
        // pid为0表示子进程,即system_server进程
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                // 注意此时socketName是"zygote"
                waitForSecondaryZygote(socketName);
            }
            // 在ZygoteInit的main中,也会关闭一次,不用担心,ZygoteServer内部会判断是否已经关闭
            zygoteServer.closeServerSocket();
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }
    private static void waitForSecondaryZygote(String socketName) {
        String otherZygoteName = Zygote.PRIMARY_SOCKET_NAME.equals(socketName)
                ? Zygote.SECONDARY_SOCKET_NAME : Zygote.PRIMARY_SOCKET_NAME;
        ZygoteProcess.waitForConnectionToZygote(otherZygoteName);
    }

	// 完成fork成system_server前的最后工作
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);
        // niceName被作为进程的名称
        if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName);
        }

        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
		//上面forkSystemServer方法中定义的启动参数没有"--invoke-with",所以这里执行的是else分支
        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 cl = getOrCreateSystemServerClassLoader();
            if (cl != null) {
                Thread.currentThread().setContextClassLoader(cl);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }

        /* should never reach here */
    }
ZygoteProcess.waitForConnectionToZygote

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\android\os\ZygoteProcess.java

java 复制代码
    // 不断尝试连接Zygote,直到超时
    public static void waitForConnectionToZygote(String zygoteSocketName) {
        final LocalSocketAddress zygoteSocketAddress =
                new LocalSocketAddress(zygoteSocketName, LocalSocketAddress.Namespace.RESERVED);
        waitForConnectionToZygote(zygoteSocketAddress);
    }
    public static void waitForConnectionToZygote(LocalSocketAddress zygoteSocketAddress) {
        for (int n = numRetries; n >= 0; n--) {
            try {
                final ZygoteState zs =
                        ZygoteState.connect(zygoteSocketAddress, null);
                zs.close();
                return;
            } catch (IOException ioe) {
            }
            Thread.sleep(ZYGOTE_CONNECT_RETRY_DELAY_MS);
        }
    }
	// ZygoteState是ZygoteProcess内部类
    private static class ZygoteState implements AutoCloseable {
        static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
                @Nullable LocalSocketAddress usapSocketAddress)
                throws IOException {

            DataInputStream zygoteInputStream;
            BufferedWriter zygoteOutputWriter;
            final LocalSocket zygoteSessionSocket.connect(zygoteSocketAddress);

            return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                                   zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
                                   getAbiList(zygoteOutputWriter, zygoteInputStream));
        }
    }
ZygoteInit.zygoteInit
java 复制代码
    public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

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

D:\AOSP\android-13.0.0_r9\frameworks\base\core\java\com\android\internal\os\RuntimeInit.java

java 复制代码
    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        final Arguments args = new Arguments(argv);

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

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

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

        Method m = cl.getMethod("main", new Class[] { String[].class });

        return new MethodAndArgsCaller(m, argv);
    }

Runnable r.run()

启动system_server

zygoteServer.runSelectLoop

zygote准备接受请求

相关推荐
叽哥1 小时前
Kotlin学习第 1 课:Kotlin 入门准备:搭建学习环境与认知基础
android·java·kotlin
风往哪边走2 小时前
创建自定义语音录制View
android·前端
用户2018792831672 小时前
事件分发之“官僚主义”?或“绕圈”的艺术
android
用户2018792831672 小时前
Android事件分发为何喜欢“兜圈子”?不做个“敞亮人”!
android
Kapaseker4 小时前
你一定会喜欢的 Compose 形变动画
android
QuZhengRong4 小时前
【数据库】Navicat 导入 Excel 数据乱码问题的解决方法
android·数据库·excel
zhangphil5 小时前
Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin(2)
android·kotlin
程序员码歌12 小时前
【零代码AI编程实战】AI灯塔导航-总结篇
android·前端·后端
书弋江山13 小时前
flutter 跨平台编码库 protobuf 工具使用
android·flutter
来来走走15 小时前
Flutter开发 webview_flutter的基本使用
android·flutter