系列文章
Android S从桌面点击图标启动APP流程 (一)
Android S从桌面点击图标启动APP流程 (二)
Android 12的源码链接:
Android 12 Aosphttp://aospxref.com/android-12.0.0_r3/
16. ActivityStarter#startActivityUnchecked
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
*在完成大部分初步检查并确认调用方拥有执行此操作的必要权限时启动activity 。此处还可确保在启动不成功时删除启动activity 。 private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { int result = START_CANCELED; final Task startedActivityRootTask; 立即创建一个过渡,以记录在 startActivityInner 中执行的操作的原始意图。否则,startActivityInner 中的逻辑可能会根据子操作启动不同的转换。只在这里创建(并推迟requestStart),因为startActivityInside可能会中止。 final Transition newTransition = (!mService.getTransitionController().isCollecting() && mService.getTransitionController().getTransitionPlayer() != null) ? mService.getTransitionController().createTransition(TRANSIT_OPEN) : null; IRemoteTransition remoteTransition = r.takeRemoteTransition(); if (newTransition != null && remoteTransition != null) { newTransition.setRemoteTransition(remoteTransition); } mService.getTransitionController().collect(r); try { //延迟绘制 mService.deferWindowLayout(); Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); //start activity result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); startedActivityRootTask = handleStartResult(r, result); //continue绘制 mService.continueWindowLayout();
10-08 23:28:37.882 1601 1817 I ActivityTaskManager: continueWindowLayout reason=0 frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java /** @see WindowSurfacePlacer#continueLayout */ void continueWindowLayout() { mWindowManager.mWindowPlacerLocked.continueLayout(mLayoutReasons != 0); if (DEBUG_ALL && !mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) { Slog.i(TAG, "continueWindowLayout reason=" + mLayoutReasons); } } /** @see WindowSurfacePlacer#deferLayout */ void deferWindowLayout() { if (!mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) { // Reset the reasons at the first entrance because we only care about the changes in the deferred scope. mLayoutReasons = 0; } mWindowManager.mWindowPlacerLocked.deferLayout(); }
mSupervisor.mUserLeaving = false;// Transition housekeeping
if (!ActivityManager.isStartResultSuccessful(result)) {
if (newTransition != null) {
newTransition.abort();
}
} else {
if (!mAvoidMoveToFront && mDoResume
&& mRootWindowContainer.hasVisibleWindowAboveButDoesNotOwnNotificationShade( r.launchedFromUid)) {
如果正在启动的activity 的 UID 在通知栏的顶部有一个可见窗口,并且它启动的activity 将位于前面,我们应该将底页移开,以便用户可以看到它。我们希望避免在未移动到前面的后台任务之上启动activity 的情况。
StatusBarManagerInternal statusBar = mService.getStatusBarManagerInternal();
if (statusBar != null) {
// This results in a async call since the interface is one-way
这会导致异步调用,因为接口是单向的
statusBar.collapsePanels();
}
}
if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
// The activity is started new rather than just brought forward, so record it as an existence change.
activity 是新开始的,而不仅仅是提前开始的,因此请将其记录为存在更改。
mService.getTransitionController().collectExistenceChange(r);
}
if (newTransition != null) {
mService.getTransitionController().requestStartTransition(newTransition,
mTargetTask, remoteTransition);
} else {
// Make the collecting transition wait until this request is ready.
使ollecting transition等到此请求准备就绪。
mService.getTransitionController().setReady(false);
}
}
}postStartActivityProcessing(r, result, startedActivityRootTask);
return result;
}
17. ActivityStarter#startActivityInner
frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
启动activity并确定该activity是应添加到现有任务的顶部,还是应将新意向交付到现有activity。还将activity task操作到请求的或有效的根任务/显示上。 @VisibleForTesting int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask, boolean restrictedBgActivity, NeededUriGrants intentGrants) { setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,voiceInteractor, restrictedBgActivity); computeLaunchingTaskFlags(); computeSourceRootTask(); mIntent.setFlags(mLaunchFlags); final Task reusedTask = getReusableTask(); setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession, voiceInteractor, restrictedBgActivity); //计算启动的Flags computeLaunchingTaskFlags(); computeSourceRootTask(); mIntent.setFlags(mLaunchFlags); final Task reusedTask = getReusableTask(); // If requested, freeze the task list if (mOptions != null && mOptions.freezeRecentTasksReordering() && mSupervisor.mRecentTasks.isCallerRecents(r.launchedFromUid) && !mSupervisor.mRecentTasks.isFreezeTaskListReorderingSet()) { mFrozeTaskList = true; mSupervisor.mRecentTasks.setFreezeTaskListReordering(); } // Compute if there is an existing task that should be used for. final Task targetTask = reusedTask != null ? reusedTask : computeTargetTask(); final boolean newTask = targetTask == null; mTargetTask = targetTask; computeLaunchParams(r, sourceRecord, targetTask); // Check if starting activity on given task or on a new task is allowed. int startResult = isAllowedToStart(r, newTask, targetTask); if (startResult != START_SUCCESS) { return startResult; } final ActivityRecord targetTaskTop = newTask ? null : targetTask.getTopNonFinishingActivity(); if (targetTaskTop != null) { // Recycle the target task for this launch. startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } else { mAddingToTask = true; } // If the activity being launched is the same as the one currently at the top, then we need to check if it should only be launched once. final Task topRootTask = mPreferredTaskDisplayArea.getFocusedRootTask(); if (topRootTask != null) { startResult = deliverToCurrentTopIfNeeded(topRootTask, intentGrants); if (startResult != START_SUCCESS) { return startResult; } } if (mTargetRootTask == null) { mTargetRootTask = getLaunchRootTask(mStartActivity, mLaunchFlags, targetTask, mOptions); } if (newTask) { final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null) ? mSourceRecord.getTask() : null; setNewTask(taskToAffiliate); } else if (mAddingToTask) { addOrReparentStartingActivity(targetTask, "adding to task"); } if (!mAvoidMoveToFront && mDoResume) { mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask); if (mOptions != null) { if (mOptions.getTaskAlwaysOnTop()) { mTargetRootTask.setAlwaysOnTop(true); } } if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.mInternal.isDreaming()) { // Launching underneath dream activity (fullscreen, always-on-top). Run the launch- -behind transition so the Activity gets created and starts in visible state. mLaunchTaskBehind = true; r.mLaunchTaskBehind = true; } } mService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants, mStartActivity.getUriPermissionsLocked()); if (mStartActivity.resultTo != null && mStartActivity.resultTo.info != null) { // we need to resolve resultTo to a uid as grantImplicitAccess deals explicitly in UIDs final PackageManagerInternal pmInternal = mService.getPackageManagerInternalLocked(); final int resultToUid = pmInternal.getPackageUid( mStartActivity.resultTo.info.packageName, 0 /* flags */, mStartActivity.mUserId); pmInternal.grantImplicitAccess(mStartActivity.mUserId, mIntent, UserHandle.getAppId(mStartActivity.info.applicationInfo.uid) /*recipient*/, resultToUid /*visible*/, true /*direct*/); } if (newTask) { EventLogTags.writeWmCreateTask(mStartActivity.mUserId, mStartActivity.getTask().mTaskId); } mStartActivity.logStartActivity( EventLogTags.WM_CREATE_ACTIVITY, mStartActivity.getTask()); mTargetRootTask.mLastPausedActivity = null; mRootWindowContainer.startPowerModeLaunchIfNeeded( false /* forceSend */, mStartActivity); mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask,mKeepCurTransition, mOptions, sourceRecord); 10-11 05:23:15.891 1562 1782 V ActivityTaskManager: Prepare open transition: starting ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8} if (mDoResume) { final ActivityRecord topTaskActivity = mStartActivity.getTask().topRunningActivityLocked(); if (!mTargetRootTask.isTopActivityFocusable() || (topTaskActivity != null && topTaskActivity.isTaskOverlay() && mStartActivity != topTaskActivity)) { mTargetRootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS); mTargetRootTask.mDisplayContent.executeAppTransition(); } else { if (mTargetRootTask.isTopActivityFocusable() && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) { mTargetRootTask.moveToFront("startActivityInner"); } mRootWindowContainer.resumeFocusedTasksTopActivities( mTargetRootTask, mStartActivity, mOptions, mTransientLaunch); 10-11 05:23:15.894 1562 1782 V ActivityTaskManager: Resuming ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8} 10-11 05:23:15.895 1562 1782 D ActivityTaskManager: setResumedActivity taskFrag:Task{3aa0954 #6 type=home I=com.android.launcher3/.uioverrides.QuickstepLauncher U=0 rootTaskId=1 visible=true visibleRequested=true mode=fullscreen translucent=false sz=1} + from: ActivityRecord{b1a7043 u0 com.android.launcher3/.uioverrides.QuickstepLauncher t6} to:null reason:startPausingLocked - onActivityStateChanged } } mRootWindowContainer.updateUserRootTask(mStartActivity.mUserId, mTargetRootTask); //活动开始时立即更新近期任务列表 // Update the recent tasks list immediately when the activity starts mSupervisor.mRecentTasks.add(mStartActivity.getTask()); 10-11 05:23:15.896 1562 1782 D ActivityTaskManager: add: task=Task{126146d #8 type=standard A=10075:android.task.calendar U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1} 10-11 05:23:15.897 1562 1782 D ActivityTaskManager: addRecent: trimming tasks for Task{126146d #8 type=standard A=10075:android.task.calendar U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1} 10-11 05:23:15.897 1562 1782 D ActivityTaskManager: addRecent: adding Task{126146d #8 type=standard A=10075:android.task.calendar U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1} mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), mPreferredWindowingMode, mPreferredTaskDisplayArea, mTargetRootTask); return START_SUCCESS; }
18. ActivityStarter#startActivityLocked
void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options,
@Nullable ActivityRecord sourceRecord) {
Task rTask = r.getTask();
final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
final boolean isOrhasTask = rTask == this || hasChild(rTask);
// mLaunchTaskBehind tasks get placed at the back of the task stack.
if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
// Last activity in task had been removed or ActivityManagerService is reusing task. Insert or replace. Might not even be in.任务中的最后一个activity 已被删除,或者activity 管理器服务正在重用task。插入或替换。甚至可能不在。
positionChildAtTop(rTask);
}
Task task = null;
if (!newTask && isOrhasTask) {
// Starting activity cannot be occluding activity, otherwise starting window could be remove immediately without transferring to starting activity.Starting activity不能遮挡活动,否则可以立即删除Starting activity,而不会转移到启动activity。
final ActivityRecord occludingActivity = getOccludingActivityAbove(r);
if (occludingActivity != null) {
// Here it is! Now, if this is not yet visible (occluded by another task) to the user, then just add it without starting; it will get started when the user navigates back to it.现在,如果这对用户还不可见(被另一个任务遮挡),那么只需添加它而不启动;当用户导航回到它时,它将开始。
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
+ "callers: %s", r, task,
new RuntimeException("here").fillInStackTrace());
rTask.positionChildAtTop(r);
ActivityOptions.abort(options);
return;
}
}// Place a new activity at top of root task, so it is next to interact with the user. If we are not placing the new activity frontmost, we do not want to deliver the onUserLeaving callback to the actual frontmost activity
将新activity放在根任务的顶部,以便它接下来与用户交互。如果我们没有将新activity放在最前面,我们不希望将 onUserLeave 回调传递到实际的最前面的activity
final Task activityTask = r.getTask();
if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) {
mTaskSupervisor.mUserLeaving = false;
if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
"startActivity() behind front, mUserLeaving=false");
}task = activityTask;
// Slot the activity into the history root task and proceed
ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
+ "callers: %s", r, task, new RuntimeException("here").fillInStackTrace());
task.positionChildAtTop(r);//如果 {@code allowMoveToFront} 为 false,则不需要过渡动画和启动窗口,因为活动将不可见。
if ((!isHomeOrRecentsRootTask() || hasActivity()) && allowMoveToFront) {
final DisplayContent dc = mDisplayContent;
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: starting " + r);
10-11 05:23:15.891 1562 1782 V ActivityTaskManager: Prepare open transition: starting ActivityRecord{be18a2 u0 com.android.calendar/.AllInOneActivity t8}
// TODO(shell-transitions): record NO_ANIMATION flag somewhere.
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
dc.prepareAppTransition(TRANSIT_NONE);
mTaskSupervisor.mNoAnimActivities.add(r);
} else {
int transit = TRANSIT_OLD_ACTIVITY_OPEN;
if (newTask) {
if (r.mLaunchTaskBehind) {
transit = TRANSIT_OLD_TASK_OPEN_BEHIND;
} else {
// 如果正在启动新任务,则将现有的顶部activity标记为支持画中画,同时仅在启动activity不被视为当前activity之上的叠加层(例如,不是全屏或助手)时暂停
if (canEnterPipOnTaskSwitch(focusedTopActivity,
null /* toFrontTask */, r, options)) {
focusedTopActivity.supportsEnterPipOnTaskSwitch = true;
}
transit = TRANSIT_OLD_TASK_OPEN;
}
}
dc.prepareAppTransition(TRANSIT_OPEN);
mTaskSupervisor.mNoAnimActivities.remove(r);
}
boolean doShow = true;
if (newTask) {
//即使此activity是重新开始的,我们仍然需要重置它,以确保我们应用相关性将任何现有activity从其他任务移动到它。如果调用方已请求重置目标任务,则执行此操作。
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeeded(r, r);
doShow = topRunningNonDelayedActivityLocked(null) == r;
}
} else if (options != null && options.getAnimationType()
== ActivityOptions.ANIM_SCENE_TRANSITION) {
doShow = false;
}
if (r.mLaunchTaskBehind) {//不要为 mLaunchTaskBehind 做一个starting window。更重要的是,确保我们告诉 WindowManager r 是可见的,即使它位于根任务的后面。
r.setVisibility(true);
ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
// 继续为此activity执行应用转换,因为不会通过恢复通道触发应用转换。
mDisplayContent.executeAppTransition();
} else if (SHOW_APP_STARTING_PREVIEW && doShow) {
// Figure out if we are transitioning from another activity that is "has the same starting icon" as the next one. This allows the window manager to keep the previous window it had previously created, if it still had one.
Task prevTask = r.getTask();
ActivityRecord prev = prevTask.topActivityWithStartingWindow();
if (prev != null) {
// We don't want to reuse the previous starting preview if: (1) The current activity is in a different task.
if (prev.getTask() != prevTask) {
prev = null;
}
// (2) The current activity is already displayed.
else if (prev.nowVisible) {
prev = null;
}
}//显示starting window
//showStartingWindow->addStartingWindow->addSplashScreenStartingWindow
r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity),true /* startActivity */, sourceRecord);
10-11 05:23:15.935 1863 2028 D SplashScreenView: Build android.window.SplashScreenView{6a2eb98 V.E...... ......ID 0,0-0,0}
10-11 05:23:15.935 1863 2028 D SplashScreenView: Icon: view: android.widget.ImageView{6b6cff1 V.ED..... ......I. 0,0-0,0 #10204aa android:id/splashscreen_icon_view} drawable: com.android.wm.shell.startingsurface.SplashscreenIconDrawableFactory$ImmobileIconDrawable@49827d6 size: 640
10-11 05:23:15.935 1863 2028 D SplashScreenView: Branding: view: android.view.View{6705a57 G.ED..... ......I. 0,0-0,0 #10204a9 android:id/splashscreen_branding_view} drawable: null size w: 0 h: 0
}
} else {
// If this is the first activity, don't do any fancy animations, because there is nothing for it to animate on top of.
ActivityOptions.abort(options);
}
}
19. RootWindowContainer#resumeFocusedTasksTopActivities
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedTasksTopActivities() {
return resumeFocusedTasksTopActivities(null, null, null);
}
----------------------------------------------------------------------------------
boolean resumeFocusedTasksTopActivities(
Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions) {
return resumeFocusedTasksTopActivities(targetRootTask, target, targetOptions, false /* deferPause */);
}
----------------------------------------------------------------------------------
boolean resumeFocusedTasksTopActivities(
Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause) {
if (!mTaskSupervisor.readyToResume()) {
return false;
}boolean result = false;
if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()
|| getTopDisplayFocusedRootTask() == targetRootTask)) {
result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions, deferPause);
}for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
final boolean curResult = result;
boolean[] resumedOnDisplay = new boolean[1];
display.forAllRootTasks(rootTask -> {
final ActivityRecord topRunningActivity = rootTask.topRunningActivity();
if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) {
return;
}
if (rootTask == targetRootTask) {
resumedOnDisplay[0] |= curResult;
return;
}
if (rootTask.getDisplayArea().isTopRootTask(rootTask)
&& topRunningActivity.isState(RESUMED)) {
rootTask.executeAppTransition(targetOptions);
} else {
resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target);
}
});
result |= resumedOnDisplay[0];
if (!resumedOnDisplay[0]) {
final Task focusedRoot = display.getFocusedRootTask();
if (focusedRoot != null) {
result |= focusedRoot.resumeTopActivityUncheckedLocked(target, targetOptions);
} else if (targetRootTask == null) {
result |= resumeHomeActivity(null /* prev */, "no-focusable-task", display.getDefaultTaskDisplayArea());
}
}
}return result;
}
20. RootWindowContainer#resumeTopActivityUncheckedLocked
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);
}
----------------------------------------------------------------------------
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
if (mInResumeTopActivity) {
// Don't even start recursing.
return false;
}boolean someActivityResumed = false;
try {
// Protect against recursion.
mInResumeTopActivity = true;if (isLeafTask()) {
if (isFocusableAndVisible()) {
//
someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
}
} else {
int idx = mChildren.size() - 1;
while (idx >= 0) {
final Task child = (Task) getChildAt(idx--);
if (!child.isTopActivityFocusable()) {
continue;
}
if (child.getVisibility(null /* starting */) != TASK_VISIBILITY_VISIBLE) {
break;
}someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options, deferPause);
if (idx >= mChildren.size()) {
idx = mChildren.size() - 1;
}
}
}
final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
if (next == null || !next.canTurnScreenOn()) {
checkReadyForSleep();
}
} finally {
mInResumeTopActivity = false;
}return someActivityResumed;
}
21. RootWindowContainer#resumeTopActivityInnerLocked
frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
boolean deferPause) {
...next代表将要去resume的activity
ActivityRecord next = topRunningActivity(true /* focusableOnly */);final boolean hasRunningActivity = next != null;
// TODO: Maybe this entire condition can get removed?
if (hasRunningActivity && !isAttached()) {
return false;
}mRootWindowContainer.cancelInitializingActivities();
if (!hasRunningActivity) {//如果将要启动的activity为null
// There are no activities left in the root task, let's look somewhere else.根任务中没有activitiy,让我们看看其他地方。
return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
}next.delayedResume = false;
final TaskDisplayArea taskDisplayArea = getDisplayArea();// If the top activity is the resumed one, nothing to do.
如果top activity是resumed的activity,则无需执行任何操作。
if (mResumedActivity == next && next.isState(RESUMED)
&& taskDisplayArea.allResumedActivitiesComplete()) {
//确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
executeAppTransition(options);
对于未处于全屏模式的设备(例如自由格式窗口),我们可能仍希望检查其他窗口的可见性是否已更改(例如,将全屏窗口向前移动以覆盖另一个自由格式活动)。
if (taskDisplayArea.inMultiWindowMode()) {
taskDisplayArea.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
false /* preserveWindows */, true /* notifyClients */);
}
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Top activity "
+ "resumed %s", next);
return false;
}if (!next.canResumeByCompat()) {
return false;
}//如果我们当前正在暂停一个activity,那么在暂停之前不要执行任何操作。
final boolean allPausedComplete = mRootWindowContainer.allPausedActivitiesComplete();
if (!allPausedComplete) {
ProtoLog.v(WM_DEBUG_STATES,
"resumeTopActivityLocked: Skip resume: some activity pausing.");return false;
}
//如果我们在sleeping,并且没有resumed的activity,并且顶级activity暂停,那么这就是我们想要的状态。
if (mLastPausedActivity == next && shouldSleepOrShutDownActivities()) {
//确保我们已执行任何挂起的转换,因为此时应该没有什么可做的。
executeAppTransition(options);
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Going to sleep and"
+ " all paused");
return false;
}//确保拥有此activity的用户已启动。 如果没有,我们将保持原样,因为有人应该将其他用户的activity带到堆栈的顶部。
if (!mAtmService.mAmInternal.hasStartedUserState(next.mUserId)) {
Slog.w(TAG, "Skipping resume of top activity " + next
+ ": user " + next.mUserId + " is stopped");
return false;
}activity可能正在等待停止,但这不再适合它。
mTaskSupervisor.mStoppingActivities.remove(next);if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);
10-08 23:28:37.877 1601 1817 V ActivityTaskManager: Resuming ActivityRecord{37cd946 u0 com.example.android.locationattribution/.MainActivity t9}
mTaskSupervisor.setLaunchSource(next.info.applicationInfo.uid);
ActivityRecord lastResumed = null;
final Task lastFocusedRootTask = taskDisplayArea.getLastFocusedRootTask();
if (lastFocusedRootTask != null && lastFocusedRootTask != getRootTask()) {那么,我们为什么不在这里使用 prev呢???请参阅有关该方法的参数注释。“上一个”不表示上次resumed的activity。但是,如果最后一个焦点堆栈不为 null,则它执行。
lastResumed = lastFocusedRootTask.getResumedActivity();
}boolean pausing = !deferPause && taskDisplayArea.pauseBackTasks(next);
if (mResumedActivity != null) {
ProtoLog.d(WM_DEBUG_STATES, "resumeTopActivityLocked: Pausing %s", mResumedActivity);
pausing |= startPausingLocked(false /* uiSleeping */, next,
"resumeTopActivityInnerLocked");
}...
22. taskDisplayArea#pauseBackTasks
frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java boolean pauseBackTasks(ActivityRecord resuming) { final int[] someActivityPaused = {0}; forAllLeafTasks((task) -> { final ActivityRecord resumedActivity = task.getResumedActivity(); if (resumedActivity != null && (task.getVisibility(resuming) != TASK_VISIBILITY_VISIBLE || !task.isTopActivityFocusable())) { ProtoLog.d(WM_DEBUG_STATES, "pauseBackTasks: task=%s " + "mResumedActivity=%s", task, resumedActivity); if (task.startPausingLocked(false /* uiSleeping*/, resuming, "pauseBackTasks")) { someActivityPaused[0]++; } } }, true /* traverseTopToBottom */); return someActivityPaused[0] > 0; }
23. Task#startPausingLocked
frameworks/base/services/core/java/com/android/server/wm/Task.java final boolean startPausingLocked(boolean uiSleeping, ActivityRecord resuming, String reason) { return startPausingLocked(mTaskSupervisor.mUserLeaving, uiSleeping, resuming, reason); }
24. Task#startPausingLocked
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming, String reason) {
if (!isLeafTask()) {
final int[] pausing = {0};
forAllLeafTasks((t) -> {
if (t.startPausingLocked(userLeaving, uiSleeping, resuming, reason)) {
pausing[0]++;
}
}, true /* traverseTopToBottom */);
return pausing[0] > 0;
}if (mPausingActivity != null) {
Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
+ " state=" + mPausingActivity.getState());
if (!shouldSleepActivities()) {避免检查睡眠时递归,并在睡眠期间完全暂停。由于activity 将在resume后立即暂停,因此只需让暂停按客户端暂停的activity 顺序完成即可。
completePauseLocked(false, resuming);
}
}
ActivityRecord prev = mResumedActivity;if (prev == null) {
if (resuming == null) {
Slog.wtf(TAG, "Trying to pause when nothing is resumed");
mRootWindowContainer.resumeFocusedTasksTopActivities();
}
return false;
}if (prev == resuming) {
Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
return false;
}ProtoLog.v(WM_DEBUG_STATES, "Moving to PAUSING: %s", prev);
mPausingActivity = prev;
mLastPausedActivity = prev;
if (prev.isNoHistory() && !mTaskSupervisor.mNoHistoryActivities.contains(prev)) {
mTaskSupervisor.mNoHistoryActivities.add(prev);
}
prev.setState(PAUSING, "startPausingLocked");
prev.getTask().touchActiveTime();mAtmService.updateCpuStats();
boolean pauseImmediately = false;
boolean shouldAutoPip = false;
if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {如果设置了标志RESUME_WHILE_PAUSING,则继续安排暂停上一个activity ,同时仅当上一个activity 无法进入 Pip 时才恢复新的resumed activity 活动,因为我们希望让 Pip 活动有机会在恢复下一个activity 之前进入 Pip。
final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState("shouldResumeWhilePausing", userLeaving);
if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
shouldAutoPip = true;
} else if (!lastResumedCanPip) {
pauseImmediately = true;
} else {
// The previous activity may still enter PIP even though it did not allow auto-PIP.
}
}boolean didAutoPip = false;
if (prev.attachedToProcess()) {
if (shouldAutoPip) {//进入PIP
ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
+ "directly: %s", prev);didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs);
mPausingActivity = null;
} else {
ProtoLog.v(WM_DEBUG_STATES, "Enqueueing pending pause: %s", prev);
try {
EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev), prev.shortComponentName, "userLeaving=" + userLeaving, reason);10-11 05:23:15.895 1562 1782 I wm_pause_activity: [0,186282051,com.android.launcher3/.uioverrides.QuickstepLauncher,userLeaving=true,pauseBackTasks] mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
...