Android ActivityManagerService--

2023-11-01  本文已影响0人  DarcyZhou

本文转载自:深度详解 Android R(11.0)Activity 启动过程

本文基于Android 11.0源码分析

前言

  继续上一篇分析Activity启动过程。

3.AMS向Zygote进程发送创建应用进程ActivityThread的过程

3.1 时序图

AMS13.png

3.2 ActivityTaskManagerService启动进程

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
    void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
            String hostingType) {
        try {
            if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "dispatchingStartProcess:"
                        + activity.processName);
            }
            // Post message to start process to avoid possible deadlock of calling into AMS with the
            // ATMS lock held.
            // 发送Handler消息来启动进程,以避免在持有ATMS锁的情况下调用AMS时可能发生的死锁
            final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
                    mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
                    isTop, hostingType, activity.intent.getComponent());
            mH.sendMessage(m);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

方法中需要发送Handler消息来启动进程,在获取Message消息对象时跟我们平时的使用方式不太一样,这里是用到PooledLambda#obtainMessage()函数,代码如下:

// frameworks/base/core/java/com/android/internal/util/function/pooled/PooledLambda.java
    static <A, B, C, D, E, F> Message obtainMessage(
            HexConsumer<? super A, ? super B, ? super C, ? super D, ? super E, ? super F> function,
            A arg1, B arg2, C arg3, D arg4, E arg5, F arg6) {
        synchronized (Message.sPoolSync) {
            PooledRunnable callback = acquire(PooledLambdaImpl.sMessageCallbacksPool,
                    function, 6, 0, ReturnType.VOID, arg1, arg2, arg3, arg4, arg5, arg6, null, null,
                    null, null, null);
            return Message.obtain().setCallback(callback.recycleOnUse());
        }
    }

可以看到这是一个静态函数,可以在接口外部直接被调用,这是Java 1.8的新特性,被static或default修饰的接口方法可以有默认实现,感兴趣的童鞋可以自行查阅哈。接口里面使用了经典的lambda定义方式,这个泛型的定义巧妙的将我们的函数以及需要传入的参数类型连接起来,第一个传入的lambda接口跟后面的参数类型紧密有关,调用这个函数的时候直接将需要传入的参数一并传入。这里需要提到的是lambda里面的中间接口是一种隐藏式的存在,我们在调用的过程中可以直接匿名忽略掉,上面的调用实例就是如此,直接使用了::符号 直接链接到目标函数 startProcess()。

  所以语法含义是调用ActivityManagerInternal类的startProcess() 方法,后面的那些变量就是传递到startProcess()方法的入参。具体的再说就偏离主题了,感兴趣的可以自行查阅,简要说明就是这里通过acquire()函数获取到一个PooledRunnable实例,又通过它的recycleOnUse()函数得到一个PooledLambdaImpl(实现了PooledLambda接口)的实例,所以当我们后续再调用sendMessage()的时候这个PooledRunnable的run()方法会得到执行,也即ActivityManagerInternal#startProcess()方法。

  ActivityManagerInternal是一个抽象类,它是Activity管理本地服务接口的,它的实现为AMS的内部类LocalService,在AMS启动的过程,通过LocalServices#addService()注册到LocalServices,此类的使用方式与ServiceManager相似,不同之处在于,此处注册的服务不是Binder对象,并且只能在同一进程(system_server进程)中使用。也就是说ActivityManagerInternal实现类LocalService是system_server进程的本地服务Service,通过本地服务注册到LocalServices中,而AMS也是运行在system_server进程,因此可以直接使用LocalService。

  LocalServices可以理解为是一个公开缓存池,内部使用ArrayMap来存储本地服务对象。system_server进程中每个服务都可以通过LocalServices#addService()注册到LocalServices中,需要使用存储的LocalService时通过 LocalServices#getService()获取注册的本地服务。

3.3 ActivityManagerService

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

    public final class LocalService extends ActivityManagerInternal {
        ......
        @Override
        public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
                boolean isTop, String hostingType, ComponentName hostingName) {
            try {
                if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                            + processName);
                }
                synchronized (ActivityManagerService.this) {
                    // If the process is known as top app, set a hint so when the process is
                    // started, the top priority can be applied immediately to avoid cpu being
                    // preempted by other processes before attaching the process of top app.
                    startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                            new HostingRecord(hostingType, hostingName, isTop),
                            ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
                            false /* isolated */, true /* keepIfLarge */);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            }
        }
        ......
    }
---------------------------------------------
    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
                keepIfLarge, null /* ABI override */, null /* entryPoint */,
                null /* entryPointArgs */, null /* crashHandler */);
    }
}

startProcess()方法调用AMS#startProcessLocked()方法,并返回ProcessRecord实例记录管理启动进程的信息。

3.4 ProcessList

// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
    final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
            boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
            int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
            boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
            Runnable crashHandler) {
        ......
        // ProcessRecord记录每个进程的信息,进程名、uid等
        ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkSlow(startTime, "startProcess: stepping in to startProcess");
        final boolean success =
                startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
        checkSlow(startTime, "startProcess: done starting proc!");
        return success ? app : null;
    }
---------------------------------------------------------------------
    final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
            int zygotePolicyFlags, String abiOverride) {
        return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
                false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
                false /* mountExtStorageFull */, abiOverride);
    }
---------------------------------------------------------------------
    boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
            int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
            boolean mountExtStorageFull, String abiOverride) {
                  ......
        try {
            app.gids = gids;
            app.setRequiredAbi(requiredAbi);
            app.instructionSet = instructionSet;

            // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            // 配置新创建进程的启动文件:ActivityThread,经过层层封装后经Socket传输到Zygote进程
            // Zygote进程fork出新进程后要加载启动的类文件名
            final String entryPoint = "android.app.ActivityThread";
            return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                    runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
                    instructionSet, invokeWith, startTime);
        }
        ......
    }
---------------------------------------------------------------------
    boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
            int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
            String seInfo, String requiredAbi, String instructionSet, String invokeWith,
            long startTime) {
        ......
        if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
            ......
        } else {
            try {
                final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                        entryPoint, app,
                        uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
                        requiredAbi, instructionSet, invokeWith, startTime);
                handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                        startSeq, false);
            }
            ......
            return app.pid > 0;
        }
    }
---------------------------------------------------------------------
    private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
            int mountExternal, String seInfo, String requiredAbi, String instructionSet,
            String invokeWith, long startTime) {
        try {
            ......
            final Process.ProcessStartResult startResult;
            if (hostingRecord.usesWebviewZygote()) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            } else if (hostingRecord.usesAppZygote()) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);
                // We can't isolate app data and storage data as parent zygote already did that.
                startResult = appZygote.getProcess().start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                        app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
                        false, false,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            } else {
                // 启动进程
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                        isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
                        whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            }
            return startResult;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }

经过调用4个startProcessLocked()方法后,调用到了startProcess()方法,然后在startProcess()方法里做了一个判断,根据不同的参数调用不同的方法启动进程,这里跟进Process#start()继续追踪源码。

3.5 Process

// frameworks/base/core/java/android/os/Process.java
    public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();

        public static ProcessStartResult start(@NonNull final String processClass,
                                           @Nullable final String niceName,
                                           int uid, int gid, @Nullable int[] gids,
                                           int runtimeFlags,
                                           int mountExternal,
                                           int targetSdkVersion,
                                           @Nullable String seInfo,
                                           @NonNull String abi,
                                           @Nullable String instructionSet,
                                           @Nullable String appDataDir,
                                           @Nullable String invokeWith,
                                           @Nullable String packageName,
                                           int zygotePolicyFlags,
                                           boolean isTopApp,
                                           @Nullable long[] disabledCompatChanges,
                                           @Nullable Map<String, Pair<String, Long>>
                                                   pkgDataInfoMap,
                                           @Nullable Map<String, Pair<String, Long>>
                                                   whitelistedDataInfoMap,
                                           boolean bindMountAppsData,
                                           boolean bindMountAppStorageDirs,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    zygotePolicyFlags, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
                    bindMountAppStorageDirs, zygoteArgs);
    }

ZYGOTE_PROCESS是ZygoteProcess在Process类中的静态实例,所以流程调用走到Process#start()方法继续进程的启动流程。

3.6 ZygoteProcess

