//第二个参数为-1表示不需要知道Activity的启动结果 if (options != null) { startActivityForResult(intent, -1, options); } else { // Note we want to go through this call for compatibility with // applications that may have overridden the method. startActivityForResult(intent, -1); } }
我们可以看到,调用了两个重载方法之后,调到了startActivityForResult(Intent intent, int requestCode,Bundle options)
/** * 启动一个您想要完成的Activity。 * @param intent The intent to start. * @param requestCode If >= 0, this code will be returned in * onActivityResult() when the activity exits. * 这个方法其实就是比startActivity多了requestCode这个参数,这个参数如果我们设置为>=0. * 那么这个Activity退出的时候会回调onActivityResult。这里我们先不重点关注 * @param options Activity启动的配置选项See {@link android.content.Context#startActivity(Intent, Bundle)} * @throws android.content.ActivityNotFoundException * * @see #startActivity */ publicvoidstartActivityForResult(@RequiresPermission Intent intent, int requestCode, @Nullable Bundle options) { // 如果是第一次启动,那么mParent == null 我们先默认第一次,看下面的代码 // TODO parent被赋值的时候,是什么时候?? if (mParent == null) { // options = transferSpringboardActivityOptions(options);
// mInstrumentation 执行启动Activity.这个Instrumentation是Activity的成员变量 // 可以作为我们Hook技术的Hook点。用代理的Instrumentation来替代原始的Instrumentation // 参数介绍: // 参数一:Context 上下文对象 /// 参数二:mMainThread.getApplicationThread() 这个参数的是一个Binder对象, // 是ActivityThread里面的getApplicationThread() // 参数三:mToken。这个方法页面重要。是客户端Activity与服务端AMS交互的令牌Token Instrumentation.ActivityResultar= mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; }
cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { // 如果mParent不为null.则会调用startActivityFromChild if (options != null) { mParent.startActivityFromChild(this, intent, requestCode, options); } else { // Note we want to go through this method for compatibility with // existing applications that may have overridden it. mParent.startActivityFromChild(this, intent, requestCode); } } }
// Save a copy in case ephemeral needs it // 保存Intent临时副本信息,以防临时使用 final Intent ephemeralIntent = new Intent(intent); // Don't modify the client's object! intent = new Intent(intent); if (componentSpecified && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null) && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction()) && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction()) && mService.getPackageManagerInternalLocked() .isInstantAppInstallerComponent(intent.getComponent())) { // intercept intents targeted directly to the ephemeral installer the // ephemeral installer should never be started with a raw Intent; instead // adjust the intent so it looks like a "normal" instant app launch intent.setComponent(null /*component*/); componentSpecified = false; }
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0 /* matchFlags */, computeResolveFilterUid( callingUid, realCallingUid, mRequest.filterCallingUid)); if (rInfo == null) { UserInfo userInfo = mSupervisor.getUserInfo(userId); if (userInfo != null && userInfo.isManagedProfile()) { // Special case for managed profiles, if attempting to launch non-cryto aware // app in a locked managed profile from an unlocked parent allow it to resolve // as user will be sent via confirm credentials to unlock the profile. UserManager userManager = UserManager.get(mService.mContext); boolean profileLockedAndParentUnlockingOrUnlocked = false; long token = Binder.clearCallingIdentity(); try { UserInfo parent = userManager.getProfileParent(userId); profileLockedAndParentUnlockingOrUnlocked = (parent != null) && userManager.isUserUnlockingOrUnlocked(parent.id) && !userManager.isUserUnlockingOrUnlocked(userId); } finally { Binder.restoreCallingIdentity(token); } if (profileLockedAndParentUnlockingOrUnlocked) { rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, computeResolveFilterUid( callingUid, realCallingUid, mRequest.filterCallingUid)); } } } // Collect information about the target of the Intent. ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
synchronized (mService.mGlobalLock) { final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack(); stack.mConfigWillChange = globalConfig != null && mService.getGlobalConfiguration().diff(globalConfig) != 0; if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Starting activity when config will change = " + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
if (aInfo != null && (aInfo.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 && mService.mHasHeavyWeightFeature) { // This may be a heavy-weight process! Check to see if we already // have another, different heavy-weight process running. // ······· } }
final ActivityRecord[] outRecord = new ActivityRecord[1]; // startActivityMayWait中还是会调用startActivity,调用startActivity int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason, allowPendingRemoteAnimationRegistryLookup, originatingPendingIntent, allowBackgroundActivityStart);