Android 进程间通信机制(四) 应用进程启动过程

一. 简介

        要想启动一个应用,首先要保证这个应用所需要的进程已经启动过。AMS在启动一个应用的时候,事先会检查这个应用的进程是否存在, 不存在的话就会请求Zygote进程去fork一个新进程, 这样应用进程就会获得 Zygote进程在启动时创建的虚拟机实例.

        当然在应用进程创建的过程中除了获取虚拟机实例外,还创建了Binder线程池和消息循环, 这样运行在应用进程中的应用程序就可以方便地使用Binder进行线程间通信以及处理消息了.

        本篇文章流程的梳理是基于Android10源码.   阅读本篇文章前,请先阅读一下 Android 进程间通信机制(三) 系统进程与应用进程通信  

二. 应用进程启动过程

        应用进程创建的流程比较复杂,  这里分为两个步骤, 分别是AMS发送启动应用进程的请求,以及Zygote接收请求并创建应用进程.

2.1  AMS发送启动应用进程请求

         这里先给出AMS发送启动应用进程请求过程的时序图:

        AMS 如果想要启应用进程,就需要向Zygote进程发送创建应用进程的请求, AMS通过startProcessLocked方法向Zygote进程发送请求

// ActivityManagerService.java

 @GuardedBy("this")
    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 */);
    }

接着调到ProcessList.java中的startProcessLocked方法   (13个参数)

@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;
        //第一次走进来 isolated(孤立应用)是false,knownToBeDead是true
        if (!isolated) {
            //第一次进来app肯定是null
            app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
            checkSlow(startTime, "startProcess: after getProcessRecord");
            //设置了后台运行,桌面启动应用一般都不会走这里
            if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
                // If we are in the background, then check to see if this process
                // is bad.  If so, we will just silently fail.
                //重新计算崩溃次数(crash大于等于2次服务将不会再启动)
                if (mService.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);
                mService.mAppErrors.resetProcessCrashTimeLocked(info);
                if (mService.mAppErrors.isBadProcessLocked(info)) {
                    EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
                            UserHandle.getUserId(info.uid), info.uid,
                            info.processName);
                    mService.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) {
            // UNISOC: bug1017202, Ensure the top activity host process been start successfully.
            if ((!knownToBeDead && !app.killed)
                    || (app.thread == null
                        && !(mService.mActivityTaskManager.
                            isProcessStartedForTopActivity(app.getWindowProcessController()) 
                            && app.killed))) {
                // 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.longVersionCode, mService.mProcessStats);
                checkSlow(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) Slog.v(TAG_PROCESSES, "App died: " + app);
            checkSlow(startTime, "startProcess: bad proc running, killing");
            ProcessList.killProcessGroup(app.uid, app.pid);
            mService.handleAppDiedLocked(app, true, true);
            checkSlow(startTime, "startProcess: done killing old proc");
        }

        //第一次是走的这里 app为null
        if (app == null) {
            //这个是google的,用于调试卡顿的,不过除了特别有问题一般情况不会出现问题,
            //50ms去掉系统或许更快,如果是给用户的稳定版本可以考虑把这段调试代码删除
            checkSlow(startTime, "startProcess: creating new process record");
            //此处是new ProcessRecord
            app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);
            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;
            //新建ProcessRecord完成,该监控操作(newProcessRecordLocked)完成
            checkSlow(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.longVersionCode, mService.mProcessStats);
            checkSlow(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 (!mService.mProcessesReady
                && !mService.isAllowedWhileBooting(info)
                && !allowWhileBooting) {
            if (!mService.mProcessesOnHold.contains(app)) {
                mService.mProcessesOnHold.add(app);
            }
            if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
                    "System not ready, putting on hold: " + app);
            checkSlow(startTime, "startProcess: returning with proc on hold");
            return app;
        }

        checkSlow(startTime, "startProcess: stepping in to startProcess");
        //开始启动进程
        final boolean success = startProcessLocked(app, hostingRecord, abiOverride);
        checkSlow(startTime, "startProcess: done starting proc!");
        return success ? app : null;
    }

接着继续调用ProcessList中的startProcessLocked方法  (5个参数)

@GuardedBy("mService")
    boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
            boolean disableHiddenApiChecks, boolean mountExtStorageFull,
            String abiOverride) {
        if (app.pendingStart) {
            return true;
        }
        long startTime = SystemClock.elapsedRealtime();
        //第一次启动app.pid == -1,不走这里
        if (app.pid > 0 && app.pid != ActivityManagerService.MY_PID) {
            checkSlow(startTime, "startProcess: removing from pids map");
            mService.mPidsSelfLocked.remove(app);
            mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
            checkSlow(startTime, "startProcess: done removing from pids map");
            app.setPid(0);
            app.startSeq = 0;
        }

        if (DEBUG_PROCESSES && mService.mProcessesOnHold.contains(app)) Slog.v(
                TAG_PROCESSES,
                "startProcessLocked removing on hold: " + app);
        mService.mProcessesOnHold.remove(app);

        checkSlow(startTime, "startProcess: starting to update cpu stats");
        //启动进程也会更新CPU状态
        mService.updateCpuStats();
        checkSlow(startTime, "startProcess: done updating cpu stats");

        try {
            try {
                final int userId = UserHandle.getUserId(app.uid);
                //用于检测是否可以启动,如:是否安装,是否正在冻屏等
                AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }

            int uid = app.uid;
            int[] gids = null;
            int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
            //isolated初始值是false
            if (!app.isolated) {
                int[] permGids = null;
                try {
                    checkSlow(startTime, "startProcess: getting gids from package manager");
                    final IPackageManager pm = AppGlobals.getPackageManager();
                    //返回应用用户组的gid,如果是uid不一样,同一个应用该值也会不一样
                    permGids = pm.getPackageGids(app.info.packageName,
                            MATCH_DIRECT_BOOT_AUTO, app.userId);
                    if (StorageManager.hasIsolatedStorage() && mountExtStorageFull) {
                        mountExternal = Zygote.MOUNT_EXTERNAL_FULL;
                    } else {
                        StorageManagerInternal storageManagerInternal = LocalServices.getService(
                                StorageManagerInternal.class);
                        //获取应用读写外部存储的权限
                        //如果是孤立应用(uid是99000-99999)将返回MOUNT_EXTERNAL_NONE;
                        //能读返回MOUNT_EXTERNAL_READ,能写返回MOUNT_EXTERNAL_WRITE
                        mountExternal = storageManagerInternal.getExternalStorageMountMode(uid,
                                app.info.packageName);
                    }
                } catch (RemoteException e) {
                    throw e.rethrowAsRuntimeException();
                }


    ......
    ......


 //android:multiArch="true"代表所有架构都支持,一般都不设置,
            //一般应用库文件需要判断是否32位还算64位,判断方法使用
            //com_android_internal_content_NativeLibraryHelper.cpp的findSupportedAbi
            //requiredAbi就是为了兼容32位&64位系统设计的
            String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;
            if (requiredAbi == null) {
                //此处如果应用没有设置实在32位还是64位运行的化,
                //默认使用属性值ro.product.cpu.abilist的第一个值arm64-v8a(64bit),
                //armeabi-v7a(32bit),armeabi(32bit)
                requiredAbi = Build.SUPPORTED_ABIS[0];
            }

            String instructionSet = null;
            if (app.info.primaryCpuAbi != null) {
                //通过应用的库文件获取虚拟机要使用那种参数
                instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);


.....
.....


         // Start the process.  It will either succeed and return a result containing
            // the PID of the new process, or else throw a RuntimeException.
            //将ActivityThread作为应用默认的入口函数entryPoint
            final String entryPoint = "android.app.ActivityThread";
            //此处才是调用Process.start启动进程的地方
            boolean startSuccess =  startProcessLocked(hostingRecord, entryPoint,
                        app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi,
                        instructionSet, invokeWith, startTime);

.........
.........

}

继续调用ProcessList中的startProcessLocked方法  (12个参数)

 @GuardedBy("mService")
    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) {

....
....
    //创建预fork进程的参数
    PreForkArgs preforkArgs = new PreForkArgs(entryPoint, app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                app.info.targetSdkVersion, app.seInfo, requiredAbi, instructionSet,
                app.info.dataDir, invokeWith, app.info.packageName,
                new String[] {PROC_START_SEQ_IDENT + app.startSeq});




  try {
//启动进程
                    final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
                            entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
                            app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);
                    synchronized (mService) {
                        handleProcessStartedLocked(app, startResult, startSeq);
                        mService.notifyProcessStart(app.info.packageName, app.hostingRecord.getType(), startResult.pid);
                        mService.preforkStart(preforkArgs);

....
....
                    }
}

继续调用 startProcess方法(12个参数)

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) {


.....
.....    
//通过log打印,走到是 else分支
                startResult = mService.handlePreForkStartProcess(preforkArgs);
                Slog.e("mytest", "==ProcessList 1900====else===");
                if (startResult == null) {
                    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});
                }
                //modify for prefork blank process end
            }


}

接下来,我们就查看Process的start方法

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

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

在Process的start方法 调用了 ZygoteProcess start 方法,其中 zygoteProcess类
用于保持与 Zygote 进程的通信状态。该 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) {
.....
    return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, useUsapPool, zygoteArgs);
.....
}

ZygoteProcess的 start方法调用了 startViaZygote方法 如下所示:

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 {
.....
     //创建字符串列表 argsForZygote ,并将应用进程的启动参数保存在argsForZygote中
     ArrayList<String> argsForZygote = new ArrayList<>();

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


.....

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

接下来就是与Zygote进程socket通信

 @GuardedBy("mLock")
    private void attemptConnectionToPrimaryZygote() throws IOException {
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            primaryZygoteState =
                    //与Zygote进程socket通信
                    ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);

            maybeSetApiBlacklistExemptions(primaryZygoteState, false);
            maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
            maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
        }
    }

好了,到这里,第一阶段就告一段落了.

2.2 Zygote 接收请求并创建应用程序进程

zygote 接收请求并建应用进程的时序图:

开机运行app_process进程(别称Zygote进程)     

(init.zygote*.rc->app_process)->app_main.main->ZygoteInit.main

我们知道Zygote受精卵进程是由init进程创建,如下通过图可知:init进程是Zygote64受精卵进程的父进程,而system_server是通过zygote64受精卵进程创建的。(pid是该进程的id,ppid是其父进程的id)

 我们先从ZygoteInit.java 的main方法看起

 @UnsupportedAppUsage
    public static void main(String argv[]) {
....
....
            //启动system_server进程默认值是false
            boolean startSystemServer = false;
            //Socket的名字是zygote
            String zygoteSocketName = "zygote";
            String abiList = null;
            boolean enableLazyPreload = false;
            for (int i = 1; i < argv.length; i++) {
                //只有当传入的参数带有 start-system-server 时,才会启动,实质上系统只有初次开机的时候会启动, 其他都是去启动应用进程
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = true;


          //系统开机第一次会走这里,他就是区去fork system_server进程
          //而我们是分析的创建应用进程,所以不会走这里
          if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@code r == null} in the parent (zygote) process, and {@code r != null} in the
                // child (system_server) process.
                if (r != null) {
                    r.run();
                    return;
                }
            }

          //而是走这里, 一直等待 AMS 请求创建新的应用进程
         // The select loop returns early in the child process after a fork and
            // loops forever in the zygote.
            caller = zygoteServer.runSelectLoop(abiList);
......
}
下面来查看ZygoteServer.java runSelectLoop方法:
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
  /**
     * Runs the zygote process's select loop. Accepts new connections as
     * they happen, and reads commands from connections one spawn-request's
     * worth at a time.
     */
    Runnable runSelectLoop(String abiList) {

        ....
      //这里是一个while死循环
      while (true) {
            fetchUsapPoolPolicyPropsWithMinInterval();

     

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

                        // TODO (chriswailes): Is this extra check necessary?
                        if (mIsForkChild) {


    .....
}

这段代码所做工作:

1) 循环遍历等待Socket缓冲区有可读的数据
2) Socket.connect时会创建新的ZygoteConnection
3) ZygoteConnection执行processOneCommand方法
4) 创建子进程后,子进程退出循环,父进程继续等待下一个Socket数据

接下来继续去看 ZygoteConnection.java 的 processOneCommand方法

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

  Runnable processOneCommand(ZygoteServer zygoteServer) {
  ....
  ....
        try {
            //获取启动应用进程的参数
            args = Zygote.readArgumentList(mSocketReader);

            // TODO (chriswailes): Remove this and add an assert.
            descriptors = mSocket.getAncillaryFileDescriptors();
        } catch (IOException ex) {
            throw new IllegalStateException("IOException on command socket", ex);
        }

     //创建应用进程
     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);


    
     try {
            //如果是子进程pid会等于0,父进程此处pid会返回子进程的pid
            //当前代码逻辑运行在子进程中,(也就是新创建的应用进程)
            if (pid == 0) {
                // 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;
            }
.....
}

如果 pid 等于0 则说明当前代码逻辑运行在新创建的子进程(应用进程 )中,这时就会调用 handleChildProc 方法来处理应用程序进程, 我们继续来看

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

 private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
            FileDescriptor pipeFd, boolean isZygote) {
....
    //关闭自己的Socket
    closeSocket();

    //此处设置进程名字为之前传进来的processName
    //设置进程的名字,这个时候通过ps就可以看到进程名字变成应用声明的进程(如果没有定义android:process那么默认该进程名字就是应用的包名)
   if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName);
        }
...
    } else {
            if (!isZygote) {
                //ZygoteInit.zygoteInit子进程的初始化
                return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            } else {
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            }
        }
}

handleChildProc 方法中调用了 Zygotelnit的zygotelnit方法 

frameworks/base/core/java/com/android/internal/os/Zygotelnit.java
 public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {

....
        //重新定向log的输入地方,此处设置log输出到Android log中
        RuntimeInit.redirectLogStreams();

        //一些通用设置的初始化
        RuntimeInit.commonInit();
        //在新的应用进程中创建Binder线程池
        ZygoteInit.nativeZygoteInit();
        
        //应用初始化,此处是接下来运行的地方
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

接下来就调用到了RuntimeInit.java 中的applicationInit方法:

frameworks/base/core/java/com/and oid/internal/os/Runtimelnit.java

 protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
....

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

}

第一个参数 args.startClass,它指的就是上面提到的参数 android.app.ActivityThread

接下来去调用 findStaticMain 方法

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {

     try {  
            //获取android.app.ActivityThread类的 Class对象
            cl = Class.forName(className, true, classLoader);


      //通过反射获取ActivityThread.java的 main Method对象
      Method m;
        try {
            m = cl.getMethod("main", new Class[] { String[].class });

       
      //调用main方法
      return new MethodAndArgsCaller(m, argv);
}



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 {
                //这里就跳转到 ActivityThread.java 的main方法了
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
.....
}

说到这里, 应用进程已经启动完成,将进入应用相关流程, 接下来看看 ActivityThread.java 的main方法中

frameworks/base/core/java/android/app/ActivityThread.java

    public static void main(String[] args) {
        //默认是没有用到SamplingProfilerIntegration的,
        //该类用于监听性能数据,包含进程名字、应用信息、线程启动与关闭,
        //还有默认persist.sys.profiler_ms毫秒dump一次该进程堆栈信息
        SamplingProfilerIntegration.start();

        //在严格模式或者调试的时候打开,默认不打卡
        CloseGuard.setEnabled(false);
       .......

        //初始化环境(这里主要是存储设备的环境,用user id初始化)
        Environment.initForCurrentUser();

        //主要是libcore中使用event log的方法,Reporter的report类似于EventLog.writeEvent
        EventLogger.setReporter(new EventLoggingReporter());

        //配置文件目录在/data/misc/user/1000
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());

        //设置认证相关的目录cacerts-added,cacerts-removed
        TrustedCertificateStore.setDefaultUserDirectory(configDir);

        //设置进程名字为<pre-initialized>,这个很快在handleBindApplication时就会给修改
        Process.setArgV0("<pre-initialized>");

        //消息队列初始化,主进程是不允许退出的,无法调用MessageQueue.quit退出
        Looper.prepareMainLooper();

       .......

        ActivityThread thread = new ActivityThread();
        //新建一个ActivityThread并attach附着,这个跟接下去的attachApplication相关
        thread.attach(false);

        if (sMainThreadHandler == null) {
            //获取thread的handler,将其作为应用的主线程
            sMainThreadHandler = thread.getHandler();
        }

        if (false) {
            //用户调试log,用于消息队列Message的事件分发log输出,
            //调试消息队列的时候可以打开
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }

        //Looper.loop()里面是个for (;;)死循环,只要Message不为null,会一直运行
        //Looper.loop() -> MessageQueue.next() 
        //-> nativePollOnce(android_os_MessageQueue.cpp) 
        //->(pollOnce/pollInner/epoll_wait) Looper.cpp,
        //这个Message==null情况只有调用MessageQueue.quit才会发生,
        //目前没有看到主动调用MessageQueue.quit,故这个消息队列循环是不会退出的
        Looper.loop();

        //如果进入到这里代表程序出错了,这里程序正常运行是不会进来的
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

三. 致谢

        本文是基于Android10源码分析总结, 也参考了刘望舒<进阶解密>第三章内容,   时序图是根据源码绘制出来的,主线流程大体是正确的, 可以供大家参考,谢谢!

四. 待更新

        后续有新的细节理解,再更新到文章来.

        

猜你喜欢

转载自blog.csdn.net/u012514113/article/details/129649290