// frameworks/base/core/java/android/os/ZygoteProcess.java
    public final Process.ProcessStartResult start(@NonNull final String processClass,
                                                  final String niceName,
                                                  int uid, int gid, @Nullable int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  @Nullable String seInfo,
                                                  @NonNull String abi,
                                                  @Nullable String instructionSet,
                                                  @Nullable String appDataDir,
                                                  @Nullable String invokeWith,
                                                  @Nullable String packageName,
                                                  int zygotePolicyFlags,
                                                  boolean isTopApp,
                                                  @Nullable long[] disabledCompatChanges,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          pkgDataInfoMap,
                                                  @Nullable Map<String, Pair<String, Long>>
                                                          whitelistedDataInfoMap,
                                                  boolean bindMountAppsData,
                                                  boolean bindMountAppStorageDirs,
                                                  @Nullable String[] zygoteArgs) {
        // TODO (chriswailes): Is there a better place to check this value?
        if (fetchUsapPoolEnabledPropWithMinInterval()) {
            informZygotesOfUsapPoolStatus();
        }
        try {
            // 继续调用startViaZygote,即通过Zygote来启动进程
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
                    bindMountAppStorageDirs, zygoteArgs);
        } 
        ......
    }
---------------------------------------------------------------------
    private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                      @Nullable final String niceName,
                                                      final int uid, final int gid,
                                                      @Nullable final int[] gids,
                                                      int runtimeFlags, int mountExternal,
                                                      int targetSdkVersion,
                                                      @Nullable String seInfo,
                                                      @NonNull String abi,
                                                      @Nullable String instructionSet,
                                                      @Nullable String appDataDir,
                                                      @Nullable String invokeWith,
                                                      boolean startChildZygote,
                                                      @Nullable String packageName,
                                                      int zygotePolicyFlags,
                                                      boolean isTopApp,
                                                      @Nullable long[] disabledCompatChanges,
                                                      @Nullable Map<String, Pair<String, Long>>
                                                              pkgDataInfoMap,
                                                      @Nullable Map<String, Pair<String, Long>>
                                                              whitelistedDataInfoMap,
                                                      boolean bindMountAppsData,
                                                      boolean bindMountAppStorageDirs,
                                                      @Nullable String[] extraArgs)
                                                      throws ZygoteStartFailedEx {
        // 创建字符串列表argsForZygote,将应用进程的启动参数保存在argsForZygote中
        // 包括uid、gid、targetSdkVersion、应用程序进程启动文件:android.app.ActivityThread等参数
        ArrayList<String> argsForZygote = new ArrayList<>();
                ...... // 添加各种参数值
                argsForZygote.add(processClass);
                ......
        synchronized(mLock) {
            // The USAP pool can not be used if the application will not use the systems graphics
            // driver.  If that driver is requested use the Zygote application start path.
            // 调用zygoteSendArgsAndGetResult(),将传入的应用进程的启动参数argsForZygote写入到ZygoteState中
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              zygotePolicyFlags, argsForZygote);
        }
    }

ZygoteProcess#start()方法中,继续调用 ZygoteProcess#startViaZygote() 方法,即通过Zygote来启动进程,方法流程如下:

3.7 ZygoteProcess开启socket连接

// frameworks/base/core/java/android/os/ZygoteProcess.java
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        try {
            //与Zygote进程建立Socket连接
            attemptConnectionToPrimaryZygote();
            if (primaryZygoteState.matches(abi)) {
                return primaryZygoteState;
            }
            if (mZygoteSecondarySocketAddress != null) {
                // The primary zygote didn't match. Try the secondary.
                attemptConnectionToSecondaryZygote();
                if (secondaryZygoteState.matches(abi)) {
                    return secondaryZygoteState;
                }
            }
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
        }
        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }
-------------------------------------------------------
    private static class ZygoteState implements AutoCloseable {
        ......
        // 上面Primary、Secondary都是调用ZygoteState.connect()方法来创建一个使用给定Zygote socket 地址的 Socket 连接
        static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,
                @Nullable LocalSocketAddress usapSocketAddress)
                throws IOException {

            DataInputStream zygoteInputStream;
            BufferedWriter zygoteOutputWriter;
            final LocalSocket zygoteSessionSocket = new LocalSocket();

            if (zygoteSocketAddress == null) {
                throw new IllegalArgumentException("zygoteSocketAddress can't be null");
            }

            try {
                zygoteSessionSocket.connect(zygoteSocketAddress);
                zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
                zygoteOutputWriter =
                        new BufferedWriter(
                                new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),
                                Zygote.SOCKET_BUFFER_SIZE);
            } catch (IOException ex) {
                try {
                    zygoteSessionSocket.close();
                } catch (IOException ignore) { }
                throw ex;
            }
            // socket、DataInputStream、BufferedWriter封装成 ZygoteState 对象供外部调用
            return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                                   zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
                                   getAbiList(zygoteOutputWriter, zygoteInputStream));
        }
    }

ZygoteProcess#openZygoteSocketIfNeeded()方法,打开与Zygote进程的socket连接,如果连接未建立,则尝试调用ZygoteState#connect()方法创建一个使用给定Zygote socket地址的Socket连接,然后连接到Zygote的远程服务端,同时创建BufferedWriter和DataInputStream进行参数数据的传输与读取,最后将socket、DataInputStream、BufferedWriter等封装成ZygoteState对象供外部调用。

3.8 ZygoteProcess发送请求参数

// frameworks/base/core/java/android/os/ZygoteProcess.java
    private Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)
            throws ZygoteStartFailedEx {
        ......
        if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {
            try {
                return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
            } catch (IOException ex) {
                // If there was an IOException using the USAP pool we will log the error and
                // attempt to start the process through the Zygote.
                Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
                        + ex.getMessage());
            }
        }

        return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
    }
-----------------------------------
    // 用来fork出一个新的应用进程
    private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
            ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
        try {
            final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
            final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

            zygoteWriter.write(msgStr);
            zygoteWriter.flush();

            // Always read the entire result from the input stream to avoid leaving
            // bytes in the stream for future process starts to accidentally stumble
            // upon.
            // 创建进程
            Process.ProcessStartResult result = new Process.ProcessStartResult();
            result.pid = zygoteInputStream.readInt();
            result.usingWrapper = zygoteInputStream.readBoolean();

            if (result.pid < 0) {
                 // 进程创建失败
                throw new ZygoteStartFailedEx("fork() failed");
            }
            return result;
        } catch (IOException ex) {
            zygoteState.close();
            Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
                    + ex.toString());
            throw new ZygoteStartFailedEx(ex);
        }
    }

ZygoteProcess#attemptZygoteSendArgsAndGetResult()方法中使用创建的ZygoteState中保存的BufferedWriter和DataInputStream来进行Socket通信,通过它们进行数据流的传输与读取操作。system_server 进程通过BufferedWriter将参数写给Zygote进程的socket的server端,然后阻塞等待Zygote进程的socket返回pid和usingWrapper后封装到 ProcessStartResult。

4.Zygote进程接收请求fork并启动应用进程ActivityThread的过程

4.1 时序图

AMS14.png

4.2 Zygote进程启动、解析Socket传入的参数

  Android系统底层是基于Linux 的,和Linux一样,init进程是Linux系统用户进程的第一个进程,它是由Linux内核(kenerl)启动的,用来启动属性服务(类似Windows中的注册表)、启动进程。其它所有的用户进程都是init 进程的子进程,我们接下来分析的Zygote进程也是由init进程而创建的,Zygote如何启动这里暂不讨论,Zygote启动之后会调用ZygoteInit#main()方法,所以我们先从main()方法来看socket创建和消息读取。代码如下:

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    ZygoteServer zygoteServer = null;
    ......
    Runnable caller;
    try {
        ......
        // 解析参数
        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]);
            }
        }
        ......
        zygoteServer = new ZygoteServer(isPrimaryZygote);
        ......
        // 调用 runSelectLoop() 开启Loop循环来监听client socket发来的消息
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with 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实例对象,调用ZygoteServer#runSelectLoop()方法开启loop无限循环来监听client socket发来的消息,当接收到创建新进程的请求时,立即唤醒并执行相应工作。如果fork出系统进程,则加入到列表,然后继续阻塞等待;如果fork出子进程,则退出loop循环,返回创建的应用子进程,并执行子进程的启动。

4.3 ZygoteServer开启Loop循环监听Socket

// frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
    ZygoteServer(boolean isPrimaryZygote) {
        mUsapPoolEventFD = Zygote.getUsapPoolEventFD();

        if (isPrimaryZygote) {
            mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
            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();
    } 
--------------------------------------------------------------
    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
        ArrayList<ZygoteConnection> peers = new ArrayList<>();
        // mZygoteSocket是服务端的socket对象,也就是Zygote进程所在socket放在fds[0]位置
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        // 刚开始默认 peers[0] = null
        peers.add(null);

        mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
        // 开启轮询等待
        while (true) {
            fetchUsapPoolPolicyPropsWithMinInterval();
            mUsapPoolRefillAction = UsapPoolRefillAction.NONE;
            int[] usapPipeFDs = null;
            StructPollfd[] pollFDs;

            if (mUsapPoolEnabled) {
                usapPipeFDs = Zygote.getUsapPipeFDs();
                pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }
            int pollIndex = 0;
            ......
            int pollTimeoutMs;
            if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
                pollTimeoutMs = -1;
            } else {
                long elapsedTimeMs = System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;
                if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
                    pollTimeoutMs = -1;
                } else if (elapsedTimeMs <= 0) {
                    pollTimeoutMs = mUsapPoolRefillDelayMs;
                } else {
                    pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
                }
            }

            int pollReturnValue;
            try {
                 // 处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

            if (pollReturnValue == 0) {
                mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
                mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;
            } else {
                boolean usapPoolFDRead = false;
                // 倒序处理,即优先处理已建立连接的信息,后处理新建连接的请求
                while (--pollIndex >= 0) {
                        // 采用I/O多路复用 epoll 机制,当接收到客户端请求到来,则往下执行;否则跳出本次循环
                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                        continue;
                    }

                    if (pollIndex == 0) {
                        // Zygote server socket
                        // pollIndex==0 表示有新的客户端请求连接到来,调用server socket端的 accpet 函数建立通信连接
                        // zygote 进程与 system server 进程建立了连接
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        // 加入到 peers 和 fds, 即开始下一次监听
                        peers.add(newPeer);
                        socketFDs.add(newPeer.getFileDescriptor());
                    } else if (pollIndex < usapPoolEventFDIndex) {
                        // Session socket accepted from the Zygote server socket
                        // socket连接成功之后从Zygote服务器的socket接受到的 Session socket
                        try {
                            ZygoteConnection connection = peers.get(pollIndex);
                            final Runnable command = connection.processOneCommand(this);

                            // TODO (chriswailes): Is this extra check necessary?
                            if (mIsForkChild) {
                                ......
                                return command;
                            } else {
                                // 如果不是fork子进程则关闭连接,删除当前 fd 消息
                                if (connection.isClosedByPeer()) {
                                    connection.closeSocket();
                                    peers.remove(pollIndex);
                                    socketFDs.remove(pollIndex);
                                }
                            }
                        } catch (Exception e) {
                            ......
                        } finally {
                            ......
                            mIsForkChild = false;
                        }
                    }
                }
                            ......
            }
                        ......
        }
    }

runSelectLoop()方法中获取zygoteSendArgsAndGetResult()方法中传输过来的应用进程的启动参数等,即和Zygote进程建立起连接,其方法流程如下:

  1. 开启Loop死循环监听socket事件,没有连接时就阻塞在那里,当有连接到来时唤醒继续往下执行。

  2. pollIndex==0时,说明收到请求连接的事件,请求和Zygote建立socket连接,调用acceptCommandPeer()方法创建ZygoteConnection对象,并调用mZygoteSocket#accept()方法建立socket 连接,然后添加到监听列表peers中,等待与该socket有关的命令的到来。

  3. pollIndex < usapPoolEventFDIndex时,表示是已经连接的socket上的命令到来,此时调用ZygoteConnection#processOneCommand()方法来接收客户端传输过来的应用进程的启动参数,并执行进程创建工作,处理完后,就会断开与客户端的连接,并把用于连接的socket从监听列表peers中移除。

4.4 ZygoteConnection

// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
    Runnable processOneCommand(ZygoteServer zygoteServer) {
        String[] args;
        try {
            // 逐行读取 client 端通过socketwrite过来的启动参数(字符串数组)
            args = Zygote.readArgumentList(mSocketReader);
        } catch (IOException ex) {
            throw new IllegalStateException("IOException on command socket", ex);
        }
        ......
        int pid;
        FileDescriptor childPipeFd = null;
        FileDescriptor serverPipeFd = null;
        // 将数据解析成ZygoteArguments格式
        ZygoteArguments parsedArgs = new ZygoteArguments(args);
        ......
        int[][] rlimits = null;
        if (parsedArgs.mRLimits != null) {
            rlimits = parsedArgs.mRLimits.toArray(Zygote.INT_ARRAY_2D);
        }

        int[] fdsToIgnore = null;
        if (parsedArgs.mInvokeWith != null) {
            try {
                FileDescriptor[] pipeFds = Os.pipe2(O_CLOEXEC);
                childPipeFd = pipeFds[1];
                serverPipeFd = pipeFds[0];
                Os.fcntlInt(childPipeFd, F_SETFD, 0);
                fdsToIgnore = new int[]{childPipeFd.getInt$(), serverPipeFd.getInt$()};
            } catch (ErrnoException errnoEx) {
                throw new IllegalStateException("Unable to set up pipe for invoke-with", errnoEx);
            }
        }
        // 将client端fd和server端fd存入fdsToClose数组中,然后fd置为null
        int [] fdsToClose = { -1, -1 };
        FileDescriptor fd = mSocket.getFileDescriptor();
        if (fd != null) {
            fdsToClose[0] = fd.getInt$();
        }
        fd = zygoteServer.getZygoteSocketFileDescriptor();
        if (fd != null) {
            fdsToClose[1] = fd.getInt$();
        }
        // 调用forkAndSpecialize()方法来fork子进程
        pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
                parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
                parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
                parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
                parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);

        try {
            if (pid == 0) {
                // in child
                //  pid = 0表示创建成功,则进入子进程中,即应用程序进程
                zygoteServer.setForkChild();
                // 关闭socket连接
                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                // 进入子进程执行相关操作
                return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
            } else {
                // In the parent. A pid < 0 indicates a failure and will be handled in handleParentProc.
                // pid < 0表示创建失败,则进入父进程返回消息给client socket表示启动失败
                IoUtils.closeQuietly(childPipeFd);
                childPipeFd = null;
                // 进入父进程执行相关操作
                handleParentProc(pid, serverPipeFd);
                return null;
            }
        } finally {
            IoUtils.closeQuietly(childPipeFd);
            IoUtils.closeQuietly(serverPipeFd);
        }
    }

该方法主要作用如下:

  1. 读取system_server端socket写入的数据,并将存入字符串数组的数据封装成ZygoteArguments格式。

  2. 调用Zygote#forkAndSpecialize()方法来fork子进程,并返回pid,这里的pid并非是进程id,而是返回结果值,0表示创建成功,-1则失败。

  3. 子进程创建成功后进入子进程执行。

4.5 Zygote创建子进程(native 层创建)

// frameworks/base/core/java/com/android/internal/os/Zygote.java
    static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            boolean isTopApp, String[] pkgDataInfoList, String[] whitelistedDataInfoList,
            boolean bindMountAppDataDirs, boolean bindMountAppStorageDirs) {
        ZygoteHooks.preFork();
        // 通过 JNI 调用 native 层方法
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir, isTopApp,
                pkgDataInfoList, whitelistedDataInfoList, bindMountAppDataDirs,
                bindMountAppStorageDirs);
        if (pid == 0) {
            // Note that this event ends at the end of handleChildProc,
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
            // If no GIDs were specified, don't make any permissions changes based on groups.
            if (gids != null && gids.length > 0) {
                NetworkUtils.setAllowNetworkingForProcess(containsInetGid(gids));
            }
        }
        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
        ZygoteHooks.postForkCommon();
        return pid;
    }

方法中调用native层的nativeForkAndSpecialize()方法创建进程,然后返回进程的pid(父进程中,返回新建的子进程的pid,子进程中,则返回0,出现错误时返回负数),具体native层的源码就不跟了,大致看了一下过程:

  1. 调用Linux的fork()方法创建进程,设置进程的主线程的name,如果是null或者system_server,则为system_server。

  2. 调用CallStaticVoidMethod()方法返回Zygote#callPostForkChildHooks()方法处理fork子线程之后的gc/线程池管理等操作。

4.6 ZygoteConnection#handleChildProc()

// frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
     private Runnable handleChildProc(ZygoteArguments parsedArgs,
            FileDescriptor pipeFd, boolean isZygote) {
        // 关闭socket连接
        closeSocket();
        // 设置应用进程的name名
        Zygote.setAppProcessName(parsedArgs, TAG);

        // End of the postFork event.
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        if (parsedArgs.mInvokeWith != null) {
            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(),
                    pipeFd, parsedArgs.mRemainingArgs);

            // Should not get here.
            throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
        } else {
            if (!isZygote) {
                // 初始化Zygote
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mDisabledCompatChanges,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            }
        }
    }

该方法就是进入子进程执行不同的初始化操作,因为已经fork()成功,关闭socket连接等释放资源,设置应用进程的name,最后调用 ZygoteInit#zygoteInit()方法初始化Zygote。

4.7 ZygoteInit#zygoteInit()

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
    public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
            ......
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();
        // 进程初始化配置,如设置异常捕获Handler、时区、重置 LogManager 等等
        RuntimeInit.commonInit();
        // native 层初始化 -- 打开/dev/binder驱动,映射内核的地址空间,创建binder线程用于IPC通信
        ZygoteInit.nativeZygoteInit();
        // 创建的Runnable对象
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

方法流程如下:

  1. 日志流重定向,将系统输出和系统错误重定向到Android日志。

  2. 进程初始化配置,如设置异常捕获Handler、时区、重置 LogManager 等等。

  3. native层初始化,打开/dev/binder驱动,映射内核的地址空间,创建binder线程用于IPC通信。

  4. 调用RuntimeInit#applicationInit()方法,返回创建的Runnable对象。

4.8 RuntimeInit#applicationInit()

// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
    protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // 如果应用程序调用了System.exit()方法立即终止进程,可能会导致剩余的运行线程在进程实际退出之前崩溃
        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) {
        // 待加载的类、这里是指ActivityThread,也就是我们第三节中在ProcessList中指明的entryPoint
        Class<?> cl; 
        try {
            // 加载android.app.ActivityThread类
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className, ex);
        }
        // 获取 main 方法
        Method m;
        try {
            // 获取 ActivityThread#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);
        }
        // 判断main方法是不是public并且static类型
        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException("Main method is not public and static on " + className);
        }
        // 返回Caller,即本小节第一部分的ZygoteInit.main()中的caller
        return new MethodAndArgsCaller(m, argv);
    }

applicationInit()方法中首先做了一个System.exit()的保护,防止退出进程时发生crash,设置targetSDKVersion等参数,最后调用findStaticMain()方法去加载ActivityThread类以及方法。

  findStaticMain()方法中通过ClassLoader加载获取目标类ActivityThread,后获取其静态main方法,然后封装成MethodAndArgsCaller对象返回,MethodAndArgsCaller实现了Runnable 接口。即返回到《4.2 Zygote进程启动、解析Socket传入的参数》 这节中ZygoteInit#main()方法的caller,如果caller=null会调用这个Runnable的run()方法。

4.9 RuntimeInit#MethodAndArgsCaller

// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
    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 {
                // 这里会调用new MethodAndArgsCaller()的第一个参数的方法
                // 也就是ActivityThread#main()函数
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                ......
            }
        }
    }

MethodAndArgsCaller#run() 方法中使用了invoke反射调用,至此ActivityThread的main()方法得以执行,应用进程也就成功启动ActivityThread。

4.10 小结

  Zygote 进程启动流程:

  1. init进程为用户空间(相对于内核空间)的第一个进程,根据init.rc启动Zygote进程。

  2. Zygote进程启动步骤:创建虚拟机、注册JNI、执行ZygoteInit#main()方法。

  3. Zygote进程启动system_server进程(Zygote 启动的第一个进程),这个本小节没有具体分析。

  4. Zygote创建socket连接通道,阻塞并等待新建进程的指令到来,通过fork新建用户进程。

  5. Zygote新加了一个优化进程创建的机制,UsapPool-池化机制,是预先缓存了几个进程。

上一篇 下一篇

猜你喜欢

热点阅读