Android应用程序的启动流程是什么

其他教程   发布日期:2024年10月07日   浏览次数:339

本篇内容介绍了“Android应用程序的启动流程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

    应用进程的启动流程

    本文基于Android 11,主要分析应用程序的启动流程,会直接定位到ActivityStackSupervisor.startSpecificActivity函数开始,因为该函数前面的内容主要在Activity的启动流程中,可以通过这部分的文章来阅读。

    看源码流程,需要戒骄戒躁,心态好。配合源码使用,建议先收藏,夜深人静,心血来潮再看。

    通过分析应用进程的启动流程,可以得到:

    • 在Framework层,现在不止有AMS负责请求Zygote进程创建新进程,还有ATMS、ActivityStarter、ActivityTaskManger、ActivityTaskS在协助分担一些参数和逻辑的检查。

    • 每个进程都是通过fork Zygote进程而来,且获得Java虚拟机。也就是说每一个应用进程都有自己的虚拟机。

    • 应用进程是通过Soket去请求Zygote进程fork自己的。

    • 每个进程都有自己的Binder线程池用于IPC。

    • 每个应用进程的主线程在ActivityThread,其main函数会创建消息循环机制。

    1、ActivityStackSupervisor.startSpecificActivity

    ATMS有一个ProcessMap<WindowProcessController>类型的mProcessNames ,用于存储封装了已启动进程信息ProcessRecord和窗口信息Windows的WindowProcessController实例。WindowProcessController用于协调ActivityManger管理ProcessReocrd和WindwManger管理WIndow和Activity的关系。

    1. void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    2. // Is this activity's application already running?
    3. final WindowProcessController wpc =
    4. mService.getProcessController(r.processName, r.info.applicationInfo.uid);
    5. boolean knownToBeDead = false;
    6. if (wpc != null && wpc.hasThread()) {
    7. realStartActivityLocked(r, wpc, andResume, checkConfig);
    8. return;
    9. ...
    10. knownToBeDead = true;
    11. }
    12. r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
    13. final boolean isTop = andResume && r.isTopRunningActivity();
    14. mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
    15. }

    这里的mService是ActivityTaskManagerService的实例,通过getProcessController函数获得当前wpc对象,判断当前启动应用进程是否启动wpc != null && wpc.hasThread(),如果条件成立,则开始真正启动一个未启动过的Activity,通过realStartActivityLocked;条件不成立,则调用mService的startProcessAsync启动当前Activity的所在的进程。即startSpecificActivity函数是启动进程和启动Activity的一个分界点。

    2、ATMS.startProcessAsync

    PooledLambda.obtainMessage函数是Lambda的调用方式,表示调用ActivityManagerInternal的startProcess函数,后续则是其参数。并返回一个Message对象,发给Handler类型的mH。

    1. void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,
    2. String hostingType) {
    3. final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,
    4. mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,
    5. isTop, hostingType, activity.intent.getComponent());
    6. mH.sendMessage(m);
    7. }

    抽象类ActivityManagerInternal的继承类定义在ActivityManagerService的内部类LocalService。

    1. public final class LocalService extends ActivityManagerInternal

    3、LocalService.startProcess

    1. @Override
    2. public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,
    3. boolean isTop, String hostingType, ComponentName hostingName) {
    4. startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,
    5. new HostingRecord(hostingType, hostingName, isTop),
    6. ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,
    7. false /* isolated */, true /* keepIfLarge */);
    8. }

    4、startProcessLocked函数

    1. final ProcessRecord startProcessLocked(String processName,
    2. ApplicationInfo info, boolean knownToBeDead, int intentFlags,
    3. HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
    4. boolean isolated, boolean keepIfLarge) {
    5. return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
    6. hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
    7. keepIfLarge, null /* ABI override */, null /* entryPoint */,
    8. null /* entryPointArgs */, null /* crashHandler */);
    9. }

    5、ProcessList.startProcessLocked

    ProcessList类的startProcessLocked函数,有几个重载函数,第一个调用。

    在 !isolated,判断了启动IntentFlag是否后台运行,是的话,直接拒绝。否则清理AMS中发生过Crash的进程(当前应用)。

    分析一:创立当前应用进程的描述ProcessRecord。

    判断当前系统是否启动完毕,未启动完毕,将进程信息缓存到AMS的mProcessesOnHold中。

    分析二:调用了另外一个重载函数。

    1. final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
    2. boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
    3. int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,
    4. boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs,
    5. Runnable crashHandler) {
    6. long startTime = SystemClock.uptimeMillis();
    7. ProcessRecord app;
    8. //isolated传递进来是false,
    9. if (!isolated) {
    10. //从mProcessNames缓存获取,由于是首次创建,null
    11. app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
    12. checkSlow(startTime, "startProcess: after getProcessRecord");
    13. //判断要启动进程是否后台运行,直接return null
    14. if ((intentFlags &amp; Intent.FLAG_FROM_BACKGROUND) != 0) {
    15. if (mService.mAppErrors.isBadProcessLocked(info)) {
    16. return null;
    17. }
    18. } else {
    19. //重置进程的crash状态,使其处于正常状态
    20. mService.mAppErrors.resetProcessCrashTimeLocked(info);
    21. if (mService.mAppErrors.isBadProcessLocked(info)) {
    22. mService.mAppErrors.clearBadProcessLocked(info);
    23. if (app != null) {
    24. app.bad = false;
    25. }
    26. }
    27. }
    28. } else {
    29. app = null;
    30. }
    31. ProcessRecord precedence = null;
    32. if (app != null &amp;&amp; app.pid &gt; 0) {
    33. if ((!knownToBeDead &amp;&amp; !app.killed) || app.thread == null) {
    34. app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
    35. return app;
    36. }
    37. ProcessList.killProcessGroup(app.uid, app.pid);
    38. precedence = app;
    39. app = null;
    40. }
    41. if (app == null) {
    42. // 分析一、创建新的应用进程描述ProcessRocrd
    43. //内部会将自己添加到mProcessNames中
    44. app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);
    45. if (app == null) {
    46. return null;
    47. }
    48. //此时三者都是null
    49. app.crashHandler = crashHandler;
    50. app.isolatedEntryPoint = entryPoint;
    51. app.isolatedEntryPointArgs = entryPointArgs;
    52. if (precedence != null) {
    53. app.mPrecedence = precedence;
    54. precedence.mSuccessor = app;
    55. }
    56. } else {
    57. app.addPackage(info.packageName, info.longVersionCode, mService.mProcessStats);
    58. }
    59. // If the system is not ready yet, then hold off on starting this
    60. // process until it is.
    61. if (!mService.mProcessesReady
    62. &amp;&amp; !mService.isAllowedWhileBooting(info)
    63. &amp;&amp; !allowWhileBooting) {
    64. if (!mService.mProcessesOnHold.contains(app)) {
    65. mService.mProcessesOnHold.add(app);
    66. }
    67. if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
    68. "System not ready, putting on hold: " + app);
    69. checkSlow(startTime, "startProcess: returning with proc on hold");
    70. return app;
    71. }
    72. 分析二:
    73. final boolean success =
    74. startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
    75. checkSlow(startTime, "startProcess: done starting proc!");
    76. return success ? app : null;
    77. }

    6、ProcessList.startProcessLocked重载

    再次调用另外一个重载函数。

    1. final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
    2. int zygotePolicyFlags, String abiOverride) {
    3. return startProcessLocked(app, hostingRecord, zygotePolicyFlags,
    4. false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,
    5. false /* mountExtStorageFull */, abiOverride);
    6. }

    重载函数,这个重载函数处理逻辑很长,主要给前面创建的ProcessRecord类型的app设置各种属性。例如外部存储挂载模式,应用进程运行模式,abi架构等等,其中包括最重要一点就是分析一,确定要启动进程的的类名:android.app.ActivityThread。分析二,继续调用重载函数。

    1. boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
    2. int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,
    3. boolean mountExtStorageFull, String abiOverride) {
    4. ...
    5. app.gids = gids;
    6. app.setRequiredAbi(requiredAbi);
    7. app.instructionSet = instructionSet;
    8. final String seInfo = app.info.seInfo
    9. + (TextUtils.isEmpty(app.info.seInfoUser) ? "" : app.info.seInfoUser);
    10. //分析一:确定要启动应用程序的类名
    11. final String entryPoint = "android.app.ActivityThread";
    12. //分析二:调用另外一个重载函数
    13. return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
    14. runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
    15. instructionSet, invokeWith, startTime);
    16. } catch (RuntimeException e) {
    17. ...
    18. }
    19. }

    重载函数:也是设置一些属性,然后调用startProcess函数。

    1. boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
    2. int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
    3. String seInfo, String requiredAbi, String instructionSet, String invokeWith,
    4. long startTime) {
    5. ...
    6. final Process.ProcessStartResult startResult = startProcess(hostingRecord,
    7. entryPoint, app,
    8. uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
    9. requiredAbi, instructionSet, invokeWith, startTime);
    10. handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
    11. startSeq, false);
    12. ...
    13. }
    14. }

    7、ProcessList.startProcess

    ProcessList类的startProcess函数会根据hostingRecord属性mHostingZygote判断走不同的创建分支,前面创建使用默认值,所以走了else分支。通过 Process.start函数创建新的应用进程。

    Process.start的一路调用:

    1. Process.start=&gt;ZygoteProcess.start=&gt;ZygoteState.start=&gt;ZygoteState.startViaZygote

    8、ZygoteState.startViaZygote

    startViaZygote函数,主要是将传递进来的参数拼接成成字符串和收集起来。其中processClass是

    1. private Process.ProcessStartResult startViaZygote(...)
    2. throws ZygoteStartFailedEx {
    3. //根据传递进来的参数,拼接成字符串并收集到ArrayList&lt;String&gt;类型argsForZygote
    4. //将作为新应用程序的主函数的参数
    5. return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
    6. zygotePolicyFlags,
    7. argsForZygote);
    8. }

    9、ZygoteState.openZygoteSocketIfNeeded

    zygoteSendArgsAndGetResult的第一个参数,调用了openZygoteSocketIfNeeded函数。尝试建立与Socket的连接(如果之前未建立的话)。我们知道Zygote进程在创建的过程,会调用runSelectLoop函数,创建Server端的Socket,一直等待来自AMS的Client端的Socket创建进程请求。

    1. private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    2. try {
    3. //建立和Zygote的Socket连接
    4. attemptConnectionToPrimaryZygote();
    5. //匹配abi的架构。在Zygote的创建对应四种模式:32,32_64和64,64_32
    6. //32,64
    7. if (primaryZygoteState.matches(abi)) {
    8. return primaryZygoteState;
    9. }
    10. //主要架构模式不配,匹配第二种 32_64,64_32
    11. if (mZygoteSecondarySocketAddress != null) {
    12. // The primary zygote didn't match. Try the secondary.
    13. attemptConnectionToSecondaryZygote();
    14. if (secondaryZygoteState.matches(abi)) {
    15. return secondaryZygoteState;
    16. }
    17. }
    18. } catch (IOException ioe) {
    19. throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
    20. }
    21. throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    22. }

    attemptConnectionToPrimaryZygote函数主要通过底层的LocalSocket创建与Zygote进程的Socket连接,并获得输入流zygoteInputStream和输出流zygoteOutputWriter。

    1. private void attemptConnectionToPrimaryZygote() throws IOException {
    2. if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
    3. primaryZygoteState =
    4. ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
    5. maybeSetApiBlacklistExemptions(primaryZygoteState, false);
    6. maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
    7. }
    8. }

    和Zygote进程的Server端Socket建立连接后,就是开始往Socket写数据了。

    10、attemptZygoteSendArgsAndGetResult

    回到第8步调用了zygoteSendArgsAndGetResult函数,又调用了attemptZygoteSendArgsAndGetResult函数。

    1. zygoteSendArgsAndGetResult=&gt;attemptZygoteSendArgsAndGetResult

    11、attemptZygoteSendArgsAndGetResult

    到这里,通过Socket的方式向Zygote进程写进前面拼接好的参数,Zygote在Server端的Socket接收到数据之后,会执行创建动作。在返回的result.pid>=0表示创建成功,并运行在新的进程。

    1. private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
    2. ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
    3. try {
    4. final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
    5. final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
    6. zygoteWriter.write(msgStr);
    7. zygoteWriter.flush();
    8. Process.ProcessStartResult result = new Process.ProcessStartResult();
    9. result.pid = zygoteInputStream.readInt();
    10. result.usingWrapper = zygoteInputStream.readBoolean();
    11. if (result.pid &lt; 0) {
    12. throw new ZygoteStartFailedEx("fork() failed");
    13. }
    14. return result;
    15. } catch (IOException ex) {
    16. zygoteState.close();
    17. Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
    18. + ex.toString());
    19. throw new ZygoteStartFailedEx(ex);
    20. }
    21. }

    12、Zygote.main

    在Zygote的启动流程过程,调用了ZygoteInit的main函数,因为Zygote是通过fork自身来创建其他进程,所以需要根据传递进来的参数,进行判断是启动什么类型的进程,例如自身isPrimaryZygote=true,或者SystemServer进程。然后通过ZygoteServer.runSelectLoop函数,等待其他进程请求创建新的进程。

    1. public static void main(String argv[]) {
    2. ZygoteServer zygoteServer = null;
    3. Runnable caller;
    4. try {
    5. ...
    6. boolean startSystemServer = false;
    7. String zygoteSocketName = "zygote";
    8. String abiList = null;
    9. boolean enableLazyPreload = false;
    10. for (int i = 1; i &lt; argv.length; i++) {
    11. if ("start-system-server".equals(argv[i])) {
    12. startSystemServer = true; //判断是否SystemServer进程
    13. } else if ("--enable-lazy-preload".equals(argv[i])) {
    14. enableLazyPreload = true;
    15. } else if (argv[i].startsWith(ABI_LIST_ARG)) {
    16. abiList = argv[i].substring(ABI_LIST_ARG.length());
    17. } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
    18. //SCOKET_NAME_ARG="--socket-name=",根据参数得到SocketName
    19. zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
    20. } else {
    21. throw new RuntimeException("Unknown command line argument: " + argv[i]);
    22. }
    23. }
    24. //PRIMARY_SOCKET_NAME=zygote
    25. final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
    26. gcAndFinalize();
    27. Zygote.initNativeState(isPrimaryZygote);
    28. ZygoteHooks.stopZygoteNoThreadCreation();
    29. zygoteServer = new ZygoteServer(isPrimaryZygote);
    30. if (startSystemServer) {
    31. //启动SystemServer进程
    32. Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
    33. if (r != null) {
    34. r.run();
    35. return;
    36. }
    37. }
    38. //循环等待AMS来请求创建新的进程
    39. caller = zygoteServer.runSelectLoop(abiList);
    40. } catch (Throwable ex) {
    41. Log.e(TAG, "System zygote died with exception", ex);
    42. throw ex;
    43. } finally {
    44. if (zygoteServer != null) {
    45. zygoteServer.closeServerSocket();
    46. }
    47. }
    48. //调用新的进程主函数
    49. if (caller != null) {
    50. caller.run();
    51. }
    52. }

    13、ZygoteServer.runSelectLoo

    这里只关注ZygoteServer.runSelectLoop函数,接受Socket客户端数据。

    1. /**
    2. * Runs the zygote process's select loop. Accepts new connections as
    3. * they happen, and reads commands from connections one spawn-request's
    4. * worth at a time.
    5. */
    6. Runnable runSelectLoop(String abiList) {
    7. while (true) {
    8. ...
    9. ZygoteConnection connection = peers.get(pollIndex);
    10. final Runnable command = connection.processOneCommand(this);
    11. ...
    12. if (mIsForkChild) {
    13. return command;
    14. }
    15. ....
    16. }
    17. }

    14、ZygoteConnection.processOneCommand

    runSelctLoop主要是从循环中检测是否有连接建立,建立之后执行ZygoteConnection的processOneCommand函数,并返回一个Runable类型的command对象。

    1. Runnable processOneCommand(ZygoteServer zygoteServer) {
    2. ...
    3. args = Zygote.readArgumentList(mSocketReader);
    4. //根据参数内容,作其他类型的处理
    5. ...
    6. //创建进程,调用底层nativeForkAndSpecialize方法,通过fork当前进程来创建一个子线程。
    7. pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
    8. parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
    9. parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
    10. parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mIsTopApp,
    11. parsedArgs.mPkgDataInfoList, parsedArgs.mWhitelistedDataInfoList,
    12. parsedArgs.mBindMountAppDataDirs, parsedArgs.mBindMountAppStorageDirs);
    13. ...
    14. if (pid == 0) {
    15. //设置mIsForkChild=true
    16. zygoteServer.setForkChild();
    17. //关闭Socket连接
    18. zygoteServer.closeServerSocket();
    19. IoUtils.closeQuietly(serverPipeFd);
    20. serverPipeFd = null;
    21. //执行子进程内容
    22. return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
    23. }
    24. ...
    25. }

    15、handleChildProc

    handleChildProc函数。

    1. private Runnable handleChildProc(ZygoteArguments parsedArgs,
    2. FileDescriptor pipeFd, boolean isZygote) {
    3. ...
    4. if (!isZygote) {
    5. return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
    6. parsedArgs.mDisabledCompatChanges,
    7. parsedArgs.mRemainingArgs, null /* classLoader */);
    8. } else {
    9. return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
    10. parsedArgs.mRemainingArgs, null /* classLoader */);
    11. }
    12. }

    16、 ZygoteInit.zygoteInit

    1. public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
    2. String[] argv, ClassLoader classLoader) {
    3. RuntimeInit.commonInit();
    4. ZygoteInit.nativeZygoteInit();//为新进程创建Binder线程池
    5. return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
    6. classLoader);
    7. }

    以前还以为每个进程共用一个Binder线程池,现在知道每个进程都有自己的Binder线程池进行IPC。

    17、RuntimeInit.applicationInit

    1. protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
    2. String[] argv, ClassLoader classLoader) {
    3. final Arguments args = new Arguments(argv);
    4. return findStaticMain(args.startClass, args.startArgs, classLoader);
    5. }

    这里的args.startClass就是Socket客户端传递下来的android.app.ActivityThread。

    18、RuntimeInit.findStaticMain

    RuntimeInit.findStaticMain函数主要通过反射创建ActivityThread类的实例,并反射主函数main,然后封装到MethodAndArgsCaller实例中返回。

    1. protected static Runnable findStaticMain(String className, String[] argv,
    2. ClassLoader classLoader) {
    3. ...
    4. Class&lt;?&gt; cl = Class.forName(className, true, classLoader);
    5. Method m = cl.getMethod("main", new Class[] {

    以上就是Android应用程序的启动流程是什么的详细内容,更多关于Android应用程序的启动流程是什么的资料请关注九品源码其它相关文章!