说实话,android source code从2.3到4.4变化是蛮多的,尤其是media部分,虽然总的框架是没有多大变化,但是找起代码来看还是挺麻烦的。在android里面最受伤的是使用了java,jni,jvm,Nativity c++等等,各种设计模式横行,当然在学习源码过程中也意识了编程语言基础,数据结构,设计模式的重要性。

android source code 经典的地方:

1. 大量使用了各种设计模式如单例模式,装饰模式,工程工厂模式,适配器模式等等。

2. 使用了binder驱动进行了IPC通信。

3. 重新设计了消息处理机制。

4. 加入了强弱指针管理。

5. 设计了activity安全的权限管理。

6. 对应用开发者可扩展,开发维护做出突出的贡献。

7. 使用了JNI技术。

8. 优化了电源管理服务。

。。。。。等等

当然,也有缺点地方。

1.  android启动慢。

因为使用了jni,jvm原因需要加载很多类及类库,和各种服务的启动。为了用户体验,使用了sureface。

上述启动完后还要启动launcher,扫描各个应用信息等等。

2.  android 是为嵌入式产品而开发的。实际上内存使用效果来看不是很理想,容易产生碎片,导致android使用越用越慢。

3.  主题定制少,缺乏大型游戏。

4.  app常驻内存导致无法长时间待机。

好吧,不要抱怨那么多了,生活已经够无奈的了。开始分析下吧。

1.  在Android系统中,应用程序是由Activity组成的,因此,应用程序的启动过程实际上就是应用程序中的默认Activity的启动过程。即在桌面程序(launcher)启动时候,扫描各个app信息,在设备屏幕中点击应用程序图标的情景就会引发Android应用程序中的默认Activity的启动,从而把应用程序启动起来。这种启动方式的特点是会启动一个新的进程来加载相应的Activity。

2.  由上可知:默认启动activity是通过launcher(onClick方法)来启动的,其实就是解析AndroidManifest.xml中的activity标签及<intent-filter>标签。然后通过startActivitySafely方法启动activity。

  1. Launcher.java (e:\baiduyundownload\intel_x86_sysimg_4.4_source_files_20131206\intel_x86_sysimg_4.4_source_files_20131206\packages\apps\launcher2\src\com\android\launcher2)
  2.  
  3. public void onClick(View v) {
  4. // Make sure that rogue clicks don't get through while allapps is launching, or after the
  5. // view has detached (it's possible for this to happen if the view is removed mid touch).
  6. if (v.getWindowToken() == null) {
  7. return;
  8. }
  9.  
  10. if (!mWorkspace.isFinishedSwitchingState()) {
  11. return;
  12. }
  13.  
  14. Object tag = v.getTag();
  15. if (tag instanceof ShortcutInfo) {
  16. // Open shortcut
  17. final Intent intent = ((ShortcutInfo) tag).intent;
  18. int[] pos = new int[];
  19. v.getLocationOnScreen(pos);
  20. intent.setSourceBounds(new Rect(pos[], pos[],
  21. pos[] + v.getWidth(), pos[] + v.getHeight()));
  22.  
  23. boolean success = startActivitySafely(v, intent, tag);
  24.  
  25. if (success && v instanceof BubbleTextView) {
  26. mWaitingForResume = (BubbleTextView) v;
  27. mWaitingForResume.setStayPressed(true);
  28. }
  29. } else if (tag instanceof FolderInfo) {
  30. if (v instanceof FolderIcon) {
  31. FolderIcon fi = (FolderIcon) v;
  32. handleFolderClick(fi);
  33. }
  34. } else if (v == mAllAppsButton) {
  35. if (isAllAppsVisible()) {
  36. showWorkspace(true);
  37. } else {
  38. onClickAllAppsButton(v);
  39. }
  40. }
  41. }
  1. boolean startActivitySafely(View v, Intent intent, Object tag) {
  2. boolean success = false;
  3. try {
  4. success = startActivity(v, intent, tag);
  5. } catch (ActivityNotFoundException e) {
  6. Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
  7. Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
  8. }
  9. return success;
  10. }
  1. boolean startActivity(View v, Intent intent, Object tag) {
  2. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  3.  
  4. try {
  5. // Only launch using the new animation if the shortcut has not opted out (this is a
  6. // private contract between launcher and may be ignored in the future).
  7. boolean useLaunchAnimation = (v != null) &&
  8. !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
           //useLaunchAnimation表示是否使用点击Launcher桌面上的图标,会先有图标放大的动画,然后才进入应用,2.3之前是没有这个选择的。
  9. if (useLaunchAnimation) {
  10. ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
  11. v.getMeasuredWidth(), v.getMeasuredHeight());
  12.  
  13. startActivity(intent, opts.toBundle());
  14. } else {
  15. startActivity(intent);
  16. }
  17. return true;
  18. } catch (SecurityException e) {
  19. Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
  20. Log.e(TAG, "Launcher does not have the permission to launch " + intent +
  21. ". Make sure to create a MAIN intent-filter for the corresponding activity " +
  22. "or use the exported attribute for this activity. "
  23. + "tag="+ tag + " intent=" + intent, e);
  24. }
  25. return false;
  26. }

  上面的

  1. startActivity(intent, opts.toBundle());在launcher.java中没有找到定义,实际上是在launcher的基类中定义的,需要转到activity.java中查找定义。

Activity.java (base\core\java\android\app)

  1. @Override
  2. public void startActivity(Intent intent, Bundle options) {
  3. if (options != null) {
          //第二个参数传入-1表示不需要这个Actvity结束后的返回结果。
  4. startActivityForResult(intent, -, 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, -);
  9. }
  10. }
  1. public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
  2. if (mParent == null) {
          //这里的mParent肯定为null,因为是从launcher启动进来的,肯定没有父activity。
          //这里的mInstrumentation是Activity类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。
          //这里的mMainThread也是Activity类的成员变量,它的类型是ActivityThread,它代表的是应用程序的主线程,这里通过mMainThread.getApplicationThread获得它里面的ApplicationThread成员变量,它是一个Binder对象,后面我们会看到,ActivityManagerService会使用它来和ActivityThread来进行进程间通信。这里我们需注意的是,这里的mMainThread代表的是Launcher应用程序运行的进程。
          //这里的mToken也是Activity类的成员变量,它是一个Binder对象的远程接口。
  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. .......
  13. }
  1. Instrumentation.java (base\core\java\android\app)
  2. public ActivityResult execStartActivity(
  3. Context who, IBinder contextThread, IBinder token, Activity target,
  4. Intent intent, int requestCode, Bundle options) {
  5. IApplicationThread whoThread = (IApplicationThread) contextThread;
  6. if (mActivityMonitors != null) {
  7. synchronized (mSync) {
  8. final int N = mActivityMonitors.size();
  9. for (int i=; i<N; i++) {
  10. final ActivityMonitor am = mActivityMonitors.get(i);
  11. if (am.match(who, null, intent)) {
  12. am.mHits++;
  13. if (am.isBlocking()) {
  14. return requestCode >= ? am.getResult() : null;
  15. }
  16. break;
  17. }
  18. }
  19. }
  20. }
  21. try {
  22. intent.migrateExtraStreamToClipData();
  23. intent.prepareToLeaveProcess();
            //这里的ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口,跟进去就知道了(IActivityManager)。
            //intent.resolveTypeIfNeeded返回这个intent的MIME类型,一般没有AndroidManifest.xml设置MainActivity的MIME类型,因此,这里返回null。
  24. int result = ActivityManagerNative.getDefault()
  25. .startActivity(whoThread, who.getBasePackageName(), intent,
  26. intent.resolveTypeIfNeeded(who.getContentResolver()),
  27. token, target != null ? target.mEmbeddedID : null,
  28. requestCode, , null, null, options);
  29. checkStartActivityResult(result, intent);
  30. } catch (RemoteException e) {
  31. }
  32. return null;
  33. }
  1. ActivityManagerNative.java (base\core\java\android\app)
  2. public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
  3. String resolvedType, IBinder resultTo, String resultWho, int requestCode,
  4. int startFlags, String profileFile,
  5. ParcelFileDescriptor profileFd, Bundle options) throws RemoteException {
    //这里已经非常接近核心了,1. 构造parcel data包和reply包,将相关要启动的intent数据打进去,然后通过远程对象mRemote的transact方法(binder IPC)投递到服务端( ActivityManagerService)
    //从调用可以知道,这里的参数resolvedType、grantedUriPermissions和resultWho均为null;参数caller为ApplicationThread类型的Binder实体;参数resultTo为一个Binder实体的远程接口,我们先不关注它;参数grantedMode为0,我们也先不关注它;参数requestCode为-1;参数onlyIfNeeded和debug均空false。
  6. Parcel data = Parcel.obtain();
  7. Parcel reply = Parcel.obtain();
  8. data.writeInterfaceToken(IActivityManager.descriptor);
  9. data.writeStrongBinder(caller != null ? caller.asBinder() : null);
  10. data.writeString(callingPackage);
  11. intent.writeToParcel(data, );
  12. data.writeString(resolvedType);
  13. data.writeStrongBinder(resultTo);
  14. data.writeString(resultWho);
  15. data.writeInt(requestCode);
  16. data.writeInt(startFlags);
  17. data.writeString(profileFile);
  18. if (profileFd != null) {
  19. data.writeInt();
  20. profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
  21. } else {
  22. data.writeInt();
  23. }
  24. if (options != null) {
  25. data.writeInt();
  26. options.writeToParcel(data, );
  27. } else {
  28. data.writeInt();
  29. }
  30. mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, );
  31. reply.readException();
  32. int result = reply.readInt();
  33. reply.recycle();
  34. data.recycle();
  35. return result;
  36. }
  1. ActivityManagerService.java (base\services\java\com\android\server\am)
  2. @Override
  3. public final int startActivity(IApplicationThread caller, String callingPackage,
  4. Intent intent, String resolvedType, IBinder resultTo,
  5. String resultWho, int requestCode, int startFlags,
  6. String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
  7. return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
  8. resultWho, requestCode,
  9. startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
  10. }
  11.  
  12. @Override
  13. public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
  14. Intent intent, String resolvedType, IBinder resultTo,
  15. String resultWho, int requestCode, int startFlags,
  16. String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
  17. enforceNotIsolatedCaller("startActivity");
  18. userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
  19. false, true, "startActivity", null);
  20. // TODO: Switch to user app stacks here.
  21. return mStackSupervisor.startActivityMayWait(caller, -, callingPackage, intent, resolvedType,
  22. resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
  23. null, null, options, userId);
  24. }
  1. ActivityStackSupervisor.java (base\services\java\com\android\server\am)
  2. final int startActivityMayWait(IApplicationThread caller, int callingUid,
  3. String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
  4. String resultWho, int requestCode, int startFlags, String profileFile,
  5. ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
  6. Bundle options, int userId) {
  7. // Refuse possible leaked file descriptors
  8. if (intent != null && intent.hasFileDescriptors()) {
  9. throw new IllegalArgumentException("File descriptors passed in Intent");
  10. }
  11. boolean componentSpecified = intent.getComponent() != null;
  12.  
  13. // Don't modify the client's object!
  14. intent = new Intent(intent);
  15.  
  16. // Collect information about the target of the Intent.收集intent的信息()
  17. ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
  18. profileFile, profileFd, userId);
  19.  
  20. synchronized (mService) {
  21. int callingPid;
  22. if (callingUid >= ) {
  23. callingPid = -;
  24. } else if (caller == null) {
  25. callingPid = Binder.getCallingPid();
  26. callingUid = Binder.getCallingUid();
  27. } else {
  28. callingPid = callingUid = -;
  29. }
  30.  
  31. final ActivityStack stack = getFocusedStack();
  32. stack.mConfigWillChange = config != null
  33. && mService.mConfiguration.diff(config) != ;
  34. if (DEBUG_CONFIGURATION) Slog.v(TAG,
  35. "Starting activity when config will change = " + stack.mConfigWillChange);
  36.  
  37. final long origId = Binder.clearCallingIdentity();
  38.  
  39. if (aInfo != null &&
  40. (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != ) {
  41. // This may be a heavy-weight process! Check to see if we already
  42. // have another, different heavy-weight process running.
  43. if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
  44. if (mService.mHeavyWeightProcess != null &&
  45. (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
  46. !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
  47. int realCallingUid = callingUid;
  48. if (caller != null) {
  49. ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
  50. if (callerApp != null) {
  51. realCallingUid = callerApp.info.uid;
  52. } else {
  53. Slog.w(TAG, "Unable to find app for caller " + caller
  54. + " (pid=" + callingPid + ") when starting: "
  55. + intent.toString());
  56. ActivityOptions.abort(options);
  57. return ActivityManager.START_PERMISSION_DENIED;
  58. }
  59. }
  60.  
  61. IIntentSender target = mService.getIntentSenderLocked(
  62. ActivityManager.INTENT_SENDER_ACTIVITY, "android",
  63. realCallingUid, userId, null, null, , new Intent[] { intent },
  64. new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
  65. | PendingIntent.FLAG_ONE_SHOT, null);
  66.  
  67. Intent newIntent = new Intent();
  68. if (requestCode >= ) {
  69. // Caller is requesting a result.
  70. newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
  71. }
  72. newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
  73. new IntentSender(target));
  74. if (mService.mHeavyWeightProcess.activities.size() > ) {
  75. ActivityRecord hist = mService.mHeavyWeightProcess.activities.get();
  76. newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
  77. hist.packageName);
  78. newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
  79. hist.task.taskId);
  80. }
  81. newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
  82. aInfo.packageName);
  83. newIntent.setFlags(intent.getFlags());
  84. newIntent.setClassName("android",
  85. HeavyWeightSwitcherActivity.class.getName());
  86. intent = newIntent;
  87. resolvedType = null;
  88. caller = null;
  89. callingUid = Binder.getCallingUid();
  90. callingPid = Binder.getCallingPid();
  91. componentSpecified = true;
  92. try {
  93. ResolveInfo rInfo =
  94. AppGlobals.getPackageManager().resolveIntent(
  95. intent, null,
  96. PackageManager.MATCH_DEFAULT_ONLY
  97. | ActivityManagerService.STOCK_PM_FLAGS, userId);
  98. aInfo = rInfo != null ? rInfo.activityInfo : null;
  99. aInfo = mService.getActivityInfoForUser(aInfo, userId);
  100. } catch (RemoteException e) {
  101. aInfo = null;
  102. }
  103. }
  104. }
  105. }
  106.  
  107. int res = startActivityLocked(caller, intent, resolvedType,
  108. aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
  109. callingPackage, startFlags, options, componentSpecified, null);
  110.  
  111. if (stack.mConfigWillChange) {
  112. // If the caller also wants to switch to a new configuration,
  113. // do so now. This allows a clean switch, as we are waiting
  114. // for the current activity to pause (so we will not destroy
  115. // it), and have not yet started the next activity.
  116. mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
  117. "updateConfiguration()");
  118. stack.mConfigWillChange = false;
  119. if (DEBUG_CONFIGURATION) Slog.v(TAG,
  120. "Updating to new configuration after starting activity.");
  121. mService.updateConfigurationLocked(config, null, false, false);
  122. }
  123.  
  124. Binder.restoreCallingIdentity(origId);
  125.  
  126. if (outResult != null) {
  127. outResult.result = res;
  128. if (res == ActivityManager.START_SUCCESS) {
  129. mWaitingActivityLaunched.add(outResult);
  130. do {
  131. try {
  132. mService.wait();
  133. } catch (InterruptedException e) {
  134. }
  135. } while (!outResult.timeout && outResult.who == null);
  136. } else if (res == ActivityManager.START_TASK_TO_FRONT) {
  137. ActivityRecord r = stack.topRunningActivityLocked(null);
  138. if (r.nowVisible) {
  139. outResult.timeout = false;
  140. outResult.who = new ComponentName(r.info.packageName, r.info.name);
  141. outResult.totalTime = ;
  142. outResult.thisTime = ;
  143. } else {
  144. outResult.thisTime = SystemClock.uptimeMillis();
  145. mWaitingActivityVisible.add(outResult);
  146. do {
  147. try {
  148. mService.wait();
  149. } catch (InterruptedException e) {
  150. }
  151. } while (!outResult.timeout && outResult.who == null);
  152. }
  153. }
  154. }
  155.  
  156. return res;
  157. }
  158. }
  1. final int startActivityLocked(IApplicationThread caller,
  2. Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
  3. String resultWho, int requestCode,
  4. int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
  5. boolean componentSpecified, ActivityRecord[] outActivity) {
  6. int err = ActivityManager.START_SUCCESS;
  7.  
  8. ProcessRecord callerApp = null;
  9. if (caller != null) {
          //从传进来的参数caller得到调用者的进程信息,并保存在callerApp变量中,这里就是Launcher应用程序的进程信息了
  10. callerApp = mService.getRecordForAppLocked(caller);
  11. if (callerApp != null) {
  12. callingPid = callerApp.pid;
  13. callingUid = callerApp.info.uid;
  14. } else {
  15. Slog.w(TAG, "Unable to find app for caller " + caller
  16. + " (pid=" + callingPid + ") when starting: "
  17. + intent.toString());
  18. err = ActivityManager.START_PERMISSION_DENIED;
  19. }
  20. }
  21.  
  22. if (err == ActivityManager.START_SUCCESS) {
  23. final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : ;
  24. Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
  25. + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
  26. }
  27.  
  28. ActivityRecord sourceRecord = null;
  29. ActivityRecord resultRecord = null;
  30. if (resultTo != null) {
    //参数resultTo是Launcher这个Activity里面的一个Binder对象,通过它可以获得Launcher这个Activity的相关信息,保存在sourceRecord变量中。
  31. sourceRecord = isInAnyStackLocked(resultTo);
  32. if (DEBUG_RESULTS) Slog.v(
  33. TAG, "Will send result to " + resultTo + " " + sourceRecord);
  34. if (sourceRecord != null) {
  35. if (requestCode >= && !sourceRecord.finishing) {
  36. resultRecord = sourceRecord;
  37. }
  38. }
  39. }
  40. ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
  41.  
  42. int launchFlags = intent.getFlags();
  43.  
  44. if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) !=
  45. && sourceRecord != null) {
  46. // Transfer the result target from the source activity to the new
  47. // one being started, including any failures.
  48. if (requestCode >= ) {
  49. ActivityOptions.abort(options);
  50. return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
  51. }
  52. resultRecord = sourceRecord.resultTo;
  53. resultWho = sourceRecord.resultWho;
  54. requestCode = sourceRecord.requestCode;
  55. sourceRecord.resultTo = null;
  56. if (resultRecord != null) {
  57. resultRecord.removeResultsLocked(
  58. sourceRecord, resultWho, requestCode);
  59. }
  60. }
  61.  
  62. if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
  63. // We couldn't find a class that can handle the given Intent.
  64. // That's the end of that!
  65. err = ActivityManager.START_INTENT_NOT_RESOLVED;
  66. }
  67.  
  68. if (err == ActivityManager.START_SUCCESS && aInfo == null) {
  69. // We couldn't find the specific class specified in the Intent.
  70. // Also the end of the line.
  71. err = ActivityManager.START_CLASS_NOT_FOUND;
  72. }
  73.  
  74. if (err != ActivityManager.START_SUCCESS) {
  75. if (resultRecord != null) {
  76. resultStack.sendActivityResultLocked(-,
  77. resultRecord, resultWho, requestCode,
  78. Activity.RESULT_CANCELED, null);
  79. }
  80. setDismissKeyguard(false);
  81. ActivityOptions.abort(options);
  82. return err;
  83. }
  84.  
  85. final int startAnyPerm = mService.checkPermission(
  86. START_ANY_ACTIVITY, callingPid, callingUid);
  87. final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
  88. callingUid, aInfo.applicationInfo.uid, aInfo.exported);
  89. if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
  90. if (resultRecord != null) {
  91. resultStack.sendActivityResultLocked(-,
  92. resultRecord, resultWho, requestCode,
  93. Activity.RESULT_CANCELED, null);
  94. }
  95. setDismissKeyguard(false);
  96. String msg;
  97. if (!aInfo.exported) {
  98. msg = "Permission Denial: starting " + intent.toString()
  99. + " from " + callerApp + " (pid=" + callingPid
  100. + ", uid=" + callingUid + ")"
  101. + " not exported from uid " + aInfo.applicationInfo.uid;
  102. } else {
  103. msg = "Permission Denial: starting " + intent.toString()
  104. + " from " + callerApp + " (pid=" + callingPid
  105. + ", uid=" + callingUid + ")"
  106. + " requires " + aInfo.permission;
  107. }
  108. Slog.w(TAG, msg);
  109. throw new SecurityException(msg);
  110. }
  111.  
  112. boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
  113. callingPid, resolvedType, aInfo.applicationInfo);
  114.  
  115. if (mService.mController != null) {
  116. try {
  117. // The Intent we give to the watcher has the extra data
  118. // stripped off, since it can contain private information.
  119. Intent watchIntent = intent.cloneFilter();
  120. abort |= !mService.mController.activityStarting(watchIntent,
  121. aInfo.applicationInfo.packageName);
  122. } catch (RemoteException e) {
  123. mService.mController = null;
  124. }
  125. }
  126.  
  127. if (abort) {
  128. if (resultRecord != null) {
  129. resultStack.sendActivityResultLocked(-, resultRecord, resultWho, requestCode,
  130. Activity.RESULT_CANCELED, null);
  131. }
  132. // We pretend to the caller that it was really started, but
  133. // they will just get a cancel result.
  134. setDismissKeyguard(false);
  135. ActivityOptions.abort(options);
  136. return ActivityManager.START_SUCCESS;
  137. }
  138.     //创建即将要启动的Activity的相关信息,并保存在r变量中
  139. ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
  140. intent, resolvedType, aInfo, mService.mConfiguration,
  141. resultRecord, resultWho, requestCode, componentSpecified, this);
  142. if (outActivity != null) {
  143. outActivity[] = r;
  144. }
  145.  
  146. final ActivityStack stack = getFocusedStack();
  147. if (stack.mResumedActivity == null
  148. || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
  149. if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
  150. PendingActivityLaunch pal =
  151. new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
  152. mService.mPendingActivityLaunches.add(pal);
  153. setDismissKeyguard(false);
  154. ActivityOptions.abort(options);
  155. return ActivityManager.START_SWITCHES_CANCELED;
  156. }
  157. }
  158.  
  159. if (mService.mDidAppSwitch) {
  160. // This is the second allowed switch since we stopped switches,
  161. // so now just generally allow switches. Use case: user presses
  162. // home (switches disabled, switch to home, mDidAppSwitch now true);
  163. // user taps a home icon (coming from home so allowed, we hit here
  164. // and now allow anyone to switch again).
  165. mService.mAppSwitchesAllowedTime = ;
  166. } else {
  167. mService.mDidAppSwitch = true;
  168. }
  169.  
  170. mService.doPendingActivityLaunchesLocked(false);
  171.     //接下来创建这个来处理下
  172. err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
  173.  
  174. if (allPausedActivitiesComplete()) {
  175. // If someone asked to have the keyguard dismissed on the next
  176. // activity start, but we are not actually doing an activity
  177. // switch... just dismiss the keyguard now, because we
  178. // probably want to see whatever is behind it.
  179. dismissKeyguard();
  180. }
  181. return err;
  182. }
  1. final int startActivityUncheckedLocked(ActivityRecord r,
  2. ActivityRecord sourceRecord, int startFlags, boolean doResume,
  3. Bundle options) {
  4. final Intent intent = r.intent;
  5. final int callingUid = r.launchedFromUid;
  6. // 函数首先获得intent的标志值,保存在launchFlags变量中。这个intent的标志值的位Intent.FLAG_ACTIVITY_NO_USER_ACTION没有置位,因此 ,成员变量mUserLeaving的值为true。这个intent的标志值的位Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP也没有置位,因此,变量notTop的值为null。
  1. int launchFlags = intent.getFlags();
  2.  
  3. // We'll invoke onUserLeaving before onPause only if the launching
  4. // activity did not explicitly state that this is an automated launch.
  5. mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == ;
  6. if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
  7.  
  8. // If the caller has asked not to resume at this point, we make note
  9. // of this in the record so that we can skip it when trying to find
  10. // the top running activity.
  11. if (!doResume) {
  12. r.delayedResume = true;
  13. }
  14.  
  15. ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != ? r : null;
  16.  
  17. // If the onlyIfNeeded flag is set, then we can do this if the activity
  18. // being launched is the same as the one making the call... or, as
  19. // a special case, if we do not know the caller then we count the
  20. // current top activity as the caller.
  21. if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != ) {
  22. ActivityRecord checkedCaller = sourceRecord;
  23. if (checkedCaller == null) {
  24. checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
  25. }
  26. if (!checkedCaller.realActivity.equals(r.realActivity)) {
  27. // Caller is not the same as launcher, so always needed.
  28. startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
  29. }
  30. }
  31.  
  32. if (sourceRecord == null) {
  33. // This activity is not being started from another... in this
  34. // case we -always- start a new task.
  35. if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == ) {
  36. Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
  37. "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
  38. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
  39. }
  40. } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
  41. // The original activity who is starting us is running as a single
  42. // instance... this new activity it is starting must go on its
  43. // own task.
  44. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
  45. } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
  46. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
  47. // The activity being started is a single instance... it always
  48. // gets launched into its own task.
  49. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
  50. }
  51.  
  52. final ActivityStack sourceStack;
  53. if (sourceRecord != null) {
  54. if (sourceRecord.finishing) {
  55. // If the source is finishing, we can't further count it as our source. This
  56. // is because the task it is associated with may now be empty and on its way out,
  57. // so we don't want to blindly throw it in to that task. Instead we will take
  58. // the NEW_TASK flow and try to find a task for it.
  59. if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == ) {
  60. Slog.w(TAG, "startActivity called from finishing " + sourceRecord
  61. + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
  62. launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
  63. }
  64. sourceRecord = null;
  65. sourceStack = null;
  66. } else {
  67. sourceStack = sourceRecord.task.stack;
  68. }
  69. } else {
  70. sourceStack = null;
  71. }
  72. //传进来的参数r.resultTo为null,表示Launcher不需要等这个即将要启动的MainActivity的执行结果。
  73. if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != ) {
  74. // For whatever reason this activity is being launched into a new
  75. // task... yet the caller has requested a result back. Well, that
  76. // is pretty messed up, so instead immediately send back a cancel
  77. // and let the new task continue launched as normal without a
  78. // dependency on its originator.
  79. Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
  80. r.resultTo.task.stack.sendActivityResultLocked(-,
  81. r.resultTo, r.resultWho, r.requestCode,
  82. Activity.RESULT_CANCELED, null);
  83. r.resultTo = null;
  84. }
  85.  
  86. boolean addingToTask = false;
  87. boolean movedHome = false;
  88. TaskRecord reuseTask = null;
  89. ActivityStack targetStack;
    //当前有没有Task可以用来执行这个Activity。由于r.launchMode的值不为ActivityInfo.LAUNCH_SINGLE_INSTANCE,因此,它通过findTaskLocked函数来查找存不存这样的Task,这里返回的结果是null,即intentActivity为null,因此,需要创建一个新的Task来启动这个Activity。
  90. if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != &&
  91. (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == )
  92. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
  93. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
  94. // If bring to front is requested, and no result is requested, and
  95. // we can find a task that was started with this same
  96. // component, then instead of launching bring that one to the front.
  97. if (r.resultTo == null) {
  98. // See if there is a task to bring to the front. If this is
  99. // a SINGLE_INSTANCE activity, there can be one and only one
  100. // instance of it in the history, and it is always in its own
  101. // unique task, so we do a special search.
  102. ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
  103. ? findTaskLocked(r)
  104. : findActivityLocked(intent, r.info);
  105. if (intentActivity != null) {
  106. if (r.task == null) {
  107. r.task = intentActivity.task;
  108. }
  109. targetStack = intentActivity.task.stack;
  110. targetStack.mLastPausedActivity = null;
  111. if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
  112. + " from " + intentActivity);
  113. moveHomeStack(targetStack.isHomeStack());
  114. if (intentActivity.task.intent == null) {
  115. // This task was started because of movement of
  116. // the activity based on affinity... now that we
  117. // are actually launching it, we can assign the
  118. // base intent.
  119. intentActivity.task.setIntent(intent, r.info);
  120. }
  121. // If the target task is not in the front, then we need
  122. // to bring it to the front... except... well, with
  123. // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
  124. // to have the same behavior as if a new instance was
  125. // being started, which means not bringing it to the front
  126. // if the caller is not itself in the front.
  127. final ActivityStack lastStack = getLastStack();
  128. ActivityRecord curTop = lastStack == null?
  129. null : lastStack.topRunningNonDelayedActivityLocked(notTop);
  130. if (curTop != null && (curTop.task != intentActivity.task ||
  131. curTop.task != lastStack.topTask())) {
  132. r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
  133. if (sourceRecord == null || (sourceStack.topActivity() != null &&
  134. sourceStack.topActivity().task == sourceRecord.task)) {
  135. // We really do want to push this one into the
  136. // user's face, right now.
  137. movedHome = true;
  138. if ((launchFlags &
  139. (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
  140. == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
  141. // Caller wants to appear on home activity.
  142. intentActivity.task.mOnTopOfHome = true;
  143. }
  144. targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
  145. options = null;
  146. }
  147. }
  148. // If the caller has requested that the target task be
  149. // reset, then do so.
  150. if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != ) {
  151. intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
  152. }
  153. if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != ) {
  154. // We don't need to start a new activity, and
  155. // the client said not to do anything if that
  156. // is the case, so this is it! And for paranoia, make
  157. // sure we have correctly resumed the top activity.
  158. if (doResume) {
  159. resumeTopActivitiesLocked(targetStack, null, options);
  160. } else {
  161. ActivityOptions.abort(options);
  162. }
  163. if (r.task == null) Slog.v(TAG,
  164. "startActivityUncheckedLocked: task left null",
  165. new RuntimeException("here").fillInStackTrace());
  166. return ActivityManager.START_RETURN_INTENT_TO_CALLER;
  167. }
  168. if ((launchFlags &
  169. (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
  170. == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
  171. // The caller has requested to completely replace any
  172. // existing task with its new activity. Well that should
  173. // not be too hard...
  174. reuseTask = intentActivity.task;
  175. reuseTask.performClearTaskLocked();
  176. reuseTask.setIntent(r.intent, r.info);
  177. } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) !=
  178. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
  179. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
  180. // In this situation we want to remove all activities
  181. // from the task up to the one being started. In most
  182. // cases this means we are resetting the task to its
  183. // initial state.
  184. ActivityRecord top =
  185. intentActivity.task.performClearTaskLocked(r, launchFlags);
  186. if (top != null) {
  187. if (top.frontOfTask) {
  188. // Activity aliases may mean we use different
  189. // intents for the top activity, so make sure
  190. // the task now has the identity of the new
  191. // intent.
  192. top.task.setIntent(r.intent, r.info);
  193. }
  194. ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
  195. r, top.task);
  196. top.deliverNewIntentLocked(callingUid, r.intent);
  197. } else {
  198. // A special case: we need to
  199. // start the activity because it is not currently
  200. // running, and the caller has asked to clear the
  201. // current task to have this activity at the top.
  202. addingToTask = true;
  203. // Now pretend like this activity is being started
  204. // by the top of its task, so it is put in the
  205. // right place.
  206. sourceRecord = intentActivity;
  207. }
  208. } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
  209. // In this case the top activity on the task is the
  210. // same as the one being launched, so we take that
  211. // as a request to bring the task to the foreground.
  212. // If the top activity in the task is the root
  213. // activity, deliver this new intent to it if it
  214. // desires.
  215. if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) !=
  216. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
  217. && intentActivity.realActivity.equals(r.realActivity)) {
  218. ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
  219. intentActivity.task);
  220. if (intentActivity.frontOfTask) {
  221. intentActivity.task.setIntent(r.intent, r.info);
  222. }
  223. intentActivity.deliverNewIntentLocked(callingUid, r.intent);
  224. } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
  225. // In this case we are launching the root activity
  226. // of the task, but with a different intent. We
  227. // should start a new instance on top.
  228. addingToTask = true;
  229. sourceRecord = intentActivity;
  230. }
  231. } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == ) {
  232. // In this case an activity is being launched in to an
  233. // existing task, without resetting that task. This
  234. // is typically the situation of launching an activity
  235. // from a notification or shortcut. We want to place
  236. // the new activity on top of the current task.
  237. addingToTask = true;
  238. sourceRecord = intentActivity;
  239. } else if (!intentActivity.task.rootWasReset) {
  240. // In this case we are launching in to an existing task
  241. // that has not yet been started from its front door.
  242. // The current task has been brought to the front.
  243. // Ideally, we'd probably like to place this new task
  244. // at the bottom of its stack, but that's a little hard
  245. // to do with the current organization of the code so
  246. // for now we'll just drop it.
  247. intentActivity.task.setIntent(r.intent, r.info);
  248. }
  249. if (!addingToTask && reuseTask == null) {
  250. // We didn't do anything... but it was needed (a.k.a., client
  251. // don't use that intent!) And for paranoia, make
  252. // sure we have correctly resumed the top activity.
  253. if (doResume) {
  254. targetStack.resumeTopActivityLocked(null, options);
  255. } else {
  256. ActivityOptions.abort(options);
  257. }
  258. if (r.task == null) Slog.v(TAG,
  259. "startActivityUncheckedLocked: task left null",
  260. new RuntimeException("here").fillInStackTrace());
  261. return ActivityManager.START_TASK_TO_FRONT;
  262. }
  263. }
  264. }
  265. }
  266.  
  267. //String uri = r.intent.toURI();
  268. //Intent intent2 = new Intent(uri);
  269. //Slog.i(TAG, "Given intent: " + r.intent);
  270. //Slog.i(TAG, "URI is: " + uri);
  271. //Slog.i(TAG, "To intent: " + intent2);
  272.  
  273. if (r.packageName != null) {
  274. // If the activity being launched is the same as the one currently
  275. // at the top, then we need to check if it should only be launched
  276. // once.
  277. ActivityStack topStack = getFocusedStack();
  278. ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
  279. if (top != null && r.resultTo == null) {
  280. if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
  281. if (top.app != null && top.app.thread != null) {
  282. if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) !=
  283. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
  284. || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
  285. ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
  286. top.task);
  287. // For paranoia, make sure we have correctly
  288. // resumed the top activity.
  289. topStack.mLastPausedActivity = null;
  290. if (doResume) {
  291. resumeTopActivitiesLocked();
  292. }
  293. ActivityOptions.abort(options);
  294. if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != ) {
  295. // We don't need to start a new activity, and
  296. // the client said not to do anything if that
  297. // is the case, so this is it!
  298. if (r.task == null) Slog.v(TAG,
  299. "startActivityUncheckedLocked: task left null",
  300. new RuntimeException("here").fillInStackTrace());
  301. return ActivityManager.START_RETURN_INTENT_TO_CALLER;
  302. }
  303. top.deliverNewIntentLocked(callingUid, r.intent);
  304. if (r.task == null) Slog.v(TAG,
  305. "startActivityUncheckedLocked: task left null",
  306. new RuntimeException("here").fillInStackTrace());
  307. return ActivityManager.START_DELIVERED_TO_TOP;
  308. }
  309. }
  310. }
  311. }
  312.  
  313. } else {
  314. if (r.resultTo != null) {
  315. r.resultTo.task.stack.sendActivityResultLocked(-, r.resultTo, r.resultWho,
  316. r.requestCode, Activity.RESULT_CANCELED, null);
  317. }
  318. ActivityOptions.abort(options);
  319. if (r.task == null) Slog.v(TAG,
  320. "startActivityUncheckedLocked: task left null",
  321. new RuntimeException("here").fillInStackTrace());
  322. return ActivityManager.START_CLASS_NOT_FOUND;
  323. }
  324.  
  325. boolean newTask = false;
  326. boolean keepCurTransition = false;
  327.  
  328. // Should this be considered a new task?
  329. if (r.resultTo == null && !addingToTask
  330. && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != ) {
  331. targetStack = adjustStackFocus(r);
  332. moveHomeStack(targetStack.isHomeStack());
  333. if (reuseTask == null) {
              //当前在堆栈顶端的Activity是否就是即将要启动的Activity,有些情况下,如果即将要启动的Activity就在堆栈的顶端,那么,就不会重新启动这个Activity的别一个实例了. 现在为启动一个newtask,要在一个新的Task里面来启动这个Activity了。 
  334. r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
  335. null, true);
  336. if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
  337. r.task);
  338. } else {
  339. r.setTask(reuseTask, reuseTask, true);
  340. }
  341. newTask = true;
  342. if (!movedHome) {
  343. if ((launchFlags &
  344. (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
  345. == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
  346. // Caller wants to appear on home activity, so before starting
  347. // their own activity we will bring home to the front.
  348. r.task.mOnTopOfHome = true;
  349. }
  350. }
  351. } else if (sourceRecord != null) {
  352. TaskRecord sourceTask = sourceRecord.task;
  353. targetStack = sourceTask.stack;
  354. moveHomeStack(targetStack.isHomeStack());
  355. if (!addingToTask &&
  356. (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != ) {
  357. // In this case, we are adding the activity to an existing
  358. // task, but the caller has asked to clear that task if the
  359. // activity is already running.
  360. ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
  361. keepCurTransition = true;
  362. if (top != null) {
  363. ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
  364. top.deliverNewIntentLocked(callingUid, r.intent);
  365. // For paranoia, make sure we have correctly
  366. // resumed the top activity.
  367. targetStack.mLastPausedActivity = null;
  368. if (doResume) {
  369. targetStack.resumeTopActivityLocked(null);
  370. }
  371. ActivityOptions.abort(options);
  372. if (r.task == null) Slog.w(TAG,
  373. "startActivityUncheckedLocked: task left null",
  374. new RuntimeException("here").fillInStackTrace());
  375. return ActivityManager.START_DELIVERED_TO_TOP;
  376. }
  377. } else if (!addingToTask &&
  378. (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != ) {
  379. // In this case, we are launching an activity in our own task
  380. // that may already be running somewhere in the history, and
  381. // we want to shuffle it to the front of the stack if so.
  382. final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
  383. if (top != null) {
  384. final TaskRecord task = top.task;
  385. task.moveActivityToFrontLocked(top);
  386. ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
  387. top.updateOptionsLocked(options);
  388. top.deliverNewIntentLocked(callingUid, r.intent);
  389. targetStack.mLastPausedActivity = null;
  390. if (doResume) {
  391. targetStack.resumeTopActivityLocked(null);
  392. }
  393. return ActivityManager.START_DELIVERED_TO_TOP;
  394. }
  395. }
  396. // An existing activity is starting this new activity, so we want
  397. // to keep the new one in the same task as the one that is starting
  398. // it.
  399. r.setTask(sourceTask, sourceRecord.thumbHolder, false);
  400. if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
  401. + " in existing task " + r.task + " from source " + sourceRecord);
  402.  
  403. } else {
  404. // This not being started from an existing activity, and not part
  405. // of a new task... just put it in the top task, though these days
  406. // this case should never happen.
  407. targetStack = adjustStackFocus(r);
  408. moveHomeStack(targetStack.isHomeStack());
  409. ActivityRecord prev = targetStack.topActivity();
  410. r.setTask(prev != null ? prev.task
  411. : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
  412. null, true);
  413. if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
  414. + " in new guessed " + r.task);
  415. }
  416.  
  417. mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
  418. intent, r.getUriPermissionsLocked());
  419.  
  420. if (newTask) {
  421. EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
  422. }
  423. ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
  424. targetStack.mLastPausedActivity = null;
  425. targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
  426. mService.setFocusedActivityLocked(r);
  427. return ActivityManager.START_SUCCESS;
  428. }
  1. ActivityStack.java (base\services\java\com\android\server\am)
  2. final void startActivityLocked(ActivityRecord r, boolean newTask,
  3. boolean doResume, boolean keepCurTransition, Bundle options) {
  4. TaskRecord rTask = r.task;
  5. final int taskId = rTask.taskId;
  6. if (taskForIdLocked(taskId) == null || newTask) {
  7. // Last activity in task had been removed or ActivityManagerService is reusing task.
  8. // Insert or replace.
  9. // Might not even be in.
  10. insertTaskAtTop(rTask);
  11. mWindowManager.moveTaskToTop(taskId);
  12. }
  13. TaskRecord task = null;
  14. if (!newTask) {
  15. // If starting in an existing task, find where that is...
  16. boolean startIt = true;
  17. for (int taskNdx = mTaskHistory.size() - ; taskNdx >= ; --taskNdx) {
    //这里的 mTaskHistory.size()表示当前系统中历史任务的个数,这里肯定是大于0,因为Launcher已经跑起来了。当 mTaskHistory.size()>0时,并且现在要切换新任务时,要做一些任务切的界面操作
  18. task = mTaskHistory.get(taskNdx);
  19. if (task == r.task) {
  20. // Here it is! Now, if this is not yet visible to the
  21. // user, then just add it without starting; it will
  22. // get started when the user navigates back to it.
  23. if (!startIt) {
  24. if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
  25. + task, new RuntimeException("here").fillInStackTrace());
  26. task.addActivityToTop(r);
  27. r.putInHistory();
  28. mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
  29. r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
  30. (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != ,
  31. r.userId);
  32. if (VALIDATE_TOKENS) {
  33. validateAppTokensLocked();
  34. }
  35. ActivityOptions.abort(options);
  36. return;
  37. }
  38. break;
  39. } else if (task.numFullscreen > ) {
  40. startIt = false;
  41. }
  42. }
  43. }
  44.  
  45. // Place a new activity at top of stack, so it is next to interact
  46. // with the user.
  47.  
  48. // If we are not placing the new activity frontmost, we do not want
  49. // to deliver the onUserLeaving callback to the actual frontmost
  50. // activity
  51. if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - )) {
  52. mStackSupervisor.mUserLeaving = false;
  53. if (DEBUG_USER_LEAVING) Slog.v(TAG,
  54. "startActivity() behind front, mUserLeaving=false");
  55. }
  56.  
  57. task = r.task;
  58.  
  59. // Slot the activity into the history stack and proceed
  60. if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
  61. new RuntimeException("here").fillInStackTrace());
  62. task.addActivityToTop(r);
  63.  
  64. r.putInHistory();
  65. r.frontOfTask = newTask;
  66. if (!isHomeStack() || numActivities() > ) {
  67. // We want to show the starting preview window if we are
  68. // switching to a new task, or the next activity's process is
  69. // not currently running.
  70. boolean showStartingIcon = newTask;
  71. ProcessRecord proc = r.app;
  72. if (proc == null) {
  73. proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
  74. }
  75. if (proc == null || proc.thread == null) {
  76. showStartingIcon = true;
  77. }
  78. if (DEBUG_TRANSITION) Slog.v(TAG,
  79. "Prepare open transition: starting " + r);
  80. if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != ) {
  81. mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
  82. mNoAnimActivities.add(r);
  83. } else {
  84. mWindowManager.prepareAppTransition(newTask
  85. ? AppTransition.TRANSIT_TASK_OPEN
  86. : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
  87. mNoAnimActivities.remove(r);
  88. }
  89. r.updateOptionsLocked(options);
  90. mWindowManager.addAppToken(task.mActivities.indexOf(r),
  91. r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
  92. (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != , r.userId);
  93. boolean doShow = true;
  94. if (newTask) {
  95. // Even though this activity is starting fresh, we still need
  96. // to reset it to make sure we apply affinities to move any
  97. // existing activities from other tasks in to it.
  98. // If the caller has requested that the target task be
  99. // reset, then do so.
  100. if ((r.intent.getFlags()
  101. &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != ) {
  102. resetTaskIfNeededLocked(r, r);
  103. doShow = topRunningNonDelayedActivityLocked(null) == r;
  104. }
  105. }
  106. if (SHOW_APP_STARTING_PREVIEW && doShow) {
  107. // Figure out if we are transitioning from another activity that is
  108. // "has the same starting icon" as the next one. This allows the
  109. // window manager to keep the previous window it had previously
  110. // created, if it still had one.
  111. ActivityRecord prev = mResumedActivity;
  112. if (prev != null) {
  113. // We don't want to reuse the previous starting preview if:
  114. // (1) The current activity is in a different task.
  115. if (prev.task != r.task) {
  116. prev = null;
  117. }
  118. // (2) The current activity is already displayed.
  119. else if (prev.nowVisible) {
  120. prev = null;
  121. }
  122. }
  123. mWindowManager.setAppStartingWindow(
  124. r.appToken, r.packageName, r.theme,
  125. mService.compatibilityInfoForPackageLocked(
  126. r.info.applicationInfo), r.nonLocalizedLabel,
  127. r.labelRes, r.icon, r.logo, r.windowFlags,
  128. prev != null ? prev.appToken : null, showStartingIcon);
  129. }
  130. } else {
  131. // If this is the first activity, don't do any fancy animations,
  132. // because there is nothing for it to animate on top of.
  133. mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
  134. r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
  135. (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != , r.userId);
  136. ActivityOptions.abort(options);
  137. }
  138. if (VALIDATE_TOKENS) {
  139. validateAppTokensLocked();
  140. }
  141. //这里传进来的参数doResume为true,于是调用resumeTopActivityLocked进一步操作。
  142. if (doResume) {
  143. mStackSupervisor.resumeTopActivitiesLocked();
  144. }
  145. }
  1. ActivityStackSupervisor.java (base\services\java\com\android\server\am)
  2. boolean resumeTopActivitiesLocked() {
  3. return resumeTopActivitiesLocked(null, null, null);
  4. }
  5.  
  6. boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
  7. Bundle targetOptions) {
  8. if (targetStack == null) {
  9. targetStack = getFocusedStack();
  10. }
  11. boolean result = false;
  12. for (int stackNdx = mStacks.size() - ; stackNdx >= ; --stackNdx) {
  13. final ActivityStack stack = mStacks.get(stackNdx);
  14. if (isFrontStack(stack)) {
  15. if (stack == targetStack) {
            //把顶层的activity设置resume状态。
  16. result = stack.resumeTopActivityLocked(target, targetOptions);
  17. } else {
  18. stack.resumeTopActivityLocked(null);
  19. }
  20. }
  21. }
  22. return result;
  23. }
  1. ActivityStack.java (base\services\java\com\android\server\am)
  2. final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
  3. if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
  4.  
  5. // Find the first activity that is not finishing.函数先通过调用topRunningActivityLocked函数获得堆栈顶端的Activity,这里就是MainActivity了,之前已经设置好的,保存在next变量中。
  6. ActivityRecord next = topRunningActivityLocked(null);
  7.  
  8. // Remember how we'll process this pause/resume situation, and ensure
  9. // that the state is reset however we wind up proceeding.
    //接下来把mUserLeaving的保存在本地变量userLeaving中,然后重新设置为false,在前面,mUserLeaving的值为true,因此,这里的userLeaving为true。
  10. final boolean userLeaving = mStackSupervisor.mUserLeaving;
  11. mStackSupervisor.mUserLeaving = false;
  12.  
  13. if (next == null) {
  14. // There are no more activities! Let's just start up the
  15. // Launcher...
  16. ActivityOptions.abort(options);
  17. if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
  18. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  19. return mStackSupervisor.resumeHomeActivity(prev);
  20. }
  21.  
  22. next.delayedResume = false;
  23.  
  24. // If the top activity is the resumed one, nothing to do.
    //这里的mResumedActivity为Launcher,因为Launcher是当前正被执行的Activity。
    //它首先看要启动的Activity是否就是当前处理Resumed状态的Activity,如果是的话,那就什么都不用做,直接返回就可以了;否则再看一下系统当前是否休眠状态,如果是的话,再看看要启动的Activity是否就是当前处于堆栈顶端的Activity,如果是的话,也是什么都不用做。
  25. if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
  26. mStackSupervisor.allResumedActivitiesComplete()) {
  27. // Make sure we have executed any pending transitions, since there
  28. // should be nothing left to do at this point.
  29. mWindowManager.executeAppTransition();
  30. mNoAnimActivities.clear();
  31. ActivityOptions.abort(options);
  32. if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
  33. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  34. return false;
  35. }
  36.  
  37. final TaskRecord nextTask = next.task;
  38. final TaskRecord prevTask = prev != null ? prev.task : null;
  39. if (prevTask != null && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {
  40. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  41. if (prevTask == nextTask) {
  42. ArrayList<ActivityRecord> activities = prevTask.mActivities;
  43. final int numActivities = activities.size();
  44. for (int activityNdx = ; activityNdx < numActivities; ++activityNdx) {
  45. final ActivityRecord r = activities.get(activityNdx);
  46. // r is usually the same as next, but what if two activities were launched
  47. // before prev finished?
  48. if (!r.finishing) {
  49. r.frontOfTask = true;
  50. break;
  51. }
  52. }
  53. } else if (prevTask != topTask()) {
  54. // This task is going away but it was supposed to return to the home task.
  55. // Now the task above it has to return to the home task instead.
  56. final int taskNdx = mTaskHistory.indexOf(prevTask) + ;
  57. mTaskHistory.get(taskNdx).mOnTopOfHome = true;
  58. } else {
  59. if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Launching home next");
  60. return mStackSupervisor.resumeHomeActivity(prev);
  61. }
  62. }
  63.  
  64. // If we are sleeping, and there is no resumed activity, and the top
  65. // activity is paused, well that is the state we want.
  66. if (mService.isSleepingOrShuttingDown()
  67. && mLastPausedActivity == next
  68. && mStackSupervisor.allPausedActivitiesComplete()) {
  69. // Make sure we have executed any pending transitions, since there
  70. // should be nothing left to do at this point.
  71. mWindowManager.executeAppTransition();
  72. mNoAnimActivities.clear();
  73. ActivityOptions.abort(options);
  74. if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
  75. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  76. return false;
  77. }
  78.  
  79. // Make sure that the user who owns this activity is started. If not,
  80. // we will just leave it as is because someone should be bringing
  81. // another user's activities to the top of the stack.
  82. if (mService.mStartedUsers.get(next.userId) == null) {
  83. Slog.w(TAG, "Skipping resume of top activity " + next
  84. + ": user " + next.userId + " is stopped");
  85. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  86. return false;
  87. }
  88.  
  89. // The activity may be waiting for stop, but that is no longer
  90. // appropriate for it.
  91. mStackSupervisor.mStoppingActivities.remove(next);
  92. mStackSupervisor.mGoingToSleepActivities.remove(next);
  93. next.sleeping = false;
  94. mStackSupervisor.mWaitingVisibleActivities.remove(next);
  95.  
  96. next.updateOptionsLocked(options);
  97.  
  98. if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
  99.  
  100. // If we are currently pausing an activity, then don't do anything
  101. // until that is done.
  102. if (!mStackSupervisor.allPausedActivitiesComplete()) {
  103. if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
  104. "resumeTopActivityLocked: Skip resume: some activity pausing.");
  105. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  106. return false;
  107. }
  108.  
  109. // Okay we are now going to start a switch, to 'next'. We may first
  110. // have to pause the current activity, but this is an important point
  111. // where we have decided to go to 'next' so keep track of that.
  112. // XXX "App Redirected" dialog is getting too many false positives
  113. // at this point, so turn off for now.
  114. if (false) {
  115. if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
  116. long now = SystemClock.uptimeMillis();
  117. final boolean inTime = mLastStartedActivity.startTime !=
  118. && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
  119. final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
  120. final int nextUid = next.info.applicationInfo.uid;
  121. if (inTime && lastUid != nextUid
  122. && lastUid != next.launchedFromUid
  123. && mService.checkPermission(
  124. android.Manifest.permission.STOP_APP_SWITCHES,
  125. -, next.launchedFromUid)
  126. != PackageManager.PERMISSION_GRANTED) {
  127. mService.showLaunchWarningLocked(mLastStartedActivity, next);
  128. } else {
  129. next.startTime = now;
  130. mLastStartedActivity = next;
  131. }
  132. } else {
  133. next.startTime = SystemClock.uptimeMillis();
  134. mLastStartedActivity = next;
  135. }
  136. }
  137.  
  138. // We need to start pausing the current activity so the top one
  139. // can be resumed...
    //上面两个条件(mResumedActivity == next && next.state == ActivityState.RESUMED)都不满足,因此,在继续往下执行之前,首先要把当处于Resumed状态的Activity推入Paused状态,然后才可以启动新的Activity。但是在将当前这个Resumed状态的Activity推入Paused状态之前,首先要看一下当前是否有Activity正在进入Pausing状态,如果有的话,当前这个Resumed状态的Activity就要稍后才能进入Paused状态了,这样就保证了所有需要进入Paused状态的Activity串行处理
    这里没有处于Pausing状态的Activity,即mPausingActivitynull,而且mResumedActivity也不为null,于是就调用startPausingLocked函数把Launcher推入Paused状态去了。
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
  140. if (mResumedActivity != null) {
  141. pausing = true;
            //同时也是在此调用内,最终调用到应用程序activity的onCreate()函数。
  142. startPausingLocked(userLeaving, false);
  143. if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
  144. }
  145. if (pausing) {
  146. if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
  147. "resumeTopActivityLocked: Skip resume: need to start pausing");
  148. // At this point we want to put the upcoming activity's process
  149. // at the top of the LRU list, since we know we will be needing it
  150. // very soon and it would be a waste to let it get killed if it
  151. // happens to be sitting towards the end.
  152. if (next.app != null && next.app.thread != null) {
  153. // No reason to do full oom adj update here; we'll let that
  154. // happen whenever it needs to later.
  155. mService.updateLruProcessLocked(next.app, false, true);
  156. }
  157. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  158. return true;
  159. }
  160.  
  161. // If the most recent activity was noHistory but was only stopped rather
  162. // than stopped+finished because the device went to sleep, we need to make
  163. // sure to finish it as we're making a new activity topmost.
  164. if (mService.mSleeping && mLastNoHistoryActivity != null &&
  165. !mLastNoHistoryActivity.finishing) {
  166. if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
  167. " on new resume");
  168. requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
  169. null, "no-history", false);
  170. mLastNoHistoryActivity = null;
  171. }
  172.  
  173. if (prev != null && prev != next) {
  174. if (!prev.waitingVisible && next != null && !next.nowVisible) {
  175. prev.waitingVisible = true;
  176. mStackSupervisor.mWaitingVisibleActivities.add(prev);
  177. if (DEBUG_SWITCH) Slog.v(
  178. TAG, "Resuming top, waiting visible to hide: " + prev);
  179. } else {
  180. // The next activity is already visible, so hide the previous
  181. // activity's windows right now so we can show the new one ASAP.
  182. // We only do this if the previous is finishing, which should mean
  183. // it is on top of the one being resumed so hiding it quickly
  184. // is good. Otherwise, we want to do the normal route of allowing
  185. // the resumed activity to be shown so we can decide if the
  186. // previous should actually be hidden depending on whether the
  187. // new one is found to be full-screen or not.
  188. if (prev.finishing) {
  189. mWindowManager.setAppVisibility(prev.appToken, false);
  190. if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
  191. + prev + ", waitingVisible="
  192. + (prev != null ? prev.waitingVisible : null)
  193. + ", nowVisible=" + next.nowVisible);
  194. } else {
  195. if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
  196. + prev + ", waitingVisible="
  197. + (prev != null ? prev.waitingVisible : null)
  198. + ", nowVisible=" + next.nowVisible);
  199. }
  200. }
  201. }
  202.  
  203. // Launching this app's activity, make sure the app is no longer
  204. // considered stopped.
  205. try {
  206. AppGlobals.getPackageManager().setPackageStoppedState(
  207. next.packageName, false, next.userId); /* TODO: Verify if correct userid */
  208. } catch (RemoteException e1) {
  209. } catch (IllegalArgumentException e) {
  210. Slog.w(TAG, "Failed trying to unstop package "
  211. + next.packageName + ": " + e);
  212. }
  213.  
  214. // We are starting up the next activity, so tell the window manager
  215. // that the previous one will be hidden soon. This way it can know
  216. // to ignore it when computing the desired screen orientation.
  217. boolean anim = true;
  218. if (prev != null) {
  219. if (prev.finishing) {
  220. if (DEBUG_TRANSITION) Slog.v(TAG,
  221. "Prepare close transition: prev=" + prev);
  222. if (mNoAnimActivities.contains(prev)) {
  223. anim = false;
  224. mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
  225. } else {
  226. mWindowManager.prepareAppTransition(prev.task == next.task
  227. ? AppTransition.TRANSIT_ACTIVITY_CLOSE
  228. : AppTransition.TRANSIT_TASK_CLOSE, false);
  229. }
  230. mWindowManager.setAppWillBeHidden(prev.appToken);
  231. mWindowManager.setAppVisibility(prev.appToken, false);
  232. } else {
  233. if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
  234. if (mNoAnimActivities.contains(next)) {
  235. anim = false;
  236. mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
  237. } else {
  238. mWindowManager.prepareAppTransition(prev.task == next.task
  239. ? AppTransition.TRANSIT_ACTIVITY_OPEN
  240. : AppTransition.TRANSIT_TASK_OPEN, false);
  241. }
  242. }
  243. if (false) {
  244. mWindowManager.setAppWillBeHidden(prev.appToken);
  245. mWindowManager.setAppVisibility(prev.appToken, false);
  246. }
  247. } else {
  248. if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
  249. if (mNoAnimActivities.contains(next)) {
  250. anim = false;
  251. mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
  252. } else {
  253. mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
  254. }
  255. }
  256. if (anim) {
  257. next.applyOptionsLocked();
  258. } else {
  259. next.clearOptionsLocked();
  260. }
  261.  
  262. ActivityStack lastStack = mStackSupervisor.getLastStack();
  263. if (next.app != null && next.app.thread != null) {
  264. if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
  265.  
  266. // This activity is now becoming visible.
  267. mWindowManager.setAppVisibility(next.appToken, true);
  268.  
  269. // schedule launch ticks to collect information about slow apps.
  270. next.startLaunchTickingLocked();
  271.  
  272. ActivityRecord lastResumedActivity =
  273. lastStack == null ? null :lastStack.mResumedActivity;
  274. ActivityState lastState = next.state;
  275.  
  276. mService.updateCpuStats();
  277.  
  278. if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
  279. next.state = ActivityState.RESUMED;
  280. mResumedActivity = next;
  281. next.task.touchActiveTime();
  282. mService.addRecentTaskLocked(next.task);
  283. mService.updateLruProcessLocked(next.app, true, true);
  284. updateLRUListLocked(next);
  285.  
  286. // Have the window manager re-evaluate the orientation of
  287. // the screen based on the new activity order.
  288. boolean notUpdated = true;
  289. if (mStackSupervisor.isFrontStack(this)) {
  290. Configuration config = mWindowManager.updateOrientationFromAppTokens(
  291. mService.mConfiguration,
  292. next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
  293. if (config != null) {
  294. next.frozenBeforeDestroy = true;
  295. }
  296. notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
  297. }
  298.  
  299. if (notUpdated) {
  300. // The configuration update wasn't able to keep the existing
  301. // instance of the activity, and instead started a new one.
  302. // We should be all done, but let's just make sure our activity
  303. // is still at the top and schedule another run if something
  304. // weird happened.
  305. ActivityRecord nextNext = topRunningActivityLocked(null);
  306. if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
  307. "Activity config changed during resume: " + next
  308. + ", new next: " + nextNext);
  309. if (nextNext != next) {
  310. // Do over!
  311. mStackSupervisor.scheduleResumeTopActivities();
  312. }
  313. if (mStackSupervisor.reportResumedActivityLocked(next)) {
  314. mNoAnimActivities.clear();
  315. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  316. return true;
  317. }
  318. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  319. return false;
  320. }
  321.  
  322. try {
  323. // Deliver all pending results.
  324. ArrayList<ResultInfo> a = next.results;
  325. if (a != null) {
  326. final int N = a.size();
  327. if (!next.finishing && N > ) {
  328. if (DEBUG_RESULTS) Slog.v(
  329. TAG, "Delivering results to " + next
  330. + ": " + a);
  331. next.app.thread.scheduleSendResult(next.appToken, a);
  332. }
  333. }
  334.  
  335. if (next.newIntents != null) {
  336. next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
  337. }
  338.  
  339. EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
  340. next.userId, System.identityHashCode(next),
  341. next.task.taskId, next.shortComponentName);
  342.  
  343. next.sleeping = false;
  344. mService.showAskCompatModeDialogLocked(next);
  345. next.app.pendingUiClean = true;
  346. next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
  347. next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
  348. mService.isNextTransitionForward());
  349.  
  350. mStackSupervisor.checkReadyForSleepLocked();
  351.  
  352. if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
  353. } catch (Exception e) {
  354. // Whoops, need to restart this activity!
  355. if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
  356. + lastState + ": " + next);
  357. next.state = lastState;
  358. if (lastStack != null) {
  359. lastStack.mResumedActivity = lastResumedActivity;
  360. }
  361. Slog.i(TAG, "Restarting because process died: " + next);
  362. if (!next.hasBeenLaunched) {
  363. next.hasBeenLaunched = true;
  364. } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
  365. mStackSupervisor.isFrontStack(lastStack)) {
  366. mWindowManager.setAppStartingWindow(
  367. next.appToken, next.packageName, next.theme,
  368. mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
  369. next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
  370. next.windowFlags, null, true);
  371. }
  372. mStackSupervisor.startSpecificActivityLocked(next, true, false);
  373. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  374. return true;
  375. }
  376.  
  377. // From this point on, if something goes wrong there is no way
  378. // to recover the activity.
  379. try {
  380. next.visible = true;
  381. completeResumeLocked(next);
  382. } catch (Exception e) {
  383. // If any exception gets thrown, toss away this
  384. // activity and try the next one.
  385. Slog.w(TAG, "Exception thrown during resume of " + next, e);
  386. requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
  387. "resume-exception", true);
  388. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  389. return true;
  390. }
  391. next.stopped = false;
  392.  
  393. } else {
  394. // Whoops, need to restart this activity!
  395. if (!next.hasBeenLaunched) {
  396. next.hasBeenLaunched = true;
  397. } else {
  398. if (SHOW_APP_STARTING_PREVIEW) {
  399. mWindowManager.setAppStartingWindow(
  400. next.appToken, next.packageName, next.theme,
  401. mService.compatibilityInfoForPackageLocked(
  402. next.info.applicationInfo),
  403. next.nonLocalizedLabel,
  404. next.labelRes, next.icon, next.logo, next.windowFlags,
  405. null, true);
  406. }
  407. if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
  408. }
  409. if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
  410. mStackSupervisor.startSpecificActivityLocked(next, true, true);
  411. }
  412.  
  413. if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
  414. return true;
  415. }

android activity 启动过程分析(source code 4.4)的更多相关文章

  1. Activity启动过程分析

    Android的四大组件中除了BroadCastReceiver以外,其他三种组件都必须在AndroidManifest中注册,对于BroadCastReceiver来说,它既可以在AndroidMa ...

  2. Android Activity启动流程源码全解析(1)

    前言 Activity是Android四大组件的老大,我们对它的生命周期方法调用顺序都烂熟于心了,可是这些生命周期方法到底是怎么调用的呢?在启动它的时候会用到startActivty这个方法,但是这个 ...

  3. Android Activity启动流程源码全解析(2)

    接上之前的分析 ++Android Activity启动流程源码全解析(1)++ 1.正在运行的Activity调用startPausingLocked 一个一个分析,先来看看startPausing ...

  4. Android Activity启动黑/白屏原因与解决方式

    Android Activity启动黑/白屏原因与解决方式 我们新建一个HelloWorld项目,运行在手机上时,Activity打开之前会有一个动画,而这个动画里是全白或者全黑的(取决于你的主题是亮 ...

  5. 【Android】应用程序Activity启动过程分析

    在Android系统中,有两种操作会引发Activity的启动,一种用户点击应用程序图标时,Launcher会为我们启动应用程序的主Activity:应用程序的默认Activity启动起来后,它又可以 ...

  6. android Activity启动过程(四)startActivityUncheckedLocked

    final int startActivityUncheckedLocked(ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteract ...

  7. Android Activity启动耗时统计方案

    作者:林基宗 Activity的启动速度是很多开发者关心的问题,当页面跳转耗时过长时,App就会给人一种非常笨重的感觉.在遇到某个页面启动过慢的时候,开发的第一直觉一般是onCreate执行速度太慢了 ...

  8. android activity启动的4种方式记录及打开其他应用的activity的坑

    Android启动的四种方式分别为standard,singleTop,singleTask,singleInstence. standard是最常见的activity启动方式,也是默认的启动的方式. ...

  9. Android Activity 启动模式详解

    最近有群里的朋友问我 Activity的四种启动模式分别是什么意思? 当初因为项目比较忙,草草的解释了下, Api文档中说的也只是一般,在这里就小记一下吧,以便有更多的朋友对Activity启动模式了 ...

随机推荐

  1. php安装swoole2.1.2

    准备环境: cos7.2  &   php 7.1.7 1.www.swoole.com找到对应版本2.使用git clone或则 wget 命令(下载后需解压)进行下载3.在swoole目录 ...

  2. linux(centos 7)安装及使用yum

    yum介绍: Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的 ...

  3. 吴裕雄--天生自然 pythonTensorFlow图形数据处理:windows操作系统删除tensorflow

    输入:pip uninstall tensorflow Proceed(y/n):y

  4. 吴裕雄--天生自然python TensorFlow图片数据处理:No module named 'tensorflow.examples.tutorials'解决办法

    import numpy as np import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_dat ...

  5. TPO5-3 The Cambrian Explosion

    At one time, the animals present in these fossil beds were assigned to various modern animal groups, ...

  6. Mac中Apache常用命令

    Apache常用命令记录,还是记一下吧,总是忘记. Apache常用命令: # sudo apachectl start // 启动Apache服务 # sudo apachectl stop // ...

  7. SpringBoot集成ssm-druid-通用mapper

    简单介绍 springboot 首先什么是springboot? springboot是spring的另外一款框架,设计目的是用来简化新的spring应用的搭建和开发时所需要的特定的配置,从而使开发过 ...

  8. sql 新增随机数

    update RemoteDetection set humidity=round((rand()*3+29),0),TEMPERATURE=round((rand()*3+16),0),atmosp ...

  9. xmemcached过期时间

    最近项目中使用到了Memcached,而客户端选择了XMemcached ,在设置过期时间时,因对Memcached 不熟悉,将expire 设置为1000000000,本意表示尽量长的时间不要过期, ...

  10. Synchronized的jvm实现

    参考文档: https://www.cnblogs.com/dennyzhangdd/p/6734638.html