OSDN Git Service

WindowLayout: Layout IN_SCREEN floating windows in screen
authorAdrian Roos <roosa@google.com>
Thu, 29 Mar 2018 17:41:30 +0000 (19:41 +0200)
committerAdrian Roos <roosa@google.com>
Mon, 9 Apr 2018 23:02:19 +0000 (23:02 +0000)
Uses screen coordinates when placing floating LAYOUT_IN_SCREEN
windows, even when there is a cutout. Making sure that the window
does not overlap the cutout area is instead made sure by the
clip/shift-to-displayFrame logic in WindowState.

Change-Id: Ic485b8f191db737bb7a10b1694a489111afd5f2c
Fixes: 76199703
Test: Run CalcyIV, make sure that the expanded window is properly attached to the non-expanded window.

services/core/java/com/android/server/policy/PhoneWindowManager.java
services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerLayoutTest.java
services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java

index 2e6e348..1cfcbac 100644 (file)
@@ -87,6 +87,7 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
 import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -5397,6 +5398,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         final boolean attachedInParent = attached != null && !layoutInScreen;
         final boolean requestedHideNavigation =
                 (requestedSysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
+
+        // TYPE_BASE_APPLICATION windows are never considered floating here because they don't get
+        // cropped / shifted to the displayFrame in WindowState.
+        final boolean floatingInScreenWindow = !attrs.isFullscreen() && layoutInScreen
+                && type != TYPE_BASE_APPLICATION;
+
         // Ensure that windows with a DEFAULT or NEVER display cutout mode are laid out in
         // the cutout safe zone.
         if (cutoutMode != LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS) {
@@ -5431,7 +5438,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
             }
             // Windows that are attached to a parent and laid out in said parent already avoid
             // the cutout according to that parent and don't need to be further constrained.
-            if (!attachedInParent) {
+            // Floating IN_SCREEN windows get what they ask for and lay out in the full screen.
+            // They will later be cropped or shifted using the displayFrame in WindowState,
+            // which prevents overlap with the DisplayCutout.
+            if (!attachedInParent && !floatingInScreenWindow) {
                 mTmpRect.set(pf);
                 pf.intersectUnchecked(displayCutoutSafeExceptMaybeBars);
                 parentFrameWasClippedByDisplayCutout |= !mTmpRect.equals(pf);
index b6be3a4..97a716f 100644 (file)
@@ -22,6 +22,7 @@ import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -29,6 +30,7 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
@@ -260,6 +262,23 @@ public class PhoneWindowManagerLayoutTest extends PhoneWindowManagerTestBase {
     }
 
     @Test
+    public void layoutWindowLw_withDisplayCutout_floatingInScreen() {
+        addDisplayCutout();
+
+        mAppWindow.attrs.flags = FLAG_LAYOUT_IN_SCREEN;
+        mAppWindow.attrs.type = TYPE_APPLICATION_OVERLAY;
+        mAppWindow.attrs.width = DISPLAY_WIDTH;
+        mAppWindow.attrs.height = DISPLAY_HEIGHT;
+        mPolicy.addWindow(mAppWindow);
+
+        mPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+        mPolicy.layoutWindowLw(mAppWindow, null, mFrames);
+
+        assertInsetByTopBottom(mAppWindow.parentFrame, 0, NAV_BAR_HEIGHT);
+        assertInsetByTopBottom(mAppWindow.displayFrame, STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+    }
+
+    @Test
     public void layoutWindowLw_withDisplayCutout_fullscreenInCutout_landscape() {
         addDisplayCutout();
         setRotation(ROTATION_90);
index 195dd39..2c47a94 100644 (file)
@@ -229,7 +229,8 @@ public class PhoneWindowManagerTestBase {
         void addWindow(WindowState state) {
             if (state instanceof FakeWindowState) {
                 ((FakeWindowState) state).surfaceLayer =
-                        getWindowLayerFromTypeLw(state.getAttrs().type);
+                        getWindowLayerFromTypeLw(state.getAttrs().type,
+                                true /* canAddInternalSystemWindow */);
             }
             adjustWindowParamsLw(state, state.getAttrs(), true /* hasStatusBarPermission */);
             assertEquals(WindowManagerGlobal.ADD_OKAY, prepareAddWindowLw(state, state.getAttrs()));