Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 604|回复: 0

[默认分类] Android源码解析之(十一)-->应用进程启动流程

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-1 10:00:05 | 显示全部楼层 |阅读模式


      转载请标明出处:一片枫叶的专栏
    本节主要是通过分析Activity的启动过程介绍应用程序进程的启动流程。关于Android的应用进程在android guide中有这样的一段描述:

      By default, every application runs in its own Linux process. Android starts the process when any of the application’s components need to be executed, then shuts down the process when it’s no longer needed or when the system must recover memory for other applications.
    每一个android应用默认都是在他自己的linux进程中运行。android操作系统会在这个android应用中的组件需要被执行的时候启动这个应用进程,并且会在这个应用进程没有任何组件执行或者是系统需要为其他应用申请更多内存的时候杀死这个应用进程。所以当我们需要启动这个应用的四大组件之一的时候如果这个应用的进程还没有启动,那么就会先启动这个应用程序进程。
    在上一篇文章中我们简要的介绍了Launcher的启动流程,在SystemServer进程执行完成,各种系统服务启动完成之后,会调用ActivityManagerService中的systemReady()方法,在systemReady()方法中会执行Launcher启动的相关逻辑了,具体可以参考: android源码解析之(十)–>Launcher启动流程
    Launcher应用程序在启动过程中会通过PackageManagerService服务请求查询系统所有的已安装应用的包名,图标和应用名称等信息,然后填充到Launcher中的Adapter中,这样点击某一项应用图标的时候就可以根据该图标的包名和启动Activity的类名初始化Intent对象,然后调用startActivity(Intent)启动相关的应用程序了。
    其实android中应用进程可以通过许多方式启动,比如启动一个Activity,启动一个Service,启动一个ContentProvider或者是一个BroadcastReceiver,也就是说我们可以通过启动四大组件的方式启动应用进程,在应用进程没有启动的时候,如果我们通过启动这些组件,这时候系统会判断当前这些组件所需要的应用进程是否已经启动,若没有的话,则会启动应用进程。
    这里我们通过Launcher简单分析一下应用进程的启动流程。通过上一篇Launcher启动流程,我们知道每一个launcher中的图标对应着一个应用报名和启动activity类名,查看LauncherActivity中的图标点击事件:
    1. [code]protected void onListItemClick(ListView l, View v, int position, long id) {
    2.         Intent intent = intentForPosition(position);
    3.         startActivity(intent);
    4.     }
    复制代码
    [/code]
    在通过应用包名和启动activity类名构造完成Intent之后,我们调用了startActivity方法来启动这个activity,很明显的,当前这个应用并没有启动,也就是说我们调用的startActivity方法不单单为我们启动了这个activity也同时在启动activity之前启动了这个应用进程,好了,那我们这里就以这个方法为入口分析一下应用进程的启动流程。
    跟踪代码到Activity,发现其调用了startActivity的重载方法:
    1. [code]@Override
    2.     public void startActivity(Intent intent) {
    3.         this.startActivity(intent, null);
    4.     }
    复制代码
    [/code]
    继续跟进:
    1. [code]@Override
    2.     public void startActivity(Intent intent, @Nullable Bundle options) {
    3.         if (options != null) {
    4.             startActivityForResult(intent, -1, options);
    5.         } else {
    6.             // Note we want to go through this call for compatibility with
    7.             // applications that may have overridden the method.
    8.             startActivityForResult(intent, -1);
    9.         }
    10.     }
    复制代码
    [/code]
    很明显的我们此时传递的options为空:
    1. [code]public void startActivityForResult(Intent intent, int requestCode) {
    2.         startActivityForResult(intent, requestCode, null);
    3.     }
    复制代码
    [/code]
    好吧,最后调用的还是这个重载方法:
    1. [code]public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
    2.         if (mParent == null) {
    3.             Instrumentation.ActivityResult ar =
    4.                 mInstrumentation.execStartActivity(
    5.                     this, mMainThread.getApplicationThread(), mToken, this,
    6.                     intent, requestCode, options);
    7.             if (ar != null) {
    8.                 mMainThread.sendActivityResult(
    9.                     mToken, mEmbeddedID, requestCode, ar.getResultCode(),
    10.                     ar.getResultData());
    11.             }
    12.             if (requestCode >= 0) {
    13.                 mStartedActivity = true;
    14.             }
    15.             cancelInputsAndStartExitTransition(options);
    16.             // TODO Consider clearing/flushing other event sources and events for child windows.
    17.         } else {
    18.             if (options != null) {
    19.                 mParent.startActivityFromChild(this, intent, requestCode, options);
    20.             } else {
    21.                 // Note we want to go through this method for compatibility with
    22.                 // existing applications that may have overridden it.
    23.                 mParent.startActivityFromChild(this, intent, requestCode);
    24.             }
    25.         }
    26.     }
    复制代码
    [/code]
    可以发现这里调用了mInstrumentation.execStartActivity方法,这里先简单介绍一下Instrumentation对象,他是Android系统中应用程序端操作Activity的具体操作类,这里的操作段是相对于ActivityManagerService服务端来说的。也就是说当我们在执行对Activity的具体操作时,比如回调生命周期的各个方法都是借助于Instrumentation类来实现的。
    好了,下面我们继续看一下Instrumentation的execStartActivity方法:
    1. [code]public ActivityResult execStartActivity(
    2.             Context who, IBinder contextThread, IBinder token, Activity target,
    3.             Intent intent, int requestCode, Bundle options) {
    4.         ...
    5.         try {
    6.             intent.migrateExtraStreamToClipData();
    7.             intent.prepareToLeaveProcess();
    8.             int result = ActivityManagerNative.getDefault()
    9.                 .startActivity(whoThread, who.getBasePackageName(), intent,
    10.                         intent.resolveTypeIfNeeded(who.getContentResolver()),
    11.                         token, target != null ? target.mEmbeddedID : null,
    12.                         requestCode, 0, null, options);
    13.             checkStartActivityResult(result, intent);
    14.         } catch (RemoteException e) {
    15.             throw new RuntimeException("Failure from system", e);
    16.         }
    17.         return null;
    18.     }
    复制代码
    [/code]
    这里主要关注这个代码:
    1. [code]int result = ActivityManagerNative.getDefault()
    2.                 .startActivity(whoThread, who.getBasePackageName(), intent,
    3.                         intent.resolveTypeIfNeeded(who.getContentResolver()),
    4.                         token, target != null ? target.mEmbeddedID : null,
    5.                         requestCode, 0, null, options);
    复制代码
    [/code]
    这断代码实际上是进程间通讯,我们可以发现ActivityManagerNative继承于Binder接口,所以ActivityManagerNative就是一个Binder对象,然后上面一节我们介绍SystemServer进程的时候对ActivityManagerService有过了解,发现其继承于ActivityManagerNative,好吧,了解过Binder机制的童鞋就知道了,ActivityManagerService就是这个Binder机制的服务器端而ActivityManagerNative就是这个Binder机制的客户端,所以我们这里调用的startActivity实际上是讲参数传递给ActivityManagerService并执行ActivityManagerService的startActivity方法。
    既然这样,我们看一下ActivityManagerService的startActivity方法:
    1. [code]@Override
    2.     public final int startActivity(IApplicationThread caller, String callingPackage,
    3.             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    4.             int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    5.         return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
    6.             resultWho, requestCode, startFlags, profilerInfo, options,
    7.             UserHandle.getCallingUserId());
    8.     }
    复制代码
    [/code]
    调用了startActivityAsUser方法,然后我们继续看一下startActivityAsUser方法:
    1. [code]@Override
    2.     public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
    3.             Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    4.             int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
    5.         enforceNotIsolatedCaller("startActivity");
    6.         userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
    7.                 false, ALLOW_FULL_ONLY, "startActivity", null);
    8.         // TODO: Switch to user app stacks here.
    9.         return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
    10.                 resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
    11.                 profilerInfo, null, null, options, false, userId, null, null);
    12.     }
    复制代码
    [/code]
    继续查看startActivityMayWait方法:
    1. [code]final int startActivityMayWait(IApplicationThread caller, int callingUid,
    2.             String callingPackage, Intent intent, String resolvedType,
    3.             IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    4.             IBinder resultTo, String resultWho, int requestCode, int startFlags,
    5.             ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
    6.             Bundle options, boolean ignoreTargetSecurity, int userId,
    7.             IActivityContainer iContainer, TaskRecord inTask) {
    8.         ...
    9.             int res = startActivityLocked(caller, intent, resolvedType, aInfo,
    10.                     voiceSession, voiceInteractor, resultTo, resultWho,
    11.                     requestCode, callingPid, callingUid, callingPackage,
    12.                     realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
    13.                     componentSpecified, null, container, inTask);
    14.             ...
    15.             return res;
    16.         }
    17.     }
    复制代码
    [/code]
    这个方法的逻辑比较多,我们重点关注的是其调用了startActivityLocked方法,也就是说在初始化其他逻辑之后,这个方法会调用startActivityLocked方法:
    1. [code]err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
    2.                 startFlags, true, options, inTask);
    复制代码
    [/code]
    代码量也是比较大的,在方法体中调用了startActivityUncheckedLocked方法,然后我们继续跟进startActivityUncheckedLocked方法:
    1. [code]targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
    复制代码
    [/code]
    然后我们查看startActivityLocked方法的实现:
    1. [code]if (doResume) {
    2.             mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
    3.         }
    复制代码
    [/code]
    可以发现其调用了resumeTopActivitiesLocked方法:
    1. [code]stack.resumeTopActivityLocked(null);
    复制代码
    [/code]
    继续跟进:
    1. [code]final boolean resumeTopActivityLocked(ActivityRecord prev) {
    2.         return resumeTopActivityLocked(prev, null);
    3.     }
    复制代码
    [/code]
    然后我们看一下resumeTopActivityLocked方法的实现:
    1. [code]result = resumeTopActivityInnerLocked(prev, options);
    复制代码
    [/code]
    继续查看resumeTopActivityInnerLocked方法的实现:
    1. [code]mStackSupervisor.startSpecificActivityLocked(next, true, true);
    复制代码
    [/code]
    可以发现在方法体中执行了相关逻辑判断与初始化操作之后调用了startSpecificActivityLocked方法:
    1. [code]mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
    2.                 "activity", r.intent.getComponent(), false, false, true);
    复制代码
    [/code]
    可以发现在方法体中调用了startProcessLocked方法,从名字可以看出来这个方法就是启动进程的。
    1. [code]final ProcessRecord startProcessLocked(String processName,
    2.             ApplicationInfo info, boolean knownToBeDead, int intentFlags,
    3.             String hostingType, ComponentName hostingName, boolean allowWhileBooting,
    4.             boolean isolated, boolean keepIfLarge) {
    5.         return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
    6.                 hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
    7.                 null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
    8.                 null /* crashHandler */);
    9.     }
    复制代码
    [/code]
    查看startProcessLocked方法的实现:
    1. [code]checkTime(startTime, "startProcess: stepping in to startProcess");
    2.         startProcessLocked(
    3. app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
    4.         checkTime(startTime, "startProcess: done starting proc!");
    复制代码
    [/code]
    查看startProcessLocked方法的具体实现;
    1. [code]checkTime(startTime, "startProcess: asking zygote to start proc");
    2.             Process.ProcessStartResult startResult = Process.start(entryPoint,
    3.                     app.processName, uid, uid, gids, debugFlags, mountExternal,
    4.                     app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
    5.                     app.info.dataDir, entryPointArgs);
    6.             checkTime(startTime, "startProcess: returned from zygote!");
    复制代码
    [/code]
    查看关键代码,这里调用了Process.start方法:
    1. [code]public static final ProcessStartResult start(final String processClass,
    2.                                   final String niceName,
    3.                                   int uid, int gid, int[] gids,
    4.                                   int debugFlags, int mountExternal,
    5.                                   int targetSdkVersion,
    6.                                   String seInfo,
    7.                                   String abi,
    8.                                   String instructionSet,
    9.                                   String appDataDir,
    10.                                   String[] zygoteArgs) {
    11.         try {
    12.             return startViaZygote(processClass, niceName, uid, gid, gids,
    13.                     debugFlags, mountExternal, targetSdkVersion, seInfo,
    14.                     abi, instructionSet, appDataDir, zygoteArgs);
    15.         } catch (ZygoteStartFailedEx ex) {
    16.             Log.e(LOG_TAG,
    17.                     "Starting VM process through Zygote failed");
    18.             throw new RuntimeException(
    19.                     "Starting VM process through Zygote failed", ex);
    20.         }
    21.     }
    复制代码
    [/code]
    这里的processClass就是要启动的进程的名称,这里传递的就是ActivityThread:
    1. [code]"android.app.ActivityThread"
    复制代码
    [/code]
    具体的Process启动进程的Native层代码这里不做过多的分析,这个方法就是启动了AcitivtyThread进程并执行了ActivityThread的main方法,所以我们经常说的进程的启动方法就是ActivityThread的main方法就是这里体现的。
    总结:

      android应用进程会在需要启动其组件的时候启动,当没有任何组件运行或者是系统内存较低的时候应用进程会被杀死。
      在启动应用四大组件的时候若发现当前应用的进程没有启动,则会首先启动应用程序的进程。
      我们可以为应用程序配置多个进程,每个进程都有自己的JVM和运行环境,各个进程之间的通讯需要通过Binder机制。
      Launcher启动的过程也是先启动Launcher进程再启动其Activity组件。

    另外对android源码解析方法感兴趣的可参考我的:
    android源码解析之(一)–>android项目构建过程
    android源码解析之(二)–>异步消息机制
    android源码解析之(三)–>异步任务AsyncTask
    android源码解析之(四)–>HandlerThread
    android源码解析之(五)–>IntentService
    android源码解析之(六)–>Log
    android源码解析之(七)–>LruCache
    android源码解析之(八)–>Zygote进程启动流程
    android源码解析之(九)–>SystemServer进程启动流程
    android源码解析之(十)–>Launcher启动流程


    本文以同步至github中:https://github.com/yipianfengye/androidSource,欢迎star和follow



    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-3-28 21:16 , Processed in 0.420130 second(s), 52 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表