OSDN Git Service

Use the top stack on display instead of focused
authorAndrii Kulian <akulian@google.com>
Thu, 16 Feb 2017 23:45:58 +0000 (15:45 -0800)
committerAndrii Kulian <akulian@google.com>
Thu, 16 Feb 2017 23:51:17 +0000 (15:51 -0800)
There are places where there is an assumption that there is only
one display with activities in the system and that the focused stack
is usually the topmost stack on current display.
Here we explicitly use the topmost from the stacks on a display
instead of focused stack record in ActivityStackSupervisor.

Bug: 34263289
Bug: 35258038
Test: android.server.cts.ActivityManagerDisplayTests
Test: #testStackFocusSwitchOnDisplayRemoved
Test: #testStackFocusSwitchOnDisplayRemoved2
Change-Id: Ice1a555b0a4460d6bd63be2af7b51b145c85ab7f

services/core/java/com/android/server/am/ActivityStack.java
services/core/java/com/android/server/am/ActivityStackSupervisor.java

index 7c24604..6129bf9 100644 (file)
@@ -1559,12 +1559,13 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
             return STACK_INVISIBLE;
         }
 
-        final ActivityStack focusedStack = mStackSupervisor.getFocusedStack();
-        final int focusedStackId = focusedStack.mStackId;
+        // Check position and visibility of this stack relative to the front stack on its display.
+        final ActivityStack topStack = getTopStackOnDisplay();
+        final int topStackId = topStack.mStackId;
 
         if (StackId.isBackdropToTranslucentActivity(mStackId)
-                && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(focusedStackId)
-                && !focusedStack.topActivity().fullscreen) {
+                && hasVisibleBehindActivity() && StackId.isHomeOrRecentsStack(topStackId)
+                && !topStack.topActivity().fullscreen) {
             // The fullscreen or assistant stack should be visible if it has a visible behind
             // activity behind the home or recents stack that is translucent.
             return STACK_VISIBLE_ACTIVITY_BEHIND;
@@ -1574,39 +1575,39 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
             // Docked stack is always visible, except in the case where the top running activity
             // task in the focus stack doesn't support any form of resizing but we show it for the
             // home task even though it's not resizable.
-            final ActivityRecord r = focusedStack.topRunningActivityLocked();
+            final ActivityRecord r = topStack.topRunningActivityLocked();
             final TaskRecord task = r != null ? r.task : null;
             return task == null || task.supportsSplitScreen() || task.isHomeTask() ? STACK_VISIBLE
                     : STACK_INVISIBLE;
         }
 
-        // Find the first stack behind focused stack that actually got something visible.
-        int stackBehindFocusedIndex = mStacks.indexOf(focusedStack) - 1;
-        while (stackBehindFocusedIndex >= 0 &&
-                mStacks.get(stackBehindFocusedIndex).topRunningActivityLocked() == null) {
-            stackBehindFocusedIndex--;
+        // Find the first stack behind front stack that actually got something visible.
+        int stackBehindTopIndex = mStacks.indexOf(topStack) - 1;
+        while (stackBehindTopIndex >= 0 &&
+                mStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
+            stackBehindTopIndex--;
         }
-        if ((focusedStackId == DOCKED_STACK_ID || focusedStackId == PINNED_STACK_ID)
-                && stackIndex == stackBehindFocusedIndex) {
+        if ((topStackId == DOCKED_STACK_ID || topStackId == PINNED_STACK_ID)
+                && stackIndex == stackBehindTopIndex) {
             // Stacks directly behind the docked or pinned stack are always visible.
             return STACK_VISIBLE;
         }
 
-        final int stackBehindFocusedId = (stackBehindFocusedIndex >= 0)
-                ? mStacks.get(stackBehindFocusedIndex).mStackId : INVALID_STACK_ID;
+        final int stackBehindTopId = (stackBehindTopIndex >= 0)
+                ? mStacks.get(stackBehindTopIndex).mStackId : INVALID_STACK_ID;
 
-        if (StackId.isBackdropToTranslucentActivity(focusedStackId)
-                && focusedStack.isStackTranslucent(starting, stackBehindFocusedId)) {
+        if (StackId.isBackdropToTranslucentActivity(topStackId)
+                && topStack.isStackTranslucent(starting, stackBehindTopId)) {
             // Stacks behind the fullscreen or assistant stack with a translucent activity are
             // always visible so they can act as a backdrop to the translucent activity.
             // For example, dialog activities
-            if (stackIndex == stackBehindFocusedIndex) {
+            if (stackIndex == stackBehindTopIndex) {
                 return STACK_VISIBLE;
             }
-            if (stackBehindFocusedIndex >= 0) {
-                if ((stackBehindFocusedId == DOCKED_STACK_ID
-                        || stackBehindFocusedId == PINNED_STACK_ID)
-                        && stackIndex == (stackBehindFocusedIndex - 1)) {
+            if (stackBehindTopIndex >= 0) {
+                if ((stackBehindTopId == DOCKED_STACK_ID
+                        || stackBehindTopId == PINNED_STACK_ID)
+                        && stackIndex == (stackBehindTopIndex - 1)) {
                     // The stack behind the docked or pinned stack is also visible so we can have a
                     // complete backdrop to the translucent activity when the docked stack is up.
                     return STACK_VISIBLE;
@@ -4271,8 +4272,8 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
             AppTimeTracker timeTracker, String reason) {
         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
 
-        final ActivityRecord focusedTopActivity = mStackSupervisor.getFocusedStack() != null
-                ? mStackSupervisor.getFocusedStack().topActivity() : null;
+        final ActivityStack topStack = getTopStackOnDisplay();
+        final ActivityRecord topActivity = topStack != null ? topStack.topActivity() : null;
         final int numTasks = mTaskHistory.size();
         final int index = mTaskHistory.indexOf(tr);
         if (numTasks == 0 || index < 0)  {
@@ -4297,7 +4298,7 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
         insertTaskAtTop(tr, null);
 
         // Don't refocus if invisible to current user
-        ActivityRecord top = tr.getTopActivity();
+        final ActivityRecord top = tr.getTopActivity();
         if (top == null || !top.okToShowLocked()) {
             addRecentActivityLocked(top);
             ActivityOptions.abort(options);
@@ -4305,7 +4306,7 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
         }
 
         // Set focus to the top running activity of this stack.
-        ActivityRecord r = topRunningActivityLocked();
+        final ActivityRecord r = topRunningActivityLocked();
         mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, reason);
 
         if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
@@ -4320,8 +4321,8 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
         }
         // If a new task is moved to the front, then mark the existing top activity as supporting
         // picture-in-picture while paused
-        if (focusedTopActivity != null) {
-            focusedTopActivity.supportsPictureInPictureWhilePausing = true;
+        if (topActivity != null) {
+            topActivity.supportsPictureInPictureWhilePausing = true;
         }
 
         mStackSupervisor.resumeFocusedStackTopActivityLocked();
@@ -4447,6 +4448,15 @@ final class ActivityStack extends ConfigurationContainer implements StackWindowL
         return true;
     }
 
+    /**
+     * Get the topmost stack on the current display. It may be different from focused stack, because
+     * focus may be on another display.
+     */
+    private ActivityStack getTopStackOnDisplay() {
+        final ArrayList<ActivityStack> stacks = mActivityContainer.mActivityDisplay.mStacks;
+        return stacks.isEmpty() ? null : stacks.get(stacks.size() - 1);
+    }
+
     static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
         final Uri data = r.intent.getData();
         final String strData = data != null ? data.toSafeString() : null;
index 95734a4..463ea79 100644 (file)
@@ -181,6 +181,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
@@ -2774,7 +2775,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
             stack.prepareFreezingTaskBounds();
 
             // Make sure the task has the appropriate bounds/size for the stack it is in.
-            if (stackId == FULLSCREEN_WORKSPACE_STACK_ID && task.mBounds != null) {
+            if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
+                    && !Objects.equals(task.mBounds, stack.mBounds)) {
                 kept = task.resize(stack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
                         deferResume);
             } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
@@ -2897,6 +2899,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
         mService.mTaskChangeNotificationController.notifyActivityPinned();
     }
 
+    /** Move activity with its stack to front and make the stack focused. */
     boolean moveFocusableActivityStackToFrontLocked(ActivityRecord r, String reason) {
         if (r == null || !r.isFocusable()) {
             if (DEBUG_FOCUS) Slog.d(TAG_FOCUS,
@@ -4898,24 +4901,24 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
      * @return a list of activities which are the top ones in each visible stack. The first
      * entry will be the focused activity.
      */
-    public List<IBinder> getTopVisibleActivities() {
-        // TODO(multi-display): Get rid of DEFAULT_DISPLAY here. Used in
-        // VoiceInteractionManagerServiceImpl#showSessionLocked.
-        final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
-        if (display == null) {
-            return Collections.EMPTY_LIST;
-        }
-        ArrayList<IBinder> topActivityTokens = new ArrayList<>();
-        final ArrayList<ActivityStack> stacks = display.mStacks;
-        for (int i = stacks.size() - 1; i >= 0; i--) {
-            ActivityStack stack = stacks.get(i);
-            if (stack.getStackVisibilityLocked(null) == ActivityStack.STACK_VISIBLE) {
-                ActivityRecord top = stack.topActivity();
-                if (top != null) {
-                    if (stack == mFocusedStack) {
-                        topActivityTokens.add(0, top.appToken);
-                    } else {
-                        topActivityTokens.add(top.appToken);
+    List<IBinder> getTopVisibleActivities() {
+        final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
+        // Traverse all displays.
+        for (int i = mActivityDisplays.size(); i >= 0; i--) {
+            final ActivityDisplay display = mActivityDisplays.valueAt(i);
+            // Traverse all stacks on a display.
+            for (int j = display.mStacks.size() - 1; j >= 0; j--) {
+                final ActivityStack stack = display.mStacks.get(j);
+                // Get top activity from a visible stack and add it to the list.
+                if (stack.getStackVisibilityLocked(null /* starting */)
+                        == ActivityStack.STACK_VISIBLE) {
+                    final ActivityRecord top = stack.topActivity();
+                    if (top != null) {
+                        if (stack == mFocusedStack) {
+                            topActivityTokens.add(0, top.appToken);
+                        } else {
+                            topActivityTokens.add(top.appToken);
+                        }
                     }
                 }
             }