[关闭]
@universal 2018-09-26T05:35:08.000000Z 字数 13556 阅读 304

启动Activity的那点事儿

源码分析 android


前言

这次主要是从源码角度和IPC角度分析下Activity的启动流程,基于Android 8.0,估计知识点比较多0.0,而且需要提前了解下一丢丢IPC的东西。


铺垫

首先,从用户点击APP图标开始走起。既然是启动一个APP,那必然需要启动一个进程来执行App。因为Android是基于Linux的,所有的进程都是由init进程fork出来的。所以(1)当手机系统启动的时候,init进程会创建一个Zygote进程,后面我们所有app的进程都是由这个Zygote进程fork出来的;(2)当有app启动时,ActivityManagerService会通过socket通知Zygote进程fork一个新进程。在这里额外说明一哈,其实这个AMS也是通过Zygote创建的,Zygote进程创建后首先会创建一个SystemServer进程,在这个SS进程中会启动像AMS、PMS这样的服务,有的都是IPC中关键的服务端程序。所以Zygote进程和SystemServer进程是Android Framework中非常重要的两大进程。

上面说到了app的进程是由Zygote孵化出来的,那么究竟是哪个进程去通知孵化的。其实很简单,如果是从其他app中启动的,就是那个app所在的进程;如果是从桌面启动的就是launcher进程,Launcher其实也是继承自Activity,所以我们也可以把桌面当作一个app,两种启动的方式都是调用startActivity()发送intent请求。


那么......敌军还有5秒到达战场......重要的来了

Activity(C端)

我们通常调用的startActivity的几种重载方法最终都会调用startActivityForResult()方法

  1. public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
  2. @Nullable Bundle options)
  3. {
  4. if (mParent == null) {
  5. options = transferSpringboardActivityOptions(options);
  6. Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(
  7. this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
  8. if (ar != null) {
  9. mMainThread.sendActivityResult(
  10. mToken, mEmbeddedID, requestCode, ar.getResultCode(),
  11. ar.getResultData());
  12. }
  13. cancelInputsAndStartExitTransition(options);
  14. } else {
  15. if (options != null) {
  16. mParent.startActivityFromChild(this, intent, requestCode, options);
  17. } else {
  18. mParent.startActivityFromChild(this, intent, requestCode);
  19. }
  20. }
  21. }

主要看当mParent为null时,这个mParent指的是ActivityGroup,用来嵌套多个Activity,不过这个现在已经被废弃了,都用fragment来代替了,这里提主要是为了提醒下startActivityFromChild()这个方法,也能启动activity(记得在笔试题见到过 = =、)。好了回归主线,启动Activity的任务会交给Instrumention的execStartActivity()方法,注意这里的一个参数 mMainThread.getApplicationThread(),很重要,先记住。

  1. //Instrumention.java
  2. public ActivityResult execStartActivity(Context who, IBinder contextThread,
  3. IBinder token,Activity target,Intent intent, int requestCode, Bundle options) {
  4. IApplicationThread whoThread = (IApplicationThread) contextThread;
  5. .......
  6. try {
  7. intent.migrateExtraStreamToClipData();
  8. intent.prepareToLeaveProcess(who);
  9. int result = ActivityManager.getService()
  10. .startActivity(whoThread, who.getBasePackageName(), intent,
  11. intent.resolveTypeIfNeeded(who.getContentResolver()),
  12. token, target != null ? target.mEmbeddedID : null,
  13. requestCode, 0, null, options);
  14. checkStartActivityResult(result, intent);
  15. } catch (RemoteException e) {
  16. throw new RuntimeException("Failure from system", e);
  17. }
  18. return null;
  19. }
  20. //上面是8.0的源码,和8.0之前有差别,但是原理都是一样的,具体的区别有兴趣的可以自行查看
  21. //ActivityManager.java
  22. public static IActivityManager getService() {
  23. return IActivityManagerSingleton.get();
  24. }
  25. private static final Singleton<IActivityManager> IActivityManagerSingleton =
  26. new Singleton<IActivityManager>() {
  27. @Override
  28. protected IActivityManager create() {
  29. final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
  30. final IActivityManager am = IActivityManager.Stub.asInterface(b);
  31. return am;
  32. }
  33. };

首先来说说Instrumention这个类,每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象,Instrumentation充当着一个管家的作用,任何和activity生命周期包括创建相关的方法都是通过它来具体实现的,这些后面再说它。

在execStartActivity()中,通过ActivityManager启动activity,ActivityManager.getService()返回的是一个单例,这个单例通过 asInterface()方法返回了一个Proxy对象,Proxy对象实现了IActivityManager接口,里面保存着服务端的binder对象(这个对象是通过ServiceManager拿到服务端的AMS binder对象),所以最后会通过Binder跨进程去调用服务端AMS中的方法启动activity。这其实就是个aidl的模板,可以自己敲一个aidl的实例对照着分析。

注意: 在8.0的时候,这里直接采用了aidl进行cs通信,所以8.0以前的ActivityManagerNative(服务端)、ActivityManagerProxy(客户端)已经被废弃,没有之前那么复杂了,但是原理都是一样的,最后都会跨进程去通知服务端的AMS启动activity。只不过8.0之前是通过binder(ActivityManagerNative)的transact()方法将数据打包成Parcel对象传给服务端,具体的流程大家可以自己去查阅,现在市面上的分析大部分都是8.0之前的版本。


AMS(S端)

现在启动任务交给了核心服务AMS处理:

  1. //ActivityManagerService.java
  2. @Override
  3. public final int startActivity( .......) {
  4. return startActivityAsUser(........);
  5. }
  6. @Override
  7. public final int startActivityAsUser(........);
  8. userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
  9. userId, false, ALLOW_FULL_ONLY, "startActivity", null);
  10. return mActivityStarter.startActivityMayWait(.......);
  11. }

为了方便看到流程,我把详细参数都省略掉了,可以看到最后会交给ActivityStarter去启动:

  1. //ActivityStarter.java
  2. final int startActivityMayWait(IApplicationThread caller, int callingUid,String callingPackage, Intent intent, .....){
  3. ....
  4. final ActivityRecord[] outRecord = new ActivityRecord[1];
  5. int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
  6. aInfo, rInfo, voiceSession, voiceInteractor,
  7. resultTo, resultWho, requestCode, callingPid,
  8. callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
  9. options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
  10. reason);
  11. ....
  12. return res;
  13. }
  14. //验证intent、Class、Permission等
  15. int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,....){
  16. ....
  17. mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
  18. aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
  19. callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
  20. options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
  21. inTask);
  22. ....
  23. return mLastStartActivityResult != START_ABORTED ? mLastStartActivityResult : START_SUCCESS;
  24. }
  25. private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,.....){
  26. .....
  27. //这里会去调用另外一个重载的startActivity()方法,具体的我就不贴了,下面是最后的出口
  28. result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
  29. startFlags, doResume, options, inTask, outActivity);
  30. return result;
  31. }
  32. private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
  33. IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
  34. int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
  35. ActivityRecord[] outActivity) {
  36. ....
  37. //检查栈顶活动是否是我们要启动的activity
  38. final boolean dontStart = top != null && mStartActivity.resultTo == null
  39. && top.realActivity.equals(mStartActivity.realActivity)
  40. && top.userId == mStartActivity.userId
  41. && top.app != null && top.app.thread != null
  42. && ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
  43. || mLaunchSingleTop || mLaunchSingleTask);
  44. //准备工作已经完成
  45. if (dontStart) {
  46. topStack.mLastPausedActivity = null;
  47. if (mDoResume) {
  48. mSupervisor.resumeFocusedStackTopActivityLocked();
  49. }
  50. ....
  51. }
  52. }

其实,ActivityStarter类中的逻辑像是在做战斗前的准备工作,比如确认战斗的双方、战斗的目标和战斗时间等等。在startActivityMayWait()方法中主要获取调用者的uid和pid,并且通过resolveIntent和resolveActivity获取ActivityInfo信息,确定要启动的Activity组件;在startActivityLocked()方法中去调用startActivity()创建ActivityRecord,记录activity的核心状态信息;在startActivityUnchecked()方法中根据intent的Flag信息、activity的启动模式分配或者创建任务栈,设置TaskRecord。最后去调用ActivityStackSupervisor和ActivityStack中的相关方法:

  1. //ActivityStackSupervisor.java
  2. boolean resumeFocusedStackTopActivityLocked(
  3. ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
  4. if (targetStack != null && isFocusedStack(targetStack)) {
  5. return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
  6. }
  7. final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
  8. if (r == null || r.state != RESUMED) {
  9. mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
  10. } else if (r.state == RESUMED) {
  11. // Kick off any lingering app transitions form the MoveTaskToFront operation.
  12. mFocusedStack.executeAppTransition(targetOptions);
  13. }
  14. return false;
  15. }
  16. //ActivityStack.java
  17. boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
  18. if (mStackSupervisor.inResumeTopActivity) {
  19. // Don't even start recursing.
  20. return false;
  21. }
  22. boolean result = false;
  23. try {
  24. // Protect against recursion.
  25. mStackSupervisor.inResumeTopActivity = true;
  26. result = resumeTopActivityInnerLocked(prev, options);
  27. } finally {
  28. mStackSupervisor.inResumeTopActivity = false;
  29. }
  30. final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */);
  31. if (next == null || !next.canTurnScreenOn()) {
  32. checkReadyForSleep();
  33. }
  34. return result;
  35. }
  36. //这里主要是判断需要启动的Activity所在进程和app是否存在,不存在的话去孵化进程,存在的话直接启动activity
  37. private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
  38. if (next.app != null && next.app.thread != null) {
  39. ........
  40. }else {
  41. .......
  42. mStackSupervisor.startSpecificActivityLocked(next, true, true);
  43. }
  44. return true;
  45. }
  46. //ActivityStackSupervisor.java
  47. void startSpecificActivityLocked(ActivityRecord r,boolean andResume, boolean checkConfig) {
  48. ProcessRecord app =
  49. mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
  50. r.getStack().setLaunchTime(r);
  51. if (app != null && app.thread != null) {
  52. try {
  53. if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
  54. || !"android".equals(r.info.packageName)) {
  55. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
  56. mService.mProcessStats);
  57. }
  58. realStartActivityLocked(r, app, andResume, checkConfig);
  59. return;
  60. } catch (RemoteException e) {
  61. Slog.w(TAG, "Exception when starting activity "
  62. + r.intent.getComponent().flattenToShortString(), e);
  63. }
  64. }
  65. }
  66. final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
  67. boolean andResume, boolean checkConfig) throws RemoteException {
  68. ......
  69. app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
  70. System.identityHashCode(r), r.info,
  71. mergedConfiguration.getGlobalConfiguration(),
  72. mergedConfiguration.getOverrideConfiguration(), r.compat,
  73. r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
  74. r.persistentState, results, newIntents, !andResume,
  75. mService.isNextTransitionForward(), profilerInfo);
  76. }

可以看到上面的代码是绕来绕去,= =、我们知道activity都是通过任务栈来进行管理的,所以stackSupervisor就是服务端统一管理这些任务栈的地方,而ActivityStack就是用来管理当前任务栈中的activity,所以服务端干的事简单来说就是完成activity的切换、将要启动的activity移至栈顶,然后通知客户端去渲染ui。但是实际上里面的逻辑很复杂,比如说不同启动模式下,栈中的activity如何操作,以及我们常见的为什么是firstActivity onPause之后secondActivity 才开始创建等等,这些和任务栈相关的都是在服务端控制。
里面具体的逻辑这里就不分析了,我们主要分析这个启动流程,参考下图了解下即可。
此处输入图片的描述
重点是最后这个realstart方法中的这句scheduleLaunchActivity,其他之前的包括starter中的逻辑都是在铺垫。。这个app.thread其实是保存在ProcessRecord中的一个IApplicationThread对象,是不是感觉这个对象名字很熟悉,它其实就是客户端中的ApplicationThread,因为从AMS开始,方法的执行都是在服务端执行,所以服务端的工作做完了,就需要去通知客户端去操作了,那么通知的桥梁就是这个ApplicationThread对象,它继承自IApplicationThread.Stub,是一个binder对象,其实这里跟上面和AMS的通信一样,在8.0之后,统一采用aidl方式,放弃了像ApplicationThreadNative+ApplicationThreadProxy的方式,但是它们的作用和aidl生成的java类中的逻辑是一样的,这个大家手动敲一个aidl的例子对比一哈就能看出来。

回到主线程

下面我们就具体看看客户端后续在干什么:

  1. //ActivityThread.ApplicationThread.java
  2. @Override
  3. public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
  4. ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
  5. CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
  6. int procState, Bundle state, PersistableBundle persistentState,
  7. List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
  8. boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
  9. updateProcessState(procState, false);
  10. //创建ActivityClientRecord
  11. ActivityClientRecord r = new ActivityClientRecord();
  12. r.token = token;
  13. r.ident = ident;
  14. r.intent = intent;
  15. r.referrer = referrer;
  16. r.voiceInteractor = voiceInteractor;
  17. r.activityInfo = info;
  18. r.compatInfo = compatInfo;
  19. r.state = state;
  20. r.persistentState = persistentState;
  21. r.pendingResults = pendingResults;
  22. r.pendingIntents = pendingNewIntents;
  23. r.startsNotResumed = notResumed;
  24. r.isForward = isForward;
  25. r.profilerInfo = profilerInfo;
  26. r.overrideConfig = overrideConfig;
  27. updatePendingConfiguration(curConfig);
  28. //将消息传给handler处理
  29. sendMessage(H.LAUNCH_ACTIVITY, r);
  30. }
  31. //ActivityThread.H.java
  32. public void handleMessage(Message msg) {
  33. if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
  34. switch (msg.what) {
  35. case LAUNCH_ACTIVITY: {
  36. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
  37. final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
  38. r.packageInfo = getPackageInfoNoCheck(
  39. r.activityInfo.applicationInfo, r.compatInfo);
  40. handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
  41. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  42. } break;
  43. ....
  44. }
  45. }
  46. //ActivityThread.java
  47. private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
  48. ......
  49. Activity a = performLaunchActivity(r, customIntent);
  50. if (a != null) {
  51. handleResumeActivity(r.token, false, r.isForward,
  52. !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
  53. .....
  54. }
  55. .....
  56. }
  57. private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
  58. .....
  59. ContextImpl appContext = createBaseContextForActivity(r);
  60. Activity activity = null;
  61. try {
  62. java.lang.ClassLoader cl = appContext.getClassLoader();
  63. //创建activity
  64. activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
  65. StrictMode.incrementExpectedActivityCount(activity.getClass());
  66. r.intent.setExtrasClassLoader(cl);
  67. r.intent.prepareToEnterProcess();
  68. if (r.state != null) {
  69. r.state.setClassLoader(cl);
  70. }
  71. } catch (Exception e) {
  72. if (!mInstrumentation.onException(activity, e)) {
  73. throw new RuntimeException(
  74. "Unable to instantiate activity " + component
  75. + ": " + e.toString(), e);
  76. }
  77. }
  78. .....
  79. Application app = r.packageInfo.makeApplication(false, mInstrumentation);
  80. .....
  81. if (r.isPersistable()) {
  82. //生命周期的调用
  83. mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
  84. } else {
  85. mInstrumentation.callActivityOnCreate(activity, r.state);
  86. }
  87. .....
  88. }
  89. //LoadedApk.java
  90. public Application makeApplication(boolean forceDefaultAppClass,Instrumentation instrumentation){
  91. if (mApplication != null) {
  92. return mApplication;
  93. }
  94. try {
  95. java.lang.ClassLoader cl = getClassLoader();
  96. if (!mPackageName.equals("android")) {
  97. Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,"initializeJavaContextClassLoader");
  98. initializeJavaContextClassLoader();
  99. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  100. }
  101. ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
  102. //创建application
  103. app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
  104. appContext.setOuterContext(app);
  105. } catch (Exception e) {
  106. if (!mActivityThread.mInstrumentation.onException(app, e)) {
  107. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
  108. throw new RuntimeException(
  109. "Unable to instantiate application " + appClass
  110. + ": " + e.toString(), e);
  111. }
  112. }
  113. }

这里activity启动之后将消息传递给activitythread中的handler处理,然后重点在消息处理后调用的performLaunchActivity中,主要干了两件事,一是通过反射创建activity,二是创建application,当然如果application已存在,就不用再创建了。后面就开始了Activity生命周期的调用。
在performLaunchActivity方法中可以看到,调用生命周期oncreate方法的具体实现是在mInstrumentation中,其实其他像activity和Application的生命周期的调用包括创建等等也是在这个类中实现,所以就印证了我上面提到的Instrumentation充当着一个管家的作用。

到这里,,就差不多可以点投降了。
这里简单的总结了下启动过程中的ipc,当然这里面不仅仅只有这两次跨进程通信,而且服务端参与的服务也不仅仅只有AMS,像在resolveIntent时就会跨进程去掉用PMS中的服务。
此处输入图片的描述

那么Activity启动的流程....大致.....是这样,猝。

一点儿干货

点此可以详细查看activity启动流程
个人觉得讲binder讲的最好的一篇

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注