要想启动一个应用,首先要保证这个应用所需要的进程已经启动过。AMS在启动一个应用的时候,事先会检查这个应用的进程是否存在, 不存在的话就会请求Zygote进程去fork一个新进程, 这样应用进程就会获得 Zygote进程在启动时创建的虚拟机实例.
当然在应用进程创建的过程中除了获取虚拟机实例外,还创建了Binder线程池和消息循环, 这样运行在应用进程中的应用程序就可以方便地使用Binder进行线程间通信以及处理消息了.
本篇文章流程的梳理是基于Android10源码. 阅读本篇文章前,请先阅读一下 Android 进程间通信机制(三) 系统进程与应用进程通信
应用进程创建的流程比较复杂, 这里分为两个步骤, 分别是AMS发送启动应用进程的请求,以及Zygote接收请求并创建应用进程.
这里先给出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是trueif (!isolated) {//第一次进来app肯定是nullapp = 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 listapp.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为nullif (app == null) {//这个是google的,用于调试卡顿的,不过除了特别有问题一般情况不会出现问题,//50ms去掉系统或许更快,如果是给用户的稳定版本可以考虑把这段调试代码删除checkSlow(startTime, "startProcess: creating new process record");//此处是new ProcessRecordapp = 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 listapp.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初始值是falseif (!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_WRITEmountExternal = 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作为应用默认的入口函数entryPointfinal 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 argsForZygote = new ArrayList<>();// --runtime-args, --setuid=, --setgid=,// and --setgroups= must go firstargsForZygote.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);}}
好了,到这里,第一阶段就告一段落了.
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方法看起
@UnsupportedAppUsagepublic static void main(String argv[]) {
....
....//启动system_server进程默认值是falseboolean startSystemServer = false;//Socket的名字是zygoteString 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 childzygoteServer.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) {
....//关闭自己的SocketcloseSocket();//此处设置进程名字为之前传进来的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 mainreturn 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.writeEventEventLogger.setReporter(new EventLoggingReporter());//配置文件目录在/data/misc/user/1000final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());//设置认证相关的目录cacerts-added,cacerts-removedTrustedCertificateStore.setDefaultUserDirectory(configDir);//设置进程名字为,这个很快在handleBindApplication时就会给修改Process.setArgV0("");//消息队列初始化,主进程是不允许退出的,无法调用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(newLogPrinter(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源码分析总结, 也参考了刘望舒<进阶解密>第三章内容, 时序图是根据源码绘制出来的,主线流程大体是正确的, 可以供大家参考,谢谢!
后续有新的细节理解,再更新到文章来.