前言
Activity是四大组件中最常见的,也是相对来说最复杂的,AMS中的逻辑相当复杂,直线很多,且牵涉到WMS显示相关的部分,很难将其完全理清,这里只能说尽力理清主线流程。直接从AMS中的处理开始:
流程
ActivityManagerService#startActivity
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
ActivityManagerService#startActivityAsUser
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
true /*validateIncomingUser*/);
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
boolean validateIncomingUser) {
enforceNotIsolatedCaller("startActivity");
userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,
Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
// TODO: Switch to user app stacks here.
return mActivityStartController.obtainStarter(intent, "startActivityAsUser")
.setCaller(caller)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
.setActivityOptions(bOptions)
.setMayWait(userId)
.execute();
}
ActivityStarter#execute
/**
* Starts an activity based on the request parameters provided earlier.
* @return The starter result.
*/
int execute() {
try {
// TODO(b/64750076): Look into passing request directly to these methods to allow
// for transactional diffs and preprocessing.
if (mRequest.mayWait) {
return startActivityMayWait(mRequest.caller, mRequest.callingUid,
mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
mRequest.outActivity, mRequest.inTask, mRequest.reason,
mRequest.allowPendingRemoteAnimationRegistryLookup);
}
} finally {
onExecutionComplete();
}
}
ActivityStarter#startActivityMayWait
949 private int startActivityMayWait(IApplicationThread caller, int callingUid,
950 String callingPackage, Intent intent, String resolvedType,
951 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
952 IBinder resultTo, String resultWho, int requestCode, int startFlags,
953 ProfilerInfo profilerInfo, WaitResult outResult,
954 Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
955 int userId, TaskRecord inTask, String reason,
956 boolean allowPendingRemoteAnimationRegistryLookup) {
//resultTo用于接收返回的结果,resultWho用于描述接收结果的对象
//requestCode由调用者定义,Intent携带的start activity对应的flag
957 // Refuse possible leaked file descriptors
958 if (intent != null && intent.hasFileDescriptors()) {
959 throw new IllegalArgumentException("File descriptors passed in Intent");
960 }
961 mSupervisor.getActivityMetricsLogger().notifyActivityLaunching();
962 boolean componentSpecified = intent.getComponent() != null;
963
964 final int realCallingPid = Binder.getCallingPid();
965 final int realCallingUid = Binder.getCallingUid();
966
967 int callingPid;
968 if (callingUid >= 0) {
969 callingPid = -1;
970 } else if (caller == null) {
971 callingPid = realCallingPid;
972 callingUid = realCallingUid;
973 } else {
974 callingPid = callingUid = -1;
975 }
976
977 // Save a copy in case ephemeral needs it
978 final Intent ephemeralIntent = new Intent(intent);
979 // Don't modify the client's object!
980 intent = new Intent(intent);
981 if (componentSpecified
982 && !(Intent.ACTION_VIEW.equals(intent.getAction()) && intent.getData() == null)
983 && !Intent.ACTION_INSTALL_INSTANT_APP_PACKAGE.equals(intent.getAction())
984 && !Intent.ACTION_RESOLVE_INSTANT_APP_PACKAGE.equals(intent.getAction())
985 && mService.getPackageManagerInternalLocked()
986 .isInstantAppInstallerComponent(intent.getComponent())) {
987 // intercept intents targeted directly to the ephemeral installer the
988 // ephemeral installer should never be started with a raw Intent; instead
989 // adjust the intent so it looks like a "normal" instant app launch
990 intent.setComponent(null /*component*/);
991 componentSpecified = false;
992 }
993 //利用PKMS解析满足Intent等参数要求的信息
994 ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
995 0 /* matchFlags */,
996 computeResolveFilterUid(
997 callingUid, realCallingUid, mRequest.filterCallingUid));
998 if (rInfo == null) {
999 UserInfo userInfo = mSupervisor.getUserInfo(userId);
1000 if (userInfo != null && userInfo.isManagedProfile()) {
1001 // Special case for managed profiles, if attempting to launch non-cryto aware
1002 // app in a locked managed profile from an unlocked parent allow it to resolve
1003 // as user will be sent via confirm credentials to unlock the profile.
1004 UserManager userManager = UserManager.get(mService.mContext);
1005 boolean profileLockedAndParentUnlockingOrUnlocked = false;
1006 long token = Binder.clearCallingIdentity();
1007 try {
1008 UserInfo parent = userManager.getProfileParent(userId);
1009 profileLockedAndParentUnlockingOrUnlocked = (parent != null)
1010 && userManager.isUserUnlockingOrUnlocked(parent.id)
1011 && !userManager.isUserUnlockingOrUnlocked(userId);
1012 } finally {
1013 Binder.restoreCallingIdentity(token);
1014 }
1015 if (profileLockedAndParentUnlockingOrUnlocked) {
1016 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
1017 PackageManager.MATCH_DIRECT_BOOT_AWARE
1018 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
1019 computeResolveFilterUid(
1020 callingUid, realCallingUid, mRequest.filterCallingUid));
1021 }
1022 }
1023 }
1024 // Collect information about the target of the Intent.
//通过ActivityStackSupervisor解析ActivityInfo
1025 ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
1026
1027 synchronized (mService) {
1028 final ActivityStack stack = mSupervisor.mFocusedStack;
1029 stack.mConfigWillChange = globalConfig != null
1030 && mService.getGlobalConfiguration().diff(globalConfig) != 0;
1031 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1032 "Starting activity when config will change = " + stack.mConfigWillChange);
1033
1034 final long origId = Binder.clearCallingIdentity();
1035
1036 if (aInfo != null &&
1037 (aInfo.applicationInfo.privateFlags
1038 & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0 &&
1039 mService.mHasHeavyWeightFeature) {
//正常情况下,当一个Application退到后台时,系统会为它保存状态;当调度其到前台时,恢复它之前的状态,以保证用户体验的连续性
//AndroidManifest.xml中的Application标签可以申明一个CANT_SAVE_STATE属性
//设置了该属性的Application将不享受系统提供的状态保存/恢复功能,被称为heavy-weight process
1040 // This may be a heavy-weight process! Check to see if we already
1041 // have another, different heavy-weight process running.
1042 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
1043 final ProcessRecord heavy = mService.mHeavyWeightProcess;
1044 if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
1045 || !heavy.processName.equals(aInfo.processName))) {
1046 int appCallingUid = callingUid;
1047 if (caller != null) {
1048 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
1049 if (callerApp != null) {
1050 appCallingUid = callerApp.info.uid;
1051 } else {
1052 Slog.w(TAG, "Unable to find app for caller " + caller
1053 + " (pid=" + callingPid + ") when starting: "
1054 + intent.toString());
1055 SafeActivityOptions.abort(options);
1056 return ActivityManager.START_PERMISSION_DENIED;
1057 }
1058 }
1059
1060 IIntentSender target = mService.getIntentSenderLocked(
1061 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
1062 appCallingUid, userId, null, null, 0, new Intent[] { intent },
1063 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
1064 | PendingIntent.FLAG_ONE_SHOT, null);
1065
1066 Intent newIntent = new Intent();
1067 if (requestCode >= 0) {
1068 // Caller is requesting a result.
1069 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
1070 }
1071 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
1072 new IntentSender(target));
1073 if (heavy.activities.size() > 0) {
1074 ActivityRecord hist = heavy.activities.get(0);
1075 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
1076 hist.packageName);
1077 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
1078 hist.getTask().taskId);
1079 }
1080 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
1081 aInfo.packageName);
1082 newIntent.setFlags(intent.getFlags());
1083 newIntent.setClassName("android",
1084 HeavyWeightSwitcherActivity.class.getName());
1085 intent = newIntent;
1086 resolvedType = null;
1087 caller = null;
1088 callingUid = Binder.getCallingUid();
1089 callingPid = Binder.getCallingPid();
1090 componentSpecified = true;
1091 rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId,
1092 0 /* matchFlags */, computeResolveFilterUid(
1093 callingUid, realCallingUid, mRequest.filterCallingUid));
1094 aInfo = rInfo != null ? rInfo.activityInfo : null;
1095 if (aInfo != null) {
1096 aInfo = mService.getActivityInfoForUser(aInfo, userId);
1097 }
1098 }
1099 }
1100 }
1101
1102 final ActivityRecord[] outRecord = new ActivityRecord[1];
1103 int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
1104 voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
1105 callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
1106 ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason,
1107 allowPendingRemoteAnimationRegistryLookup);
1108
1109 Binder.restoreCallingIdentity(origId);
1110
1111 if (stack.mConfigWillChange) {
1112 // If the caller also wants to switch to a new configuration,
1113 // do so now. This allows a clean switch, as we are waiting
1114 // for the current activity to pause (so we will not destroy
1115 // it), and have not yet started the next activity.
1116 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
1117 "updateConfiguration()");
1118 stack.mConfigWillChange = false;
1119 if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
1120 "Updating to new configuration after starting activity.");
1121 mService.updateConfigurationLocked(globalConfig, null, false);
1122 }
1123
1124 if (outResult != null) {
1125 outResult.result = res;
1126
1127 final ActivityRecord r = outRecord[0];
1128
1129 switch(res) {
1130 case START_SUCCESS: {
1131 mSupervisor.mWaitingActivityLaunched.add(outResult);
1132 do {
1133 try {
1134 mService.wait();
1135 } catch (InterruptedException e) {
1136 }
1137 } while (outResult.result != START_TASK_TO_FRONT
1138 && !outResult.timeout && outResult.who == null);
1139 if (outResult.result == START_TASK_TO_FRONT) {
1140 res = START_TASK_TO_FRONT;
1141 }
1142 break;
1143 }
1144 case START_DELIVERED_TO_TOP: {
1145 outResult.timeout = false;
1146 outResult.who = r.realActivity;
1147 outResult.totalTime = 0;
1148 outResult.thisTime = 0;
1149 break;
1150 }
1151 case START_TASK_TO_FRONT: {
1152 // ActivityRecord may represent a different activity, but it should not be
1153 // in the resumed state.
1154 if (r.nowVisible && r.isState(RESUMED)) {
1155 outResult.timeout = false;
1156 outResult.who = r.realActivity;
1157 outResult.totalTime = 0;
1158 outResult.thisTime = 0;
1159 } else {
1160 outResult.thisTime = SystemClock.uptimeMillis();
1161 mSupervisor.waitActivityVisible(r.realActivity, outResult);
1162 // Note: the timeout variable is not currently not ever set.
1163 do {
1164 try {
1165 mService.wait();
1166 } catch (InterruptedException e) {
1167 }
1168 } while (!outResult.timeout && outResult.who == null);
1169 }
1170 break;
1171 }
1172 }
1173 }
1174
1175 mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(res, outRecord[0]);
1176 return res;
1177 }
1178 }
ActivityStarter#startActivity
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, TaskRecord inTask, String reason,
boolean allowPendingRemoteAnimationRegistryLookup) {
if (TextUtils.isEmpty(reason)) {
throw new IllegalArgumentException("Need to specify a reason.");
}
mLastStartReason = reason;
mLastStartActivityTimeMs = System.currentTimeMillis();
mLastStartActivityRecord[0] = null;
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask, allowPendingRemoteAnimationRegistryLookup);
if (outActivity != null) {
// mLastStartActivityRecord[0] is set in the call to startActivity above.
outActivity[0] = mLastStartActivityRecord[0];
}
return getExternalResult(mLastStartActivityResult);
}
575 private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
576 String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
577 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
578 IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
579 String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
580 SafeActivityOptions options,
581 boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
582 TaskRecord inTask, boolean allowPendingRemoteAnimationRegistryLookup) {
583 int err = ActivityManager.START_SUCCESS;
584 // Pull the optional Ephemeral Installer-only bundle out of the options early.
585 final Bundle verificationBundle
586 = options != null ? options.popAppVerificationBundle() : null;
587
588 ProcessRecord callerApp = null;
589 if (caller != null) {
590 callerApp = mService.getRecordForAppLocked(caller);
591 if (callerApp != null) {
592 callingPid = callerApp.pid;
593 callingUid = callerApp.info.uid;
594 } else {
595 Slog.w(TAG, "Unable to find app for caller " + caller
596 + " (pid=" + callingPid + ") when starting: "
597 + intent.toString());
598 err = ActivityManager.START_PERMISSION_DENIED;
599 }
600 }
601
602 final int userId = aInfo != null && aInfo.applicationInfo != null
603 ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
604
605 if (err == ActivityManager.START_SUCCESS) {
606 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
607 + "} from uid " + callingUid);
608 }
609
610 ActivityRecord sourceRecord = null;
611 ActivityRecord resultRecord = null;
612 if (resultTo != null) {
613 sourceRecord = mSupervisor.isInAnyStackLocked(resultTo);
614 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS,
615 "Will send result to " + resultTo + " " + sourceRecord);
616 if (sourceRecord != null) {
617 if (requestCode >= 0 && !sourceRecord.finishing) {
618 resultRecord = sourceRecord;
619 }
620 }
621 }
622
623 final int launchFlags = intent.getFlags();
624
625 if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
626 // Transfer the result target from the source activity to the new
627 // one being started, including any failures.
628 if (requestCode >= 0) {
629 SafeActivityOptions.abort(options);
630 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
631 }
632 resultRecord = sourceRecord.resultTo;
633 if (resultRecord != null && !resultRecord.isInStackLocked()) {
634 resultRecord = null;
635 }
636 resultWho = sourceRecord.resultWho;
637 requestCode = sourceRecord.requestCode;
638 sourceRecord.resultTo = null;
639 if (resultRecord != null) {
640 resultRecord.removeResultsLocked(sourceRecord, resultWho, requestCode);
641 }
642 if (sourceRecord.launchedFromUid == callingUid) {
643 // The new activity is being launched from the same uid as the previous
644 // activity in the flow, and asking to forward its result back to the
645 // previous. In this case the activity is serving as a trampoline between
646 // the two, so we also want to update its launchedFromPackage to be the
647 // same as the previous activity. Note that this is safe, since we know
648 // these two packages come from the same uid; the caller could just as
649 // well have supplied that same package name itself. This specifially
650 // deals with the case of an intent picker/chooser being launched in the app
651 // flow to redirect to an activity picked by the user, where we want the final
652 // activity to consider it to have been launched by the previous app activity.
653 callingPackage = sourceRecord.launchedFromPackage;
654 }
655 }
656
657 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
658 // We couldn't find a class that can handle the given Intent.
659 // That's the end of that!
660 err = ActivityManager.START_INTENT_NOT_RESOLVED;
661 }
662
663 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
664 // We couldn't find the specific class specified in the Intent.
665 // Also the end of the line.
666 err = ActivityManager.START_CLASS_NOT_FOUND;
667 }
668
669 if (err == ActivityManager.START_SUCCESS && sourceRecord != null
670 && sourceRecord.getTask().voiceSession != null) {
671 // If this activity is being launched as part of a voice session, we need
672 // to ensure that it is safe to do so. If the upcoming activity will also
673 // be part of the voice session, we can only launch it if it has explicitly
674 // said it supports the VOICE category, or it is a part of the calling app.
675 if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) == 0
676 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
677 try {
678 intent.addCategory(Intent.CATEGORY_VOICE);
679 if (!mService.getPackageManager().activitySupportsIntent(
680 intent.getComponent(), intent, resolvedType)) {
681 Slog.w(TAG,
682 "Activity being started in current voice task does not support voice: "
683 + intent);
684 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
685 }
686 } catch (RemoteException e) {
687 Slog.w(TAG, "Failure checking voice capabilities", e);
688 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
689 }
690 }
691 }
692
693 if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
694 // If the caller is starting a new voice session, just make sure the target
695 // is actually allowing it to run this way.
696 try {
697 if (!mService.getPackageManager().activitySupportsIntent(intent.getComponent(),
698 intent, resolvedType)) {
699 Slog.w(TAG,
700 "Activity being started in new voice task does not support: "
701 + intent);
702 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
703 }
704 } catch (RemoteException e) {
705 Slog.w(TAG, "Failure checking voice capabilities", e);
706 err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
707 }
708 }
709
710 final ActivityStack resultStack = resultRecord == null ? null : resultRecord.getStack();
711
712 if (err != START_SUCCESS) {
713 if (resultRecord != null) {
714 resultStack.sendActivityResultLocked(
715 -1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
716 }
717 SafeActivityOptions.abort(options);
718 return err;
719 }
720
721 boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
722 requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
723 inTask != null, callerApp, resultRecord, resultStack);
724 abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
725 callingPid, resolvedType, aInfo.applicationInfo);
726
727 // Merge the two options bundles, while realCallerOptions takes precedence.
728 ActivityOptions checkedOptions = options != null
729 ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
730 : null;
731 if (allowPendingRemoteAnimationRegistryLookup) {
732 checkedOptions = mService.getActivityStartController()
733 .getPendingRemoteAnimationRegistry()
734 .overrideOptionsIfNeeded(callingPackage, checkedOptions);
735 }
736 if (mService.mController != null) {
737 try {
738 // The Intent we give to the watcher has the extra data
739 // stripped off, since it can contain private information.
740 Intent watchIntent = intent.cloneFilter();
741 abort |= !mService.mController.activityStarting(watchIntent,
742 aInfo.applicationInfo.packageName);
743 } catch (RemoteException e) {
744 mService.mController = null;
745 }
746 }
747
748 mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
749 if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
750 callingUid, checkedOptions)) {
751 // activity start was intercepted, e.g. because the target user is currently in quiet
752 // mode (turn off work) or the target application is suspended
753 intent = mInterceptor.mIntent;
754 rInfo = mInterceptor.mRInfo;
755 aInfo = mInterceptor.mAInfo;
756 resolvedType = mInterceptor.mResolvedType;
757 inTask = mInterceptor.mInTask;
758 callingPid = mInterceptor.mCallingPid;
759 callingUid = mInterceptor.mCallingUid;
760 checkedOptions = mInterceptor.mActivityOptions;
761 }
762
763 if (abort) {
764 if (resultRecord != null) {
765 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
766 RESULT_CANCELED, null);
767 }
768 // We pretend to the caller that it was really started, but
769 // they will just get a cancel result.
770 ActivityOptions.abort(checkedOptions);
771 return START_ABORTED;
772 }
773
774 // If permissions need a review before any of the app components can run, we
775 // launch the review activity and pass a pending intent to start the activity
776 // we are to launching now after the review is completed.
777 if (mService.mPermissionReviewRequired && aInfo != null) {
778 if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
779 aInfo.packageName, userId)) {
780 IIntentSender target = mService.getIntentSenderLocked(
781 ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
782 callingUid, userId, null, null, 0, new Intent[]{intent},
783 new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
784 | PendingIntent.FLAG_ONE_SHOT, null);
785
786 final int flags = intent.getFlags();
787 Intent newIntent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
788 newIntent.setFlags(flags
789 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
790 newIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, aInfo.packageName);
791 newIntent.putExtra(Intent.EXTRA_INTENT, new IntentSender(target));
792 if (resultRecord != null) {
793 newIntent.putExtra(Intent.EXTRA_RESULT_NEEDED, true);
794 }
795 intent = newIntent;
796
797 resolvedType = null;
798 callingUid = realCallingUid;
799 callingPid = realCallingPid;
800
801 rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId, 0,
802 computeResolveFilterUid(
803 callingUid, realCallingUid, mRequest.filterCallingUid));
804 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags,
805 null /*profilerInfo*/);
806
807 if (DEBUG_PERMISSIONS_REVIEW) {
808 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true,
809 true, false) + "} from uid " + callingUid + " on display "
810 + (mSupervisor.mFocusedStack == null
811 ? DEFAULT_DISPLAY : mSupervisor.mFocusedStack.mDisplayId));
812 }
813 }
814 }
815
816 // If we have an ephemeral app, abort the process of launching the resolved intent.
817 // Instead, launch the ephemeral installer. Once the installer is finished, it
818 // starts either the intent we resolved here [on install error] or the ephemeral
819 // app [on install success].
820 if (rInfo != null && rInfo.auxiliaryInfo != null) {
821 intent = createLaunchIntent(rInfo.auxiliaryInfo, ephemeralIntent,
822 callingPackage, verificationBundle, resolvedType, userId);
823 resolvedType = null;
824 callingUid = realCallingUid;
825 callingPid = realCallingPid;
826
827 aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, null /*profilerInfo*/);
828 }
829 //创建要启动的Activity对应的ActivityRecord
830 ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
831 callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
832 resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
833 mSupervisor, checkedOptions, sourceRecord);
834 if (outActivity != null) {
835 outActivity[0] = r;
836 }
837
838 if (r.appTimeTracker == null && sourceRecord != null) {
839 // If the caller didn't specify an explicit time tracker, we want to continue
840 // tracking under any it has.
841 r.appTimeTracker = sourceRecord.appTimeTracker;
842 }
843
844 final ActivityStack stack = mSupervisor.mFocusedStack;
845
846 // If we are starting an activity that is not from the same uid as the currently resumed
847 // one, check whether app switches are allowed.
848 if (voiceSession == null && (stack.getResumedActivity() == null
849 || stack.getResumedActivity().info.applicationInfo.uid != realCallingUid)) {
850 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
851 realCallingPid, realCallingUid, "Activity start")) {
852 mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
853 sourceRecord, startFlags, stack, callerApp));
854 ActivityOptions.abort(checkedOptions);
855 return ActivityManager.START_SWITCHES_CANCELED;
856 }
857 }
858
859 if (mService.mDidAppSwitch) {
860 // This is the second allowed switch since we stopped switches,
861 // so now just generally allow switches. Use case: user presses
862 // home (switches disabled, switch to home, mDidAppSwitch now true);
863 // user taps a home icon (coming from home so allowed, we hit here
864 // and now allow anyone to switch again).
865 mService.mAppSwitchesAllowedTime = 0;
866 } else {
867 mService.mDidAppSwitch = true;
868 }
869
870 mController.doPendingActivityLaunches(false);
871
872 return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
873 true /* doResume */, checkedOptions, inTask, outActivity);
874 }
1197 private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
1198 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1199 int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
1200 ActivityRecord[] outActivity) {
1201 int result = START_CANCELED;
1202 try {
1203 mService.mWindowManager.deferSurfaceLayout();
1204 result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
1205 startFlags, doResume, options, inTask, outActivity);
1206 } finally {
1207 // If we are not able to proceed, disassociate the activity from the task. Leaving an
1208 // activity in an incomplete state can lead to issues, such as performing operations
1209 // without a window container.
1210 final ActivityStack stack = mStartActivity.getStack();
1211 if (!ActivityManager.isStartResultSuccessful(result) && stack != null) {
1212 stack.finishActivityLocked(mStartActivity, RESULT_CANCELED,
1213 null /* intentResultData */, "startActivity", true /* oomAdj */);
1214 }
1215 mService.mWindowManager.continueSurfaceLayout();
1216 }
1217
1218 postStartActivityProcessing(r, result, mTargetStack);
1219
1220 return result;
1221 }
以上做完了参数准备工作和检查工作,下面开始真正启动Activity的核心操作,见startActivityUnchecked
网友评论