summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Riddle Hsu <riddlehsu@google.com> 2018-10-03 12:28:29 +0800
committer Riddle Hsu <riddlehsu@google.com> 2018-10-05 13:24:21 +0800
commitbbb63c26b1a9f3dec69f12dc2f588f02adf4423a (patch)
treebeecf6ca5cbfb999b2af51062d2e9e49b68a3f17
parentb49951053543ad337194177fb44c465ce6cfe273 (diff)
Move last focused stack from global to per-display
- Update last focused stack when moving stack to front or back by comparing updated focused stack with ideal previous one. - Print event log am_focused_stack by display. - Remove setFocusStackUnchecked because it is no longer used to set current focus. - Change allResumedActivitiesComplete to per-display for checking whether to execute transition (originally it is global but still only check for the top focused). - Remove checking of finish booting (added in commit f3ea23ad9b) when moving order of stack. That intended to fix a corner case when home is idle but it is not the topmost. Currently the case won't happen because now: 1. The restored empty tasks from recent will be put on bottom. 2. The checking in activityIdleInternalLocked uses isTopDisplayFocusedStack that will not be affected by empty (non-focusable or invisible) stacks on top. Bug: 117198947 Test: atest ActivityDisplayTests Change-Id: I5dcce337b4b6e33807b7a6729720cebd062356e2
-rw-r--r--services/core/java/com/android/server/am/ActivityDisplay.java63
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java35
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java67
-rw-r--r--services/core/java/com/android/server/am/EventLogTags.logtags2
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java19
5 files changed, 97 insertions, 89 deletions
diff --git a/services/core/java/com/android/server/am/ActivityDisplay.java b/services/core/java/com/android/server/am/ActivityDisplay.java
index fcb717ed51f0..a648b09abda5 100644
--- a/services/core/java/com/android/server/am/ActivityDisplay.java
+++ b/services/core/java/com/android/server/am/ActivityDisplay.java
@@ -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;
@@ -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;
@@ -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);
@@ -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(),
@@ -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().
@@ -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) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index ea807adc7d4f..ebfaf0fe9a7e 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -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 */);
}
}
@@ -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;
}
}
@@ -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);
@@ -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.
@@ -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:
@@ -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);
@@ -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
@@ -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();
@@ -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 */);
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index a968ae4e0201..b6863aa89309 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -337,11 +337,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
@@ -692,8 +687,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);
}
@@ -761,43 +755,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);
@@ -1091,28 +1052,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) {
@@ -3673,7 +3612,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;
@@ -3984,8 +3923,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) {
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 0ef2a0a90e13..09064f2fc441 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -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)
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
index 44981b3a90cf..ea90ffd0792f 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityDisplayTests.java
@@ -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;
@@ -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.