深入理解Android之應用程序進程啓動流程

在上一篇文章深入理解Android 之 Activity啓動流程中,應用程序根Activity的啓動過程通過系統源碼梳理了一遍,其中還有一個細節便是Android每個應用都是都是一個應用進程,而應用進程不會憑空產生,本文則通過系統源碼繼續探究Android應用程序進程啓動流程(文中源碼基於Android 10 )。

  • Android源碼地址

  • 首先照例還是先看一個腦圖,在自己大腦中能產生初步印象

ActivityManagerService請求Zygote啓動應用程序進程

AMS處理啓動應用程序基本數據

  • 上一篇文章第二小節分析中提到了ActivityStackSupervisor的startSpecificActivityLocked的方法

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

void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
        // Activity應用程序進程是否已經準備好
        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); //2
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }
        .......
        }

        .......
        try {
           .......
            // Post message to start process to avoid possible deadlock of calling into AMS with the
            // ATMS lock held.  Hnadler發消息 避免死鎖
            final Message msg = PooledLambda.obtainMessage(
                    ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
                    r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());//3
            mService.mH.sendMessage(msg);
        }
        ........
    }
  • 由以前源碼註釋1和2如果應用程序進程已經存在,則繼續啓動Activity邏輯,否則來到註釋3出,我們看到關鍵部分ActivityManagerInternal::startProcess,"::"是Java 8 新增特性,相當於調用了ActivityManagerInternal的startProcess方法,而ActivityManagerInternal(frameworks/base/core/java/android/app/ActivityManagerInternal.java)是一個抽象類,它是Activity管理器本地服務接口,它的實現爲AMS的內部類LocalService,它註冊在AMS啓動的過程,通過LocalServices(frameworks/base/core/java/com/android/server/LocalServices.java)註冊,此類的使用方式與ServiceManager相似,不同之處在於,此處註冊的服務不是Binder對象,並且只能在同一進程(SystemServer進程)中使用。也就是說ActivityManagerInternal實現類LocalService是SystemServer進程的本地服務Service,通過本地服務註冊到LocalServices中,而AMS也是運行在SystemServer進程,則可以直接使用LocalService。所以註釋3處調用了LocalService的startProcess方法

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) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
                null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
                null /* crashHandler */); //2 
    }        

  • 由以上源碼註釋1處調用了startProcessLocked方法,由註釋2處則調用了 ProcessList的 startProcessLocked方法,ProcessList是處理Activity進程的管理類,接着往下看

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);//1
            if (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;
    }
  • 由以上代碼,註釋1處創建了ProcessRecord對象,它保存了當前正在運行的特定進程的完整信息,也就是需要啓動的應用程序進程,接着註釋2繼續調用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) {
               ......

                /*
                 *添加共享的應用程序和配置文件GID,以便應用程序可以共享 某些資源(如共享庫)並訪問用戶範圍的資源
                 */
                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";//3

            return startProcessLocked(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) {
              ........  
            }
            return app.pid > 0;
        }
    }
  • 由以上代碼註釋1處獲取了應用程序的用戶id,註釋2出獲取了用戶組ID,爲應用程序進程提供用戶組資源訪問權限,註釋3處給entryPoint賦值爲android.app.ActivityThread,先記住這個值,後續分析還會繼續提起它;註釋4處接着調用了startProcessLocked方法,在該方法中註釋5和6最終都是調用了ProcessList類的startProcess方法,接着往下看

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
            }
            ....
            return startResult;
        } 
        ......
    }

  • 由以上代碼,startProcess方法會根據當前啓動的是什麼進程處理不同的邏輯,註釋1是啓動webview進程,註釋2處理用戶AppZygote,而註釋3處纔是出路新創建的應用程序進程,也就是調用了Process類的start方法,Process是
    用於管理操作系統進程的工具類,接着看它的start方法

Process 處理啓動參數到Zygote進程

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
    }

  • 由以上代碼,結合註釋1和註釋2則調用了ZygoteProcess類的start方法,ZygoteProcess保持與Zygote 的通信狀態。 此類負責對Zygote 打開套接字,並代表Porcess啓動進程。接着看到ZygoteProcess類的start方法

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
        }
        .....
    }
  • 由以上代碼註釋1,又調用了ZygoteProcess類的start方法,接着往下看

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 used if the application will not use the systems graphics
            // driver.  If that driver is requested use the Zygote application start path.
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              useUsapPool,
                                              argsForZygote);//2
        }
    }
  • 由以上代碼,註釋1處創建了一個集合argsForZygote用來保存啓動應用程序進程參數,接着又調用了zygoteSendArgsAndGetResult方法,而該方法第一個參數又調用了openZygoteSocketIfNeeded方法

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 {
                return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);//1
            } 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);//2
    }
    
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        try {
            attemptConnectionToPrimaryZygote();//3

            if (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);
    }
  • 由以上代碼,註釋1處和註釋2都傳入了zygoteState,它代表的是ZygoteState類,它是ZygoteProcess靜態內部類,保存了與 Zygote 進行通信的狀態,而它的返回是由openZygoteSocketIfNeeded方法處理的,所以看到註釋3和註釋4分別調用了attemptConnectionToPrimaryZygote方法和attemptConnectionToSecondaryZygote方法,這和Zygote進程啓動加載的配置文件有關,這裏就不展開了,兩個方法邏輯基本相同,直接看到其中一個attemptConnectionToPrimaryZygote方法

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);
        }
    }
  • 由註釋1調用ZygoteState的connect方法來打開Socket連接,mZygoteSocketAddress則是名稱爲zygote的 Socket 服務

ActivityManagerService請求Zygote啓動應用程序進程時序圖

  • 本小節最後還是通過時序圖來對上面的步驟進行回顧

Zygote啓動應用程序進程

  • 經過上一小節分析,AMS最終是通過Socket方式進程間通信請求到了Zygote進程。Zygote英文爲受精卵的意思,它啓動過程創建了Android 虛擬機,其他應用程序進程則通過fork複製Zygote來創建應用程序進程,比如AMS服務所在的SystemServer進程,關於Zygote進程進程的啓動過程細節又是另一部分內容了,本文則先只分析應用程序進程啓動的過程,接下來從ZygoteInit的main方法開始

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;
            boolean enableLazyPreload = 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);//6

            if (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
        }
    }

由以上是縮短精簡的ZygoteInit的main方法,註釋1處創建了一個Runnable類型的請求對象代表此次請求Zygote獲取應用進程的對象;結合註釋2、4和7如果是Android系統啓動過程,則會啓動核心進程SystemServer,否則是啓動其他應用程序進程,註釋3出設置Socket連接名稱爲zygote,註釋5出則初始化了Zygote的狀態環境,包括支持套接字的環境,安全環境等,同時也包括Socket連接的名稱爲zygote;註釋6創建了ZygoteServer對象,它可以理解爲Zygote支持Socket進程通信的服務端,而在註釋8的 runSelectLoop 方法則是Zygote進程等待接收AMS請求啓動應用程序進程的關鍵方法,註釋9先放着,接着往下看

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  從Zygote服務器套接字接受會話套接字

                    try {
                        ZygoteConnection connection = peers.get(pollIndex);
                        final Runnable command = connection.processOneCommand(this); //1

                        ......
                            return command;
                        } 
        .......                
    }
  • 由以上代碼,通過一個死循環等待接收請求,註釋1處則調用了ZygoteConnection的processOneCommand方法,接着往下看

獲取應用程序進程

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
     * for by 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);
                return null;
            }
        } 
        ......
    }
  • 由以上代碼註釋1處獲取了啓動應用程序進程的參數,看到註釋2處,直接調用了Zygote類的forkAndSpecialize方法

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 for zygote process.
        resetNicePriority();
        int pid = nativeForkAndSpecialize(
                uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                fdsToIgnore, startChildZygote, instructionSet, appDataDir);//1
        return pid;
    }
  • 由以上代碼註釋1處,通過Native方法nativeForkAndSpecialize與底層通信複製fork出應用即將要啓動的應用程序進程,本文則關注大致流程,底層Native實現則不再繼續展開,有興趣朋友可以繼續跟進frameworks/base/core/jni/com_android_internal_os_Zygote.cpp查看。根據forkAndSpecialize方法的註釋也可以明白,該方法返回0則爲child,也就是應用程序進程,-1則爲父進程,所以這裏再次回到ZygoteConnection的processOneCommand方法,啓動的是應用程序進程,則在註釋3出pid=0 此時已經處於應用程序進程了,接着繼續調用ZygoteConnection的
    handleChildProc方法

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

    private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
        ..........
        } else {
            if (!isZygote) {
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */); //1
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            }
        }
    }
  • 由以上源碼,啓動的是應用程序進程則會走到註釋1處調用ZygoteInit類的zygoteInit方法

創建應用程序的ActivityThread

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();//1
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); //2
    }
  • 由以上源碼,註釋1出的Native方法會創建當前應用程序進程的Binder線程池,則當前應用程序就擁有了Binder通信的能力,註釋2處接着調用了RuntimeInit的applicationInit方法

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
    }
  • 由以上代碼,註釋1處處理AMS請求中傳遞過來的參數,這其中就包括android.app.ActivityThread,也就是註釋2處args.startClass代表的值,接着繼續看findStaticMain方法

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 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);
    }
  • 由以上代碼,註釋1處反射獲取了android.app.ActivityThread,也就是應用程序進程的ActivityThread,註釋2處獲取了ActivityThread的main方法,然後返回了Runnable對象爲MethodAndArgsCaller

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

/**
     * Helper class which holds 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 void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs }); //1
            } 
            ...
        }
    }
  • 由以上代碼,註釋1處代表應用程序進程ActivityThread的main方法,結合本小節開頭的從ZygoteInit的main方法的註釋9,目前已經處於應用程序進程,則會調用Runnable類型caller的run方法,也就是MethodAndArgsCaller的run方法,由以上代碼註釋1處,則會調用ActivityThread的main方法,而ActivityThread作爲每個應程序主線程的管理類,到此,應用程序進程啓動完成,接着上一篇文章,當ATMS與應用程序Binder通信通過IApplicationThread爲ActivityThread的內部類,然後調用ActivityThread的performLaunchActivity方法來啓動Activity

Zygote啓動應用程序進程時序圖

  • 本小節最後還是通過時序圖來對上面的步驟進行回顧

總結

啓動過程涉及的進程

參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章