Loading services/core/java/com/android/server/am/ActivityDisplay.java +59 −4 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; import static com.android.server.am.ActivityStackSupervisor.FindTaskResult; import static com.android.server.am.ActivityStackSupervisor.TAG_STATES; import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS; Loading Loading @@ -120,6 +121,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> */ private ActivityStack mPreferredTopFocusableStack; /** * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused * stack has been resumed. If stacks are changing position this will hold the old stack until * the new stack becomes resumed after which it will be set to current focused stack. */ private ActivityStack mLastFocusedStack; // Cached reference to some special stacks we tend to get a lot so we don't need to loop // through the list to find them. private ActivityStack mHomeStack = null; Loading Loading @@ -182,20 +190,33 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } void positionChildAtTop(ActivityStack stack, boolean includingParents) { positionChildAt(stack, mStacks.size(), includingParents); positionChildAtTop(stack, includingParents, null /* updateLastFocusedStackReason */); } void positionChildAtTop(ActivityStack stack, boolean includingParents, String updateLastFocusedStackReason) { positionChildAt(stack, mStacks.size(), includingParents, updateLastFocusedStackReason); } void positionChildAtBottom(ActivityStack stack) { positionChildAt(stack, 0, false /* includingParents */); positionChildAtBottom(stack, null /* updateLastFocusedStackReason */); } void positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason) { positionChildAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason); } private void positionChildAt(ActivityStack stack, int position) { positionChildAt(stack, position, false /* includingParents */); positionChildAt(stack, position, false /* includingParents */, null /* updateLastFocusedStackReason */); } private void positionChildAt(ActivityStack stack, int position, boolean includingParents) { private void positionChildAt(ActivityStack stack, int position, boolean includingParents, String updateLastFocusedStackReason) { // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust // the position internally, also update the logic here final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null ? getFocusedStack() : null; final boolean wasContained = mStacks.remove(stack); final int insertPosition = getTopInsertPosition(stack, position); mStacks.add(insertPosition, stack); Loading @@ -211,6 +232,17 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> mPreferredTopFocusableStack = null; } if (updateLastFocusedStackReason != null) { final ActivityStack currentFocusedStack = getFocusedStack(); if (currentFocusedStack != prevFocusedStack) { mLastFocusedStack = prevFocusedStack; EventLogTags.writeAmFocusedStack(mSupervisor.mCurrentUser, mDisplayId, currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(), mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), updateLastFocusedStackReason); } } // Since positionChildAt() is called during the creation process of pinned stacks, // ActivityStack#getWindowContainerController() can be null. In this special case, // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(), Loading Loading @@ -458,6 +490,26 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return resumedActivity; } ActivityStack getLastFocusedStack() { return mLastFocusedStack; } boolean allResumedActivitiesComplete() { for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityRecord r = mStacks.get(stackNdx).getResumedActivity(); if (r != null && !r.isState(RESUMED)) { return false; } } final ActivityStack currentFocusedStack = getFocusedStack(); if (DEBUG_STACK) { Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from=" + mLastFocusedStack + " to=" + currentFocusedStack); } mLastFocusedStack = currentFocusedStack; return true; } /** * Pause all activities in either all of the stacks or just the back stacks. * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving(). Loading Loading @@ -1138,6 +1190,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (mPreferredTopFocusableStack != null) { pw.println(myPrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack); } if (mLastFocusedStack != null) { pw.println(myPrefix + "mLastFocusedStack=" + mLastFocusedStack); } } public void dumpStacks(PrintWriter pw) { Loading services/core/java/com/android/server/am/ActivityStack.java +16 −19 Original line number Diff line number Diff line Loading @@ -1105,12 +1105,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai display.moveHomeStackToFront(reason + " returnToHome"); } display.positionChildAtTop(this, true /* includingParents */); mStackSupervisor.setFocusStackUnchecked(reason, this); if (task != null) { final boolean movingTask = task != null; display.positionChildAtTop(this, !movingTask /* includingParents */, reason); if (movingTask) { // This also moves the entire hierarchy branch to top, including parents insertTaskAtTop(task, null); return; insertTaskAtTop(task, null /* starting */); } } Loading @@ -1131,13 +1130,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai setWindowingMode(WINDOWING_MODE_UNDEFINED); } getDisplay().positionChildAtBottom(this); mStackSupervisor.setFocusStackUnchecked(reason, getDisplay().getTopStack()); getDisplay().positionChildAtBottom(this, reason); if (task != null) { // TODO(b/111541062): We probably don't want to change display z-order to bottom just // because one of its stacks moved to bottom. insertTaskAtBottom(task); return; } } Loading Loading @@ -2431,10 +2428,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } next.delayedResume = false; final ActivityDisplay display = getDisplay(); // If the top activity is the resumed one, nothing to do. if (mResumedActivity == next && next.isState(RESUMED) && mStackSupervisor.allResumedActivitiesComplete()) { && display.allResumedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. executeAppTransition(options); Loading Loading @@ -2500,7 +2498,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai boolean lastResumedCanPip = false; ActivityRecord lastResumed = null; final ActivityStack lastFocusedStack = mStackSupervisor.getTopDisplayLastFocusedStack(); final ActivityStack lastFocusedStack = display.getLastFocusedStack(); if (lastFocusedStack != null && lastFocusedStack != this) { // So, why aren't we using prev here??? See the param comment on the method. prev doesn't // represent the last resumed activity. However, the last focus stack does if it isn't null. Loading Loading @@ -2545,7 +2543,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } return true; } else if (mResumedActivity == next && next.isState(RESUMED) && mStackSupervisor.allResumedActivitiesComplete()) { && display.allResumedActivitiesComplete()) { // It is possible for the activity to be resumed when we paused back stacks above if the // next activity doesn't have to wait for pause to complete. // So, nothing else to-do except: Loading Loading @@ -2661,7 +2659,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.mNoAnimActivities.clear(); ActivityStack lastStack = mStackSupervisor.getTopDisplayLastFocusedStack(); if (next.attachedToProcess()) { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped + " visible=" + next.visible); Loading @@ -2673,10 +2670,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // Launcher is already visible in this case. If we don't add it to opening // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation. final boolean lastActivityTranslucent = lastStack != null && (lastStack.inMultiWindowMode() || (lastStack.mLastPausedActivity != null && !lastStack.mLastPausedActivity.fullscreen)); final boolean lastActivityTranslucent = lastFocusedStack != null && (lastFocusedStack.inMultiWindowMode() || (lastFocusedStack.mLastPausedActivity != null && !lastFocusedStack.mLastPausedActivity.fullscreen)); // The contained logic must be synchronized, since we are both changing the visibility // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will Loading @@ -2693,7 +2690,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = lastStack == null ? null :lastStack.mResumedActivity; lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; final ActivityState lastState = next.getState(); mService.updateCpuStats(); Loading Loading @@ -2798,8 +2795,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai Slog.i(TAG, "Restarting because process died: " + next); if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null && lastStack.isTopStackOnDisplay()) { } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null && lastFocusedStack.isTopStackOnDisplay()) { next.showStartingWindow(null /* prev */, false /* newTask */, false /* taskSwitch */); } Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +2 −65 Original line number Diff line number Diff line Loading @@ -338,11 +338,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** The current user */ int mCurrentUser; /** If this is the same as mFocusedStack then the activity on the top of the focused stack has * been resumed. If stacks are changing position this will hold the old stack until the new * stack becomes resumed after which it will be set to mFocusedStack. */ private ActivityStack mLastFocusedStack; /** List of activities that are waiting for a new activity to become visible before completing * whatever operation they are supposed to do. */ // TODO: Remove mActivitiesWaitingForVisibleActivity list and just remove activity from Loading Loading @@ -693,8 +688,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ActivityDisplay defaultDisplay = getDefaultDisplay(); mLastFocusedStack = defaultDisplay.getOrCreateStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); positionChildAt(defaultDisplay, ActivityDisplay.POSITION_TOP); } Loading Loading @@ -762,43 +756,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable; } ActivityStack getTopDisplayLastFocusedStack() { return mLastFocusedStack; } boolean isTopDisplayFocusedStack(ActivityStack stack) { return stack != null && stack == getTopDisplayFocusedStack(); } /** NOTE: Should only be called from {@link ActivityStack#moveToFront} */ void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) { if (!focusCandidate.isFocusable()) { // The focus candidate isn't focusable. Move focus to the top stack that is focusable. focusCandidate = getNextFocusableStackLocked(focusCandidate, false /* ignoreCurrent */); if (focusCandidate == null) { Slog.w(TAG, "setFocusStackUnchecked: No focusable stack found, focus home as default"); focusCandidate = getDefaultDisplay().getHomeStack(); } } final ActivityStack currentFocusedStack = getTopDisplayFocusedStack(); if (currentFocusedStack != focusCandidate) { mLastFocusedStack = currentFocusedStack; // TODO(b/111541062): Update event log to include focus movements on all displays EventLogTags.writeAmFocusedStack( mCurrentUser, focusCandidate == null ? -1 : focusCandidate.getStackId(), mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), reason); } final ActivityRecord r = topRunningActivityLocked(); if (mService.isBooting() || !mService.isBooted()) { if (r != null && r.idle) { checkFinishBootingLocked(); } } } void moveRecentsStackToFront(String reason) { final ActivityStack recentsStack = getDefaultDisplay().getStack( WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS); Loading Loading @@ -1092,28 +1053,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } boolean allResumedActivitiesComplete() { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.get(displayNdx); for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = display.getChildAt(stackNdx); if (isTopDisplayFocusedStack(stack)) { final ActivityRecord r = stack.getResumedActivity(); if (r != null && !r.isState(RESUMED)) { return false; } } } } // TODO: Not sure if this should check if all Paused are complete too. final ActivityStack focusedStack = getTopDisplayFocusedStack(); if (DEBUG_STACK) Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from=" + mLastFocusedStack + " to=" + focusedStack); mLastFocusedStack = focusedStack; return true; } private boolean allResumedActivitiesVisible() { boolean foundResumed = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { Loading Loading @@ -3674,7 +3613,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (isTopDisplayFocusedStack(stack)) { mService.updateUsageStats(r, true); } if (allResumedActivitiesComplete()) { if (stack.getDisplay().allResumedActivitiesComplete()) { ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); mWindowManager.executeAppTransition(); return true; Loading Loading @@ -3985,8 +3924,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D pw.print(prefix); pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack()); pw.print(prefix); pw.println("mLastFocusedStack=" + mLastFocusedStack); pw.print(prefix); pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { Loading services/core/java/com/android/server/am/EventLogTags.logtags +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ option java_package com.android.server.am 30043 am_set_resumed_activity (User|1|5),(Component Name|3),(Reason|3) # Stack focus 30044 am_focused_stack (User|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3) 30044 am_focused_stack (User|1|5),(Display Id|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3) # Running pre boot receiver 30045 am_pre_boot (User|1|5),(Package|3) Loading services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java +19 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static com.android.server.am.ActivityStackSupervisor.ON_TOP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.platform.test.annotations.Presubmit; Loading Loading @@ -52,6 +53,24 @@ public class ActivityDisplayTests extends ActivityTestsBase { setupActivityTaskManagerService(); } @Test public void testLastFocusedStackIsUpdatedWhenMovingStack() { // Create a stack at bottom. final ActivityDisplay display = mSupervisor.getDefaultDisplay(); final ActivityStack stack = display.createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, !ON_TOP); final ActivityStack prevFocusedStack = display.getFocusedStack(); stack.moveToFront("moveStackToFront"); // After moving the stack to front, the previous focused should be the last focused. assertTrue(stack.isFocusedStackOnDisplay()); assertEquals(prevFocusedStack, display.getLastFocusedStack()); stack.moveToBack("moveStackToBack", null /* task */); // After moving the stack to back, the stack should be the last focused. assertEquals(stack, display.getLastFocusedStack()); } /** * This test simulates the picture-in-picture menu activity launches an activity to fullscreen * stack. The fullscreen stack should be the top focused for resuming correctly. Loading Loading
services/core/java/com/android/server/am/ActivityDisplay.java +59 −4 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityStack.ActivityState.RESUMED; import static com.android.server.am.ActivityStackSupervisor.FindTaskResult; import static com.android.server.am.ActivityStackSupervisor.TAG_STATES; import static com.android.server.am.ActivityStackSupervisor.TAG_TASKS; Loading Loading @@ -120,6 +121,13 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> */ private ActivityStack mPreferredTopFocusableStack; /** * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused * stack has been resumed. If stacks are changing position this will hold the old stack until * the new stack becomes resumed after which it will be set to current focused stack. */ private ActivityStack mLastFocusedStack; // Cached reference to some special stacks we tend to get a lot so we don't need to loop // through the list to find them. private ActivityStack mHomeStack = null; Loading Loading @@ -182,20 +190,33 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> } void positionChildAtTop(ActivityStack stack, boolean includingParents) { positionChildAt(stack, mStacks.size(), includingParents); positionChildAtTop(stack, includingParents, null /* updateLastFocusedStackReason */); } void positionChildAtTop(ActivityStack stack, boolean includingParents, String updateLastFocusedStackReason) { positionChildAt(stack, mStacks.size(), includingParents, updateLastFocusedStackReason); } void positionChildAtBottom(ActivityStack stack) { positionChildAt(stack, 0, false /* includingParents */); positionChildAtBottom(stack, null /* updateLastFocusedStackReason */); } void positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason) { positionChildAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason); } private void positionChildAt(ActivityStack stack, int position) { positionChildAt(stack, position, false /* includingParents */); positionChildAt(stack, position, false /* includingParents */, null /* updateLastFocusedStackReason */); } private void positionChildAt(ActivityStack stack, int position, boolean includingParents) { private void positionChildAt(ActivityStack stack, int position, boolean includingParents, String updateLastFocusedStackReason) { // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust // the position internally, also update the logic here final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null ? getFocusedStack() : null; final boolean wasContained = mStacks.remove(stack); final int insertPosition = getTopInsertPosition(stack, position); mStacks.add(insertPosition, stack); Loading @@ -211,6 +232,17 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> mPreferredTopFocusableStack = null; } if (updateLastFocusedStackReason != null) { final ActivityStack currentFocusedStack = getFocusedStack(); if (currentFocusedStack != prevFocusedStack) { mLastFocusedStack = prevFocusedStack; EventLogTags.writeAmFocusedStack(mSupervisor.mCurrentUser, mDisplayId, currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(), mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), updateLastFocusedStackReason); } } // Since positionChildAt() is called during the creation process of pinned stacks, // ActivityStack#getWindowContainerController() can be null. In this special case, // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(), Loading Loading @@ -458,6 +490,26 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> return resumedActivity; } ActivityStack getLastFocusedStack() { return mLastFocusedStack; } boolean allResumedActivitiesComplete() { for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityRecord r = mStacks.get(stackNdx).getResumedActivity(); if (r != null && !r.isState(RESUMED)) { return false; } } final ActivityStack currentFocusedStack = getFocusedStack(); if (DEBUG_STACK) { Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from=" + mLastFocusedStack + " to=" + currentFocusedStack); } mLastFocusedStack = currentFocusedStack; return true; } /** * Pause all activities in either all of the stacks or just the back stacks. * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving(). Loading Loading @@ -1138,6 +1190,9 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack> if (mPreferredTopFocusableStack != null) { pw.println(myPrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack); } if (mLastFocusedStack != null) { pw.println(myPrefix + "mLastFocusedStack=" + mLastFocusedStack); } } public void dumpStacks(PrintWriter pw) { Loading
services/core/java/com/android/server/am/ActivityStack.java +16 −19 Original line number Diff line number Diff line Loading @@ -1105,12 +1105,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai display.moveHomeStackToFront(reason + " returnToHome"); } display.positionChildAtTop(this, true /* includingParents */); mStackSupervisor.setFocusStackUnchecked(reason, this); if (task != null) { final boolean movingTask = task != null; display.positionChildAtTop(this, !movingTask /* includingParents */, reason); if (movingTask) { // This also moves the entire hierarchy branch to top, including parents insertTaskAtTop(task, null); return; insertTaskAtTop(task, null /* starting */); } } Loading @@ -1131,13 +1130,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai setWindowingMode(WINDOWING_MODE_UNDEFINED); } getDisplay().positionChildAtBottom(this); mStackSupervisor.setFocusStackUnchecked(reason, getDisplay().getTopStack()); getDisplay().positionChildAtBottom(this, reason); if (task != null) { // TODO(b/111541062): We probably don't want to change display z-order to bottom just // because one of its stacks moved to bottom. insertTaskAtBottom(task); return; } } Loading Loading @@ -2431,10 +2428,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } next.delayedResume = false; final ActivityDisplay display = getDisplay(); // If the top activity is the resumed one, nothing to do. if (mResumedActivity == next && next.isState(RESUMED) && mStackSupervisor.allResumedActivitiesComplete()) { && display.allResumedActivitiesComplete()) { // Make sure we have executed any pending transitions, since there // should be nothing left to do at this point. executeAppTransition(options); Loading Loading @@ -2500,7 +2498,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai boolean lastResumedCanPip = false; ActivityRecord lastResumed = null; final ActivityStack lastFocusedStack = mStackSupervisor.getTopDisplayLastFocusedStack(); final ActivityStack lastFocusedStack = display.getLastFocusedStack(); if (lastFocusedStack != null && lastFocusedStack != this) { // So, why aren't we using prev here??? See the param comment on the method. prev doesn't // represent the last resumed activity. However, the last focus stack does if it isn't null. Loading Loading @@ -2545,7 +2543,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai } return true; } else if (mResumedActivity == next && next.isState(RESUMED) && mStackSupervisor.allResumedActivitiesComplete()) { && display.allResumedActivitiesComplete()) { // It is possible for the activity to be resumed when we paused back stacks above if the // next activity doesn't have to wait for pause to complete. // So, nothing else to-do except: Loading Loading @@ -2661,7 +2659,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai mStackSupervisor.mNoAnimActivities.clear(); ActivityStack lastStack = mStackSupervisor.getTopDisplayLastFocusedStack(); if (next.attachedToProcess()) { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next + " stopped=" + next.stopped + " visible=" + next.visible); Loading @@ -2673,10 +2670,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai // Launcher is already visible in this case. If we don't add it to opening // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation. final boolean lastActivityTranslucent = lastStack != null && (lastStack.inMultiWindowMode() || (lastStack.mLastPausedActivity != null && !lastStack.mLastPausedActivity.fullscreen)); final boolean lastActivityTranslucent = lastFocusedStack != null && (lastFocusedStack.inMultiWindowMode() || (lastFocusedStack.mLastPausedActivity != null && !lastFocusedStack.mLastPausedActivity.fullscreen)); // The contained logic must be synchronized, since we are both changing the visibility // and updating the {@link Configuration}. {@link ActivityRecord#setVisibility} will Loading @@ -2693,7 +2690,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai next.startLaunchTickingLocked(); ActivityRecord lastResumedActivity = lastStack == null ? null :lastStack.mResumedActivity; lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; final ActivityState lastState = next.getState(); mService.updateCpuStats(); Loading Loading @@ -2798,8 +2795,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai Slog.i(TAG, "Restarting because process died: " + next); if (!next.hasBeenLaunched) { next.hasBeenLaunched = true; } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null && lastStack.isTopStackOnDisplay()) { } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null && lastFocusedStack.isTopStackOnDisplay()) { next.showStartingWindow(null /* prev */, false /* newTask */, false /* taskSwitch */); } Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +2 −65 Original line number Diff line number Diff line Loading @@ -338,11 +338,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D /** The current user */ int mCurrentUser; /** If this is the same as mFocusedStack then the activity on the top of the focused stack has * been resumed. If stacks are changing position this will hold the old stack until the new * stack becomes resumed after which it will be set to mFocusedStack. */ private ActivityStack mLastFocusedStack; /** List of activities that are waiting for a new activity to become visible before completing * whatever operation they are supposed to do. */ // TODO: Remove mActivitiesWaitingForVisibleActivity list and just remove activity from Loading Loading @@ -693,8 +688,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D final ActivityDisplay defaultDisplay = getDefaultDisplay(); mLastFocusedStack = defaultDisplay.getOrCreateStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); defaultDisplay.getOrCreateStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP); positionChildAt(defaultDisplay, ActivityDisplay.POSITION_TOP); } Loading Loading @@ -762,43 +756,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return container.getWindowConfiguration().canReceiveKeys() || alwaysFocusable; } ActivityStack getTopDisplayLastFocusedStack() { return mLastFocusedStack; } boolean isTopDisplayFocusedStack(ActivityStack stack) { return stack != null && stack == getTopDisplayFocusedStack(); } /** NOTE: Should only be called from {@link ActivityStack#moveToFront} */ void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) { if (!focusCandidate.isFocusable()) { // The focus candidate isn't focusable. Move focus to the top stack that is focusable. focusCandidate = getNextFocusableStackLocked(focusCandidate, false /* ignoreCurrent */); if (focusCandidate == null) { Slog.w(TAG, "setFocusStackUnchecked: No focusable stack found, focus home as default"); focusCandidate = getDefaultDisplay().getHomeStack(); } } final ActivityStack currentFocusedStack = getTopDisplayFocusedStack(); if (currentFocusedStack != focusCandidate) { mLastFocusedStack = currentFocusedStack; // TODO(b/111541062): Update event log to include focus movements on all displays EventLogTags.writeAmFocusedStack( mCurrentUser, focusCandidate == null ? -1 : focusCandidate.getStackId(), mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(), reason); } final ActivityRecord r = topRunningActivityLocked(); if (mService.isBooting() || !mService.isBooted()) { if (r != null && r.idle) { checkFinishBootingLocked(); } } } void moveRecentsStackToFront(String reason) { final ActivityStack recentsStack = getDefaultDisplay().getStack( WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_RECENTS); Loading Loading @@ -1092,28 +1053,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D return true; } boolean allResumedActivitiesComplete() { for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ActivityDisplay display = mActivityDisplays.get(displayNdx); for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = display.getChildAt(stackNdx); if (isTopDisplayFocusedStack(stack)) { final ActivityRecord r = stack.getResumedActivity(); if (r != null && !r.isState(RESUMED)) { return false; } } } } // TODO: Not sure if this should check if all Paused are complete too. final ActivityStack focusedStack = getTopDisplayFocusedStack(); if (DEBUG_STACK) Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from=" + mLastFocusedStack + " to=" + focusedStack); mLastFocusedStack = focusedStack; return true; } private boolean allResumedActivitiesVisible() { boolean foundResumed = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { Loading Loading @@ -3674,7 +3613,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D if (isTopDisplayFocusedStack(stack)) { mService.updateUsageStats(r, true); } if (allResumedActivitiesComplete()) { if (stack.getDisplay().allResumedActivitiesComplete()) { ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); mWindowManager.executeAppTransition(); return true; Loading Loading @@ -3985,8 +3924,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D pw.print(prefix); pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack()); pw.print(prefix); pw.println("mLastFocusedStack=" + mLastFocusedStack); pw.print(prefix); pw.println("mCurTaskIdForUser=" + mCurTaskIdForUser); pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront); for (int i = mActivityDisplays.size() - 1; i >= 0; --i) { Loading
services/core/java/com/android/server/am/EventLogTags.logtags +1 −1 Original line number Diff line number Diff line Loading @@ -91,7 +91,7 @@ option java_package com.android.server.am 30043 am_set_resumed_activity (User|1|5),(Component Name|3),(Reason|3) # Stack focus 30044 am_focused_stack (User|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3) 30044 am_focused_stack (User|1|5),(Display Id|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3) # Running pre boot receiver 30045 am_pre_boot (User|1|5),(Package|3) Loading
services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java +19 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static com.android.server.am.ActivityStackSupervisor.ON_TOP; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import android.platform.test.annotations.Presubmit; Loading Loading @@ -52,6 +53,24 @@ public class ActivityDisplayTests extends ActivityTestsBase { setupActivityTaskManagerService(); } @Test public void testLastFocusedStackIsUpdatedWhenMovingStack() { // Create a stack at bottom. final ActivityDisplay display = mSupervisor.getDefaultDisplay(); final ActivityStack stack = display.createStack( WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, !ON_TOP); final ActivityStack prevFocusedStack = display.getFocusedStack(); stack.moveToFront("moveStackToFront"); // After moving the stack to front, the previous focused should be the last focused. assertTrue(stack.isFocusedStackOnDisplay()); assertEquals(prevFocusedStack, display.getLastFocusedStack()); stack.moveToBack("moveStackToBack", null /* task */); // After moving the stack to back, the stack should be the last focused. assertEquals(stack, display.getLastFocusedStack()); } /** * This test simulates the picture-in-picture menu activity launches an activity to fullscreen * stack. The fullscreen stack should be the top focused for resuming correctly. Loading