OSDN Git Service

Defer always on top state when task gets maximized
authorKazuki Takise <takise@google.com>
Wed, 27 Jun 2018 08:05:11 +0000 (17:05 +0900)
committerKazuki Takise <takise@google.com>
Tue, 17 Jul 2018 07:09:57 +0000 (16:09 +0900)
This CL enables always on top to be restored/deferred when
stacks switch between freeform and fullscreen.

Bug: 110494387
Test: ActivityStackTests
Test: DisplayContentTests
Test: go/wm-smoke
Change-Id: Iccb9824f845dea4925fac5d5dcb5eeaab2acdfcd

core/java/android/app/WindowConfiguration.java
services/core/java/com/android/server/am/ActivityDisplay.java
services/core/java/com/android/server/am/ActivityStack.java
services/tests/servicestests/src/com/android/server/am/ActivityStackTests.java
services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java

index aea767e..e6fb5dc 100644 (file)
@@ -575,7 +575,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
      * @hide
      */
     public boolean isAlwaysOnTop() {
-        return mWindowingMode == WINDOWING_MODE_PINNED || mAlwaysOnTop == ALWAYS_ON_TOP_ON;
+        return mWindowingMode == WINDOWING_MODE_PINNED
+                || (mWindowingMode == WINDOWING_MODE_FREEFORM && mAlwaysOnTop == ALWAYS_ON_TOP_ON);
     }
 
     /**
index 562dfd6..5f9f4eb 100644 (file)
@@ -167,8 +167,14 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
         mStacks.remove(stack);
         final int insertPosition = getTopInsertPosition(stack, position);
         mStacks.add(insertPosition, stack);
-        mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
-                insertPosition);
+        // 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(),
+        // we don't have to call WindowContainerController#positionChildAt() here.
+        if (stack.getWindowContainerController() != null) {
+            mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
+                    insertPosition);
+        }
         onStackOrderChanged();
     }
 
index b0f1c45..bebaede 100644 (file)
@@ -503,11 +503,21 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
     @Override
     public void onConfigurationChanged(Configuration newParentConfig) {
         final int prevWindowingMode = getWindowingMode();
+        final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
         super.onConfigurationChanged(newParentConfig);
         final ActivityDisplay display = getDisplay();
-        if (display != null && prevWindowingMode != getWindowingMode()) {
+        if (display == null) {
+          return;
+        }
+        if (prevWindowingMode != getWindowingMode()) {
             display.onStackWindowingModeChanged(this);
         }
+        if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
+            // Since always on top is only on when the stack is freeform or pinned, the state
+            // can be toggled when the windowing mode changes. We must make sure the stack is
+            // placed properly when always on top state changes.
+            display.positionChildAtTop(this);
+        }
     }
 
     @Override
index 4094716..6290751 100644 (file)
@@ -507,6 +507,15 @@ public class ActivityStackTests extends ActivityTestsBase {
         // Ensure, when always on top is turned off for a stack, the stack is put just below all
         // other always on top stacks.
         assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == alwaysOnTopStack);
+        alwaysOnTopStack2.setAlwaysOnTop(true);
+
+        // Ensure always on top state changes properly when windowing mode changes.
+        alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        assertFalse(alwaysOnTopStack2.isAlwaysOnTop());
+        assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == alwaysOnTopStack);
+        alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertTrue(alwaysOnTopStack2.isAlwaysOnTop());
+        assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == pinnedStack);
     }
 
     @Test
index ec068db..cd8e650 100644 (file)
@@ -17,6 +17,8 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -384,7 +386,8 @@ public class DisplayContentTests extends WindowTestsBase {
      */
     @Test
     public void testAlwaysOnTopStackLocation() {
-        final TaskStack alwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
+        final TaskStack alwaysOnTopStack = createStackControllerOnStackOnDisplay(
+                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
         final Task task = createTaskInStack(alwaysOnTopStack, 0 /* userId */);
         alwaysOnTopStack.setAlwaysOnTop(true);
         mDisplayContent.positionStackAt(POSITION_TOP, alwaysOnTopStack);
@@ -398,7 +401,8 @@ public class DisplayContentTests extends WindowTestsBase {
         assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
         assertEquals(pinnedStack, mDisplayContent.getTopStack());
 
-        final TaskStack anotherAlwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
+        final TaskStack anotherAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
+                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
         anotherAlwaysOnTopStack.setAlwaysOnTop(true);
         mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack);
         assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
@@ -407,7 +411,8 @@ public class DisplayContentTests extends WindowTestsBase {
         // existing alwaysOnTop stack.
         assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
 
-        final TaskStack nonAlwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
+        final TaskStack nonAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
+                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
         assertEquals(mDisplayContent, nonAlwaysOnTopStack.getDisplayContent());
         topPosition = mDisplayContent.getStacks().size() - 1;
         // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
@@ -417,10 +422,18 @@ public class DisplayContentTests extends WindowTestsBase {
         anotherAlwaysOnTopStack.setAlwaysOnTop(false);
         mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack);
         assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
-        topPosition = mDisplayContent.getStacks().size() - 1;
         // Ensure, when always on top is turned off for a stack, the stack is put just below all
         // other always on top stacks.
         assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
+        anotherAlwaysOnTopStack.setAlwaysOnTop(true);
+
+        // Ensure always on top state changes properly when windowing mode changes.
+        anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+        assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
+        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
+        anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
+        assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
+        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
     }
 
     /**