Android8.1系统源码讲解之ActivityThread进程启动详解

在前面的文章中有一篇名《Android8.1 Launcher3启动源码解析之第一个Activity启动》文章讲解了Launcher中的第一个Activity启动过程,但是在最后没有讲解ActivityThread启动的过程。那么这篇文章将讲解ActivityThread是如何启动的。

一、由AMS发起的ActivityThread进程启动

1、ActivityStackSupervisor中启动

在ActivityStackSupervisor中关于启动Activity的代码如下:

void startSpecificActivityLocked(ActivityRecord r,
                                 boolean andResume, boolean checkConfig) {
    // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    r.getStack().setLaunchTime(r);

    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags& ActivityInfo.FLAG_MULTIPROCESS) == 0
                    || !"android".equals(r.info.packageName)) {
                // Don't add this if it is a platform component that is marked
                // to run in multiple processes, because this is actually
                // part of the framework so doesn't make sense to track as a
                // separate apk in the process.
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                        mService.mProcessStats);
            }
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                    + r.intent.getComponent().flattenToShortString(), e);
        }

        // If a dead object exception was thrown -- fall through to
        // restart the application.
    }

    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}
由于APP之前并没有启动,因此在开始从AMS中获取的app为null。这样就会造成一种情况,不会走if条件语句,直接进入AMS的startProcessLocked方法。

2、AMS中startProcessLocked方法


final ProcessRecord startProcessLocked(String processName,
                                       ApplicationInfo info, boolean knownToBeDead, int intentFlags,
                                       String hostingType, ComponentName hostingName, boolean allowWhileBooting,
                                       boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
                                       boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
                                       boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
                                       String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
    long startTime = SystemClock.elapsedRealtime();
    ProcessRecord app;
    if (!isolated) { //从前面传递过来的默认值可知这里isloated为false
        //还没有创建app,因此这里也是null
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkTime(startTime, "startProcess: after getProcessRecord");

        if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {//传递过来的值intentFlags为0,这里就直接过去
            // If we are in the background, then check to see if this process
            // is bad.  If so, we will just silently fail.
            if (mAppErrors.isBadProcessLocked(info)) {
                if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid
                        + "/" + info.processName);
                return null;
            }
        } else {
            // When the user is explicitly starting a process, then clear its
            // crash count so that we won't make it bad until they see at
            // least one crash dialog again, and make the process good again
            // if it had been bad.
            if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
                    + "/" + info.processName);
            mAppErrors.resetProcessCrashTimeLocked(info);
            if (mAppErrors.isBadProcessLocked(info)) {
                EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                        UserHandle.getUserId(info.uid), info.uid,
                        info.processName);
                mAppErrors.clearBadProcessLocked(info);
                if (app != null) {
                    app.bad = false;
                }
            }
        }
    } else {
        // If this is an isolated process, it can't re-use an existing process.
        app = null;
    }

    // We don't have to do anything more if:
    // (1) There is an existing application record; and
    // (2) The caller doesn't think it is dead, OR there is no thread
    //     object attached to it so we know it couldn't have crashed; and
    // (3) There is a pid assigned to it, so it is either starting or
    //     already running.
    if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "startProcess: name=" + processName
            + " app=" + app + " knownToBeDead=" + knownToBeDead
            + " thread=" + (app != null ? app.thread : null)
            + " pid=" + (app != null ? app.pid : -1));
    if (app != null && app.pid > 0) {//app为null
        if ((!knownToBeDead && !app.killed) || app.thread == null) {
            // We already have the app running, or are waiting for it to
            // come up (we have a pid but not yet its thread), so keep it.
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES, "App already running: " + app);
            // If this is a new package in the process, add the package to the list
            app.addPackage(info.packageName, info.versionCode, mProcessStats);
            checkTime(startTime, "startProcess: done, added package to proc");
            return app;
        }

        // An application record is attached to a previous process,
        // clean it up now.
        if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app);
        checkTime(startTime, "startProcess: bad proc running, killing");
        killProcessGroup(app.uid, app.pid);
        handleAppDiedLocked(app, true, true);
        checkTime(startTime, "startProcess: done killing old proc");
    }

    String hostingNameStr = hostingName != null
            ? hostingName.flattenToShortString() : null;

    if (app == null) {
        checkTime(startTime, "startProcess: creating new process record");
        //这里创建app的进程记录,并添加到系统管理集中
        app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
        if (app == null) {
            Slog.w(TAG, "Failed making new process record for "
                    + processName + "/" + info.uid + " isolated=" + isolated);
            return null;
        }
        app.crashHandler = crashHandler;
        checkTime(startTime, "startProcess: done creating new process record");
    } else {
        // If this is a new package in the process, add the package to the list
        app.addPackage(info.packageName, info.versionCode, mProcessStats);
        checkTime(startTime, "startProcess: added package to existing proc");
    }

    // If the system is not ready yet, then hold off on starting this
    // process until it is.
    if (!mProcessesReady
            && !isAllowedWhileBooting(info)
            && !allowWhileBooting) {//这里再次进行判断,是否已经添加到进程记录管理中
        if (!mProcessesOnHold.contains(app)) {
            mProcessesOnHold.add(app);
        }
        if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                "System not ready, putting on hold: " + app);
        checkTime(startTime, "startProcess: returning with proc on hold");
        return app;
    }

    checkTime(startTime, "startProcess: stepping in to startProcess");
    startProcessLocked(
            app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    checkTime(startTime, "startProcess: done starting proc!");
    return (app.pid != 0) ? app : null;
}

代码运行到AMS中startProcessLocked方法中,需要添加一些默认参数进去。在后面调用重载的该方法中,由于没有创建app的线程记录,因此在这里创建并将此记录添加到AMS中的线程记录数集中。最后,在最后调用另外一个重载函数。

 private final void startProcessLocked(ProcessRecord app, String hostingType,
                                          String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
        long startTime = SystemClock.elapsedRealtime();
     ......
        String invokeWith = null;
        if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
            // Debuggable apps may include a wrapper script with their library directory.
            String wrapperFileName = app.info.nativeLibraryDir + "/wrap.sh";
            StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
            try {
                if (new File(wrapperFileName).exists()) {
                    invokeWith = "/system/bin/logwrapper " + wrapperFileName;
                }
            } finally {
                StrictMode.setThreadPolicy(oldPolicy);
            }
        }

        String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
        if (requiredAbi == null) {
            requiredAbi = Build.SUPPORTED_ABIS[0];
        }

        String instructionSet = null;
        if (app.info.primaryCpuAbi != null) {
            instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);
        }

    app.gids = gids;
    app.requiredAbi = requiredAbi;
    app.instructionSet = instructionSet;

    // the per-user SELinux context must be set
            if (TextUtils.isEmpty(app.info.seInfoUser)) {
        Slog.wtf(TAG, "SELinux tag not defined",
                new IllegalStateException("SELinux tag not defined for "
                        + app.info.packageName + " (uid " + app.uid + ")"));
    }
    final String seInfo = app.info.seInfo
            + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
    // Start the process.  It will either succeed and return a result containing
    // the PID of the new process, or else throw a RuntimeException.
    boolean isActivityProcess = (entryPoint == null);
            if (entryPoint == null) entryPoint = "android.app.ActivityThread"; //这个是后面native层要启动的类
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
    app.processName);
    checkTime(startTime, "startProcess: asking zygote to start proc");
    ProcessStartResult startResult;
            if (hostingType.equals("webview_service")) {
        startResult = startWebView(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                app.info.dataDir, null, entryPointArgs);
    } else {
        startResult = Process.start(entryPoint,
                app.processName, uid, uid, gids, debugFlags, mountExternal,
                app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                app.info.dataDir, invokeWith, entryPointArgs);
    }
    checkTime(startTime, "startProcess: returned from zygote!");
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);//添加到电量监控服务中
    checkTime(startTime, "startProcess: done updating battery stats");

        EventLog.writeEvent(EventLogTags.AM_PROC_START,
            UserHandle.getUserId(uid), startResult.pid, uid,
    app.processName, hostingType,
    hostingNameStr != null ? hostingNameStr : "");

        try {
        AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,
                seInfo, app.info.sourceDir, startResult.pid);
    } catch (RemoteException ex) {
        // Ignore
    }
    ,,,,,,
}

这里的事情就比较简单,作为启动进程前变量的赋值操作,最后调用Process中的start方法启动进程。在这里需要注意的设置了进程创建之初要启动的类名为ActivityThread类,这个是重点在后面是要用到的。

二、Process启动Activity进程操作

public static final ProcessStartResult start(final String processClass,
                                             final String niceName,
                                             int uid, int gid, int[] gids,
                                             int debugFlags, int mountExternal,
                                             int targetSdkVersion,
                                             String seInfo,
                                             String abi,
                                             String instructionSet,
                                             String appDataDir,
                                             String invokeWith,
                                             String[] zygoteArgs) {
    return zygoteProcess.start(processClass, niceName, uid, gid, gids,
            debugFlags, mountExternal, targetSdkVersion, seInfo,
            abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
擦,只有这么一行代码,直接交给ZygoteProcess来处理

三,ZygoteProcess中启动ActivityThread操作

1、start

public final Process.ProcessStartResult start(final String processClass,
                                              final String niceName,
                                              int uid, int gid, int[] gids,
                                              int debugFlags, int mountExternal,
                                              int targetSdkVersion,
                                              String seInfo,
                                              String abi,
                                              String instructionSet,
                                              String appDataDir,
                                              String invokeWith,
                                              String[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
                "Starting VM process through Zygote failed");
        throw new RuntimeException(
                "Starting VM process through Zygote failed", ex);
    }
}

private Process.ProcessStartResult startViaZygote(final String processClass,
                                                  final String niceName,
                                                  final int uid, final int gid,
                                                  final int[] gids,
                                                  int debugFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  String seInfo,
                                                  String abi,
                                                  String instructionSet,
                                                  String appDataDir,
                                                  String invokeWith,
                                                  String[] extraArgs)
        throws ZygoteStartFailedEx {
    ArrayList argsForZygote = new ArrayList();

    // --runtime-args, --setuid=, --setgid=,
    // and --setgroups= must go first
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
        argsForZygote.add("--enable-jni-logging");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
        argsForZygote.add("--enable-safemode");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_JDWP) != 0) {
        argsForZygote.add("--enable-jdwp");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
        argsForZygote.add("--enable-checkjni");
    }
    if ((debugFlags & Zygote.DEBUG_GENERATE_DEBUG_INFO) != 0) {
        argsForZygote.add("--generate-debug-info");
    }
    if ((debugFlags & Zygote.DEBUG_ALWAYS_JIT) != 0) {
        argsForZygote.add("--always-jit");
    }
    if ((debugFlags & Zygote.DEBUG_NATIVE_DEBUGGABLE) != 0) {
        argsForZygote.add("--native-debuggable");
    }
    if ((debugFlags & Zygote.DEBUG_JAVA_DEBUGGABLE) != 0) {
        argsForZygote.add("--java-debuggable");
    }
    if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
        argsForZygote.add("--enable-assert");
    }
    if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
        argsForZygote.add("--mount-external-default");
    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
        argsForZygote.add("--mount-external-read");
    } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
        argsForZygote.add("--mount-external-write");
    }
    argsForZygote.add("--target-sdk-version=" + targetSdkVersion);

    // --setgroups is a comma-separated list
    if (gids != null && gids.length > 0) {
        StringBuilder sb = new StringBuilder();
        sb.append("--setgroups=");

        int sz = gids.length;
        for (int i = 0; i < sz; i++) {
            if (i != 0) {
                sb.append(',');
            }
            sb.append(gids[i]);
        }

        argsForZygote.add(sb.toString());
    }

    if (niceName != null) {
        argsForZygote.add("--nice-name=" + niceName);
    }

    if (seInfo != null) {
        argsForZygote.add("--seinfo=" + seInfo);
    }

    if (instructionSet != null) {
        argsForZygote.add("--instruction-set=" + instructionSet);
    }

    if (appDataDir != null) {
        argsForZygote.add("--app-data-dir=" + appDataDir);
    }

    if (invokeWith != null) {
        argsForZygote.add("--invoke-with");
        argsForZygote.add(invokeWith);
    }

    argsForZygote.add(processClass);

    if (extraArgs != null) {
        for (String arg : extraArgs) {
            argsForZygote.add(arg);
        }
    }

    synchronized(mLock) {
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
    
这里也基本上没做什么操作,只是设置进程创建之前的参数设定。在这里有必要看一下最后一行代码中出现一个方法,就是openZygoteSocketIfNeeded这个方法。这个方法将会为我们创建一个Sokcet并连接到系统Zygote中Socket。

2、openZygoteSocketIfNeeded

private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");

    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            primaryZygoteState = ZygoteState.connect(mSocket);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
        }
    }

    if (primaryZygoteState.matches(abi)) {
        return primaryZygoteState;
    }

    // The primary zygote didn't match. Try the secondary.
    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        try {
            secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
        }
    }

    if (secondaryZygoteState.matches(abi)) {
        return secondaryZygoteState;
    }

    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

在这里就打开的用于传输启动线程数据的socket,在后面我们将参数进行传递

3,zygoteSendArgsAndGetResult进行socket数据传输

private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList args)
        throws ZygoteStartFailedEx {
    try {
        // Throw early if any of the arguments are malformed. This means we can
        // avoid writing a partial response to the zygote.
        int sz = args.size();
        for (int i = 0; i < sz; i++) {
            if (args.get(i).indexOf('\n') >= 0) {
                throw new ZygoteStartFailedEx("embedded newlines not allowed");
            }
        }

        /**
         * See com.android.internal.os.SystemZygoteInit.readArgumentList()
         * Presently the wire format to the zygote process is:
         * a) a count of arguments (argc, in essence)
         * b) a number of newline-separated argument strings equal to count
         *
         * After the zygote process reads these it will write the pid of
         * the child or -1 on failure, followed by boolean to
         * indicate whether a wrapper process was used.
         */
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;

        writer.write(Integer.toString(args.size()));
        writer.newLine();

        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            writer.write(arg);
            writer.newLine();
        }

        writer.flush();

        // Should there be a timeout on this?
        Process.ProcessStartResult result = new Process.ProcessStartResult();

        // Always read the entire result from the input stream to avoid leaving
        // bytes in the stream for future process starts to accidentally stumble
        // upon.
        result.pid = inputStream.readInt();
        result.usingWrapper = inputStream.readBoolean();

        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

这个函数没啥说的,就是通过已经创建的Socket连接将数据传输。重点看下面。

四、Zygote启动Activity进程

在Android系统启动之初会启动Zygote进程,之后所有的进程都需要通过Zygote来进行创建。zygote会在framework层启动一个socket来等待连接,然后进行相应操作。因此要看Zygote创建Socket操作,Zygote在framework层是在ZygoteInit类中。

1、zygoteInit创建Socket

public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();

    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();

    // Zygote goes into its own process group.
    try {
        Os.setpgid(0, 0);
    } catch (ErrnoException ex) {
        throw new RuntimeException("Failed to setpgid(0,0)", ex);
    }

    final Runnable caller;
    //这一部分就不在贴出来了,这些是在Android系统其中之初的时候运行的代码
        ......
        Log.i(TAG, "Accepting command socket connections");

        // The select loop returns early in the child process after a fork and
        // loops forever in the zygote.
        caller = zygoteServer.runSelectLoop(abiList);
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        throw ex;
    } finally {
        zygoteServer.closeServerSocket();
    }

    // We're in the child process and have exited the select loop. Proceed to execute the
    // command.
    if (caller != null) {
        caller.run();
    }
}
这个函数是在Zygote启动之初在FrameWork运行的代码,在启动之初要启动SystemServer前面就有许多与SystemServer启动相关的代码,和本篇文章关系不大也就直接略过。和APP启动有关的主要是在后面zygoteServer中创建的Runnable的caller,下面看一下这个函数

2、ZygoteServer中runSelectLoop

Runnable runSelectLoop(String abiList) {
    ArrayList fds = new ArrayList();
    ArrayList peers = new ArrayList();

    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {//没有数据交互
                continue;
            }

            if (i == 0) {//没有连接
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                try {
                    ZygoteConnection connection = peers.get(i);//获取连接
                    final Runnable command = connection.processOneCommand(this);//获取连接之后处理连接

                    if (mIsForkChild) {
                        // We're in the child. We should always have a command to run at this
                        // stage if processOneCommand hasn't called "exec".
                        if (command == null) {
                            throw new IllegalStateException("command == null");
                        }

                        return command;
                    } else {
                        // We're in the server - we should never have any commands to run.
                        if (command != null) {
                            throw new IllegalStateException("command != null");
                        }

                        // We don't know whether the remote side of the socket was closed or
                        // not until we attempt to read from it from processOneCommand. This shows up as
                        // a regular POLLIN event in our regular processing loop.
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(i);
                            fds.remove(i);
                        }
                    }
                } catch (Exception e) {
                    if (!mIsForkChild) {
                        // We're in the server so any exception here is one that has taken place
                        // pre-fork while processing commands or reading / writing from the
                        // control socket. Make a loud noise about any such exceptions so that
                        // we know exactly what failed and why.

                        Slog.e(TAG, "Exception executing zygote command: ", e);

                        // Make sure the socket is closed so that the other end knows immediately
                        // that something has gone wrong and doesn't time out waiting for a
                        // response.
                        ZygoteConnection conn = peers.remove(i);
                        conn.closeSocket();

                        fds.remove(i);
                    } else {
                        // We're in the child so any exception caught here has happened post
                        // fork and before we execute ActivityThread.main (or any other main()
                        // method). Log the details of the exception and bring down the process.
                        Log.e(TAG, "Caught post-fork exception in child process.", e);
                        throw e;
                    }
                }
            }
        }
    }
}

从ZygoteInit到ZygoteServer中这部分代码主要是分离出来一个线程然后进行等待Socket的连接,等有Socket连接就执行ZygoteConnect中的方法来进行相应操作。

3、ZygoteConnect中processOneCommand

Runnable processOneCommand(ZygoteServer zygoteServer) {
    String args[];
    Arguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        args = readArgumentList();//获取参数
        descriptors = mSocket.getAncillaryFileDescriptors();//获取Socket的描述符
    } catch (IOException ex) {
        throw new IllegalStateException("IOException on command socket", ex);
    }

    // readArgumentList returns null only when it has reached EOF with no available
    // data to read. This will only happen when the remote socket has disconnected.
    if (args == null) {
        isEof = true;
        return null;
    }

    int pid = -1;
    FileDescriptor childPipeFd = null;
    FileDescriptor serverPipeFd = null;

    parsedArgs = new Arguments(args);

    if (parsedArgs.abiListQuery) {
        handleAbiListQuery();
        return null;
    }
    ......
    //创建进程
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
            parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
            parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
            parsedArgs.appDataDir);

    try {
        if (pid == 0) {//子进程,也就是创建好的APP的进程
            // in child
            zygoteServer.setForkChild();

            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;

            //在创建好的子进程中处理相应操作
            return handleChildProc(parsedArgs, descriptors, childPipeFd);
        } else {
            // In the parent. A pid < 0 indicates a failure and will be handled in
            // handleParentProc.
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

这段代码中主要是对Socket传输过来的参数进行处理,然后根据这些参数创建进程。根据返回值判断是否是创建好的子进程,如果是创建好的子进程,则进行APP启动的其他操作

4、ZygoteConnect中handleChildPro

private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
                                 FileDescriptor pipeFd) {
    /**
     * By the time we get here, the native code has closed the two actual Zygote
     * socket connections, and substituted /dev/null in their place.  The LocalSocket
     * objects still need to be closed properly.
     */

    closeSocket();//进程已经创建完毕,因此需要关闭Socket连接
    if (descriptors != null) {
        try {
            Os.dup2(descriptors[0], STDIN_FILENO);
            Os.dup2(descriptors[1], STDOUT_FILENO);
            Os.dup2(descriptors[2], STDERR_FILENO);

            for (FileDescriptor fd: descriptors) {
                IoUtils.closeQuietly(fd);
            }
        } catch (ErrnoException ex) {
            Log.e(TAG, "Error reopening stdio", ex);
        }
    }

    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }

    // End of the postFork event.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    if (parsedArgs.invokeWith != null) {//在一开始地方可以翻出来invokeWidth是为null的
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd, parsedArgs.remainingArgs);

        // Should not get here.
        throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
    } else {//看这里
        return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
                null /* classLoader */);
    }
}

在创建进程完成之后Socket也必须关闭了,然后进行下一步操作

5、ZygoteInit中zygoteInit

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

这段代码也没有多少,还要涉及到native的代码,关于native代码不做讲解,直接看后面RuntineInit的applicationInit的代码,在最后这段代码中启动要启动的类。

四、最后RuntimeInit启动ActivityThread

1、RuntimeInit的applicationInit

protected static Runnable applicationInit(int targetSdkVersion, 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);

    // We want to be fairly aggressive about heap utilization, to avoid
    // holding on to a lot of memory that isn't needed.
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);

    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);//根据上面解析好的参数启动类
}

在这里有一个参数解析的过程,肯定要解析出来要启动的类。最后才是启动,看一下参数解析

2、RuntimeInit的Arguments

  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++];//这个解析出来就是ActivityThread了
        startArgs = new String[args.length - curArg];
        System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
    }
}
这里代码也是非常少,解析出来了要启动的类ActivityThread。关于启动类在前面已经说过了,可以回去看看。

3、RuntimeInit的findStaticMain

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 });//找到静态main函数
    } 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);
}

到这里基本上就结束了,通过反射找到ActivityThread类,然后获取静态main函数

4、RuntimeInit的MethodAndArgsCaller

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 {
            mMethod.invoke(null, new Object[] { mArgs });//执行类中的main方法
        } 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);
        }
    }
}
这个类中算是执行了目标方法

五、Runnable执行run方法

到这里然并卵没有结束,要找到运行run的地方啊。看来需要回头看看首先看看ZygoteServer中的runSelectLoop的方法,在这里好像有线索

if (mIsForkChild) {
    // We're in the child. We should always have a command to run at this
    // stage if processOneCommand hasn't called "exec".
    if (command == null) {
        throw new IllegalStateException("command == null");
    }

    return command;

这里看出来是要在子线程中才会返回,那么这变量在何处进行设置了呢?仔细看了看,是在ZygoteConnection中的processOneCommand方法有这样一段代码

if (pid == 0) {
     // in child
     zygoteServer.setForkChild();

     zygoteServer.closeServerSocket();
     IoUtils.closeQuietly(serverPipeFd);
     serverPipeFd = null;

     return handleChildProc(parsedArgs, descriptors, childPipeFd);
 } else {
     // In the parent. A pid < 0 indicates a failure and will be handled in
     // handleParentProc.
     IoUtils.closeQuietly(childPipeFd);
     childPipeFd = null;
     handleParentProc(pid, descriptors, serverPipeFd);
     return null;
 }
在这里执行了ZygoteServer.setForkChild()将通知现在已经处于子进程中。最后回到ZygoteInit看看这段代码

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

在这里可以看到执行了run方法,前提是现在已经处于子进程中,至此全部讲完。


总结

关于ActivityThread在新的进程中启动的过程已经讲完,涉及到的东西还是不少。至于启动ActivityThread的main函数之后执行的操作不再本篇文章讲解的范围,剩下也就是Activity生命周期的东西。






你可能感兴趣的:(Android系统)