In the last article in-depth understanding of the Android Activity start process, the application root Activity start process through the system source code comb again, which also has a detail is Android every application is an application process, and the application process does not happen in a vacuum, This article continues to explore the Android application process startup process through the system source code (source code based on Android 10).

  • Android source code

  • First, as usual, look at a brain map to get a first impression in your own mind

ActivityManagerService requests Zygote to start the application process

AMS handles basic data for starting applications

  • In an article in the second section analysis mentioned ActivityStackSupervisor startSpecificActivityLocked method

frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, Boolean checkConfig) {// Whether the Activity application process is ready for Final WindowProcessController WPC = mService.getProcessController(r.processName, r.info.applicationInfo.uid); boolean knownToBeDead =false;
        if(wpc ! = null && wpc.hasThread()) { //1 try { realStartActivityLocked(r, wpc, andResume, checkConfig); / / 2return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e); }... }... try { ....... // Post a message to start the process to avoid possible deadlock of calling into AMS with the // ATMS lock held Avoid deadlock final Message MSG = PooledLambda. ObtainMessage (ActivityManagerInternal: : startProcess, mService mAmInternal, r.processName, r.info.applicationInfo, knownToBeDead,"activity", r.intent.getComponent()); //3 mService.mH.sendMessage(msg); }... }Copy the code
  • By source code comments 1 and 2 if the application process before already exists, continues to launch the Activity logic, or to note 3, we see ActivityManagerInternal key parts: : startProcess, “: :” is a Java 8 new features, This is equivalent to calling ActivityManagerInternal’s startProcess method, While ActivityManagerInternal (frameworks/base/core/Java/android/app/ActivityManagerInternal. Java) is an abstract class, it is the Activity manager local service interface, It is implemented as the AMS internal class LocalService, which registers with the AMS startup process, Through LocalServices (frameworks/base/core/Java/com/android/server/LocalServices. Java) registered, the use of such similar to ServiceManager, the difference is that The services registered here are not Binder objects and can only be used in the same process (SystemServer process). The ActivityManagerInternal implementation class LocalService is the LocalService of the SystemServer process, which is registered with the LocalService. AMS runs in the SystemServer process. You can use LocalService directly. So the startProcess method of LocalService is called in comment 3

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

 @Override
        public void startProcess(String processName, ApplicationInfo info,
                boolean knownToBeDead, 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) {
                    startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
                            new HostingRecord(hostingType, hostingName),
                            false /* allowWhileBooting */, false /* isolated */,
                            true/* keepIfLarge */); / /}}... } final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) {returnmProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); / / 2}Copy the code
  • The startProcessLocked method is called in comment 1 above, and the startProcessLocked method of ProcessList, the management class that handles the Activity process, is called in comment 2 above

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

@GuardedBy("mService") final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { long startTime = SystemClock.elapsedRealtime(); ProcessRecord app; .if (app == null) {
            checkSlow(startTime, "startProcess: creating new process record"); app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord); / / 1if (app == null) {
                Slog.w(TAG, "Failed making new process record for "
                        + processName + "/" + info.uid + " isolated=" + isolated);
                return null;
            }
            app.crashHandler = crashHandler;
            app.isolatedEntryPoint = entryPoint;
            app.isolatedEntryPointArgs = entryPointArgs;
            checkSlow(startTime, "startProcess: done creating new process record"); }... final boolean success = startProcessLocked(app, hostingRecord, abiOverride); //2 checkSlow(startTime,"startProcess: done starting proc!");
        return success ? app : null;
    }
Copy the code
  • From the above code, the ProcessRecord object is created in comment 1, which holds complete information about the particular process currently running, that is, the application process that needs to be started, followed by comment 2, which continues to call startProcessLocked

frameworks/base/services/core/java/com/android/server/am/ProcessList.java

/ * * * @return {@code true} if process start is successful, false otherwise.
     * @param app
     * @param hostingRecord
     * @param disableHiddenApiChecks
     * @param abiOverride
     */
    @GuardedBy("mService")
    boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
            boolean disableHiddenApiChecks, boolean mountExtStorageFull, String abiOverride) { try { .... int uid = app.uid; //1 int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;if(! app.isolated) { ...... /* * Add a shared application and a configuration file GID so that the application can share certain resources (such as shared libraries) and access user-wide resources */if (ArrayUtils.isEmpty(permGids)) {
                    gids = new int[3];
                } else{ gids = new int[permGids.length + 3]; System.arraycopy(permGids, 0, gids, 3, permGids.length); } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid)); gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid)); / / 2... }... final String entryPoint ="android.app.ActivityThread"; / / 3returnstartProcessLocked(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); //4 } catch (RuntimeException e) { ....... } } boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal, String seInfo, String requiredAbi, String instructionSet, String invokeWith, long startTime) { .......if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
            if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
                    "Posting procStart msg for "+ app.toShortString()); mService.mProcStartHandler.post(() -> { try { final Process.ProcessStartResult startResult = startProcess(app.hostingRecord, entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime); //5 synchronized (mService) { handleProcessStartedLocked(app, startResult, startSeq); } } catch (RuntimeException e) { ..... });return true;
        } else{ try { final Process.ProcessStartResult startResult = startProcess(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); //6 handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper, startSeq,false);
            } catch (RuntimeException e) {
              ........  
            }
            returnapp.pid > 0; }}Copy the code
  • By the above code comments get the application user id 1, 2 out of access to the user group id, process for the application to provide user group resource access, note 3 to the entryPoint assignment for android. The app. ActivityThread, remember this value first, subsequent analysis will continue to mention it; The startProcessLocked method is then called at comment 4, where comments 5 and 6 end up calling the startProcess method of the ProcessList class, and look below

frameworks/base/services/core/java/com/android/server/am/ProcessList.java


/**
     * The currently running application zygotes.
     */
    final ProcessMap<AppZygote> mAppZygotes = new ProcessMap<AppZygote>();

    /**
     * The processes that are forked off an application zygote.
     */
    final ArrayMap<AppZygote, ArrayList<ProcessRecord>> mAppZygoteProcesses =
            new ArrayMap<AppZygote, ArrayList<ProcessRecord>>();

 private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, 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, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); / / 1}else if (hostingRecord.usesAppZygote()) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

                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,
                        /*useUsapPool=*/ false, new String[] {PROC_START_SEQ_IDENT + app.startSeq}); / / 2}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,
                        new String[] {PROC_START_SEQ_IDENT + app.startSeq});//3
            }
            ....
            returnstartResult; }... }Copy the code
  • From the above code, the startProcess method handles different logic depending on which Process is currently started. Comment 1 starts the webView Process, comment 2 handles the user AppZygote, and comment 3 is the exit for the newly created application Process, which calls the start method of the Process class. Process is a utility class for managing operating system processes, followed by its start method

Process Processes startup parameters into the Zygote Process

frameworks/base/core/java/android/os/Process.java

/**
     * State associated with the zygote process.
     * @hide
     */
    public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess(); //1

    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,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*useUsapPool=*/ true, zygoteArgs); / / 2}Copy the code
  • From the above code, in conjunction with comments 1 and 2, the start method of the ZygoteProcess class is called, and ZygoteProcess maintains communication with Zygote. This class is responsible for opening the socket on Zygote and starting the process on behalf of Porcess. Then you see the start method of the ZygoteProcess class

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,
                                                  boolean useUsapPool,
                                                  @Nullable String[] zygoteArgs) {
        .....
        try {
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false, packageName, useUsapPool, zygoteArgs); / / 1}... }Copy the code
  • From the above code comment 1, we call the start method of the ZygoteProcess class again, and look below

frameworks/base/core/java/android/os/ZygoteProcess.java

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, boolean useUsapPool, @Nullable String[] extraArgs) throws ZygoteStartFailedEx { ArrayList<String> argsForZygote = new ArrayList<>(); //1 // --runtime-args, --setuid=, --setgid=, // and --setgroups= must go first argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        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");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
            argsForZygote.add("--mount-external-full"); }... synchronized(mLock) { // The USAP pool can not be usedif the application will not use the systems graphics
            // driver.  If that driver is requested use the Zygote application start path.
            returnzygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), useUsapPool, argsForZygote); / / 2}}Copy the code
  • By the above code, note 1 creates a collection argsForZygote used to store the start application process parameters, and then call the zygoteSendArgsAndGetResult method, and the first parameter to this method calls the openZygoteSocketIfNeeded method

frameworks/base/core/java/android/os/ZygoteProcess.java

private Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args)
            throws ZygoteStartFailedEx {
       .......

        if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) {
            try {
                returnattemptUsapSendArgsAndGetResult(zygoteState, msgStr); //1 } catch (IOException ex) { // If there was an IOException using the USAP pool we willlog the error and
                // attempt to start the process through the Zygote.
                Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "+ ex.getMessage()); }}returnattemptZygoteSendArgsAndGetResult(zygoteState, msgStr); //2 } private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { try { attemptConnectionToPrimaryZygote(); / / 3if (primaryZygoteState.matches(abi)) {
                return primaryZygoteState;
            }

            if(mZygoteSecondarySocketAddress ! = null) { // The primary zygote didn't match. Try the secondary. attemptConnectionToSecondaryZygote(); //4 if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } } } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to zygote", ioe); } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }Copy the code
  • From the above code, zygoteState is passed in at comment 1 and comment 2. This represents the zygoteState class, which is the ZygoteProcess static inner class that holds the state of communication with Zygote. Its return is handled by the openZygoteSocketIfNeeded method, So see comments 3 and 4, respectively, calls the attemptConnectionToPrimaryZygote method and attemptConnectionToSecondaryZygote method, it has to do and Zygote process start loading configuration file, here is not opened, Two methods have the same logic, see one attemptConnectionToPrimaryZygote method directly

frameworks/base/core/java/android/os/ZygoteProcess.java

 /**
     * Creates a ZygoteState for the primary zygote if it doesn't exist or has been disconnected. */ @GuardedBy("mLock") private void attemptConnectionToPrimaryZygote() throws IOException { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { primaryZygoteState = ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress); //1 maybeSetApiBlacklistExemptions(primaryZygoteState, false); maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState); maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState); }}Copy the code
  • Note 1 calls the connect method of ZygoteState to open the Socket connection. MZygoteSocketAddress is the Socket service named Zygote

ActivityManagerService asks Zygote to start the application process sequence diagram

  • This section concludes with a review of the above steps using a sequence diagram

Zygote starts the application process

  • After the analysis in the previous section, AMS finally requests to Zygote process through Socket interprocess communication. Zygote, which means Zygote in English, is started to create the Android virtual machine. Other application processes, such as the SystemServer process where THE AMS service resides, are forked to create Zygote. The details of the Zygote process startup process are another story, but this article will focus on the application process startup process, starting with the Main method of ZygoteInit

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

 @UnsupportedAppUsage
    public static void main(String argv[]) {
        .....
        Runnable caller; //1 try { ........ boolean startSystemServer =false; //2 String zygoteSocketName ="zygote"; //3 String abiList = null; booleanenableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {//4
                    startSystemServer = true; }... } final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME); . Zygote.initNativeState(isPrimaryZygote); / / 5... zygoteServer = new ZygoteServer(isPrimaryZygote); / / 6if (startSystemServer) { 
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); //7
            }

            // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller= zygoteServer.runSelectLoop(abiList); / / 8}... // We're in the child process and have exited the select loop. Proceed to execute the // command. if (caller ! = null) { caller.run(); / / 9}}Copy the code

Note 1 creates a request object of type Runnable representing the object that Zygote requested to obtain the application process. Zygote: zygote: zygote: zygote: zygote: zygote: zygote: zygote: zygote: Zygote: Zygote: Zygote The name of the Socket connection is zygote; Note 6 creates the ZygoteServer object, which can be understood as a server for Zygote to support Socket process communication, while the runSelectLoop method in note 8 is the key method for Zygote processes to wait for AMS requests to start application processes. Note 9 is there for now

frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

Runnable runSelectLoop(String abiList) {
        ......
        while (true) {

            while (--pollIndex >= 0) {
                if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                    continue;
                }

                if (pollIndex == 0) {
                    // Zygote server socket

                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor());

                } else if(pollIndex < usapPoolEventFDIndex) {// Session socket accepted from the Zygote server socket accept Session socket from the Zygote server socket try {  ZygoteConnection connection = peers.get(pollIndex); final Runnablecommand= connection.processOneCommand(this); / / 1...return command; }... }Copy the code
  • From the above code, the ZygoteConnection’s processOneCommand method is called in comment 1 in an infinite loop waiting for the request to be received

Gets the application process

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

/**
     * Reads one start command from the command socket. If successful, a child is forked and a
     * {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
     * process. {@code null} is always returned in the parent process (the zygote).
     *
     * If the client closes the socket, an {@code EOF} condition is set.which callers can test
     * forby calling {@code ZygoteConnection.isClosedByPeer}. */ Runnable processOneCommand(ZygoteServer zygoteServer) { String args[]; ZygoteArguments parsedArgs = null; FileDescriptor[] descriptors; try { args = Zygote.readArgumentList(mSocketReader); / / 1... }... 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.mTargetSdkVersion); //2 try {if (pid == 0) { //3
                // in child
                zygoteServer.setForkChild();

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

                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.mStartChildZygote);
            } 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);
                returnnull; }}... }Copy the code
  • The parameters to start the application process are retrieved from comment 1 above, and the ForkandWte method of the Zygote class is called directly from comment 2

frameworks/base/core/java/com/android/internal/os/Zygote.java

    /**
     * Forks a new VM instance.  The current VM must have been started
     * @return 0 if this is the child, pid of the child
     * if this is the parent, or -1 on error.
     */
    public 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,
            int targetSdkVersion) {
        ZygoteHooks.preFork();
        // Resets nice priority forzygote process. resetNicePriority(); int pid = nativeForkAndSpecialize( uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, fdsToIgnore, startChildZygote, instructionSet, appDataDir); / / 1return pid;
    }
Copy the code
  • In the code note 1 above, the Native method nativeForkandWpeck communicates with the base layer to copy and fork the application process that is to be started. In this paper, we focus on the general process and the base Native implementation does not continue. Interested friends can continue to follow up frameworks/base/core/jni/com_android_internal_os_Zygote CPP view. The Forkandwpecte method returns 0 as child, the application process, and -1 as the parent, so ZygoteConnection’s processOneCommand method starts the application process. ZygoteConnection’s handleChildProc method is then called

frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

    private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
        ..........
        } else {
            if(! isZygote) {returnZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); / / 1}else {
                returnZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); }}}Copy the code
  • From the source code above, the application process will go to comment 1 and call the ZygoteInit method of the ZygoteInit class

Create an ActivityThread for your application

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

 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(); / / 1returnRuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); / / 2}Copy the code
  • The Native method creates a pool of Binder threads for the current application process, and the current application has the ability to communicate with the Binder. The applicationInit method of RuntimeInit is called in the second comment

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { ...... final Arguments args = new Arguments(argv); / / 1...return findStaticMain(args.startClass, args.startArgs, classLoader);2
    }
Copy the code
  • By the above code, note 1 with AMS passed in the request parameters, including the android. The app. ActivityThread, namely 2 place args. StartClass represents the value of the then continue to read findStaticMain method

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) { Class<? > cl; try { cl = Class.forName(className,true, classLoader); //1 } 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 }); / / 2}... /* * This throw gets caughtin 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); }Copy the code
  • By the above code, note 1 reflection for the android. The app. ActivityThread, namely application process ActivityThread, obtain the main method of the ActivityThread 2 place, The Runnable object is then returned as MethodAndArgsCaller

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

/**
     * Helper class whichholds a method and arguments and can call them. This is used as part of * a trampoline to get rid of the initial process  setup stack frames. */ 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 voidrun() { try { mMethod.invoke(null, new Object[] { mArgs }); / / 1}... }}Copy the code
  • The main method of the application process ActivityThread (comment 1) and ZygoteInit (comment 9) are already in the application process, so the run method of type Runnable caller will be called. The run method for MethodAndArgsCaller calls the Main method of ActivityThread, which acts as the main management class for each application thread. At this point, the application process is started, and the last article, When the ATMS communicates with the application Binder through IApplicationThread as an inner class of ActivityThread, the Binder then invokes the ActivityThread’s performLaunchActivity method to start the Activity.

Zygote startup application process sequence diagram

  • This section concludes with a review of the above steps using a sequence diagram

conclusion

Start the processes involved in the process

  • In combination with the previous article, we have an in-depth understanding of the Android Activity startup process and summarized the following interprocess invocation diagram involved in the application process startup

The last

  • From The above understanding of The Source Code, there are still many details waiting for us to explore, so “Read The Fucking Source Code”, with a heart of awe to move forward. If there is something wrong in the article, please leave a comment in the comment area. We can discuss it together and make progress together. If you find my article helpful, please also give me a like and attention.

reference

  • Book Android Advanced Decryption
  • Android source code

About me

Blog:

  • Personal blog
  • The Denver nuggets
  • Jane’s book
  • Github

Mail: