From 55d7c4079d5b03253f14dfbc70df2900ecf11864 Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Wed, 26 Feb 2020 22:49:29 +0800 Subject: [PATCH] Notify fixed rotation transformed insets state - Use the corresponding insets state in notifyInsetsChanged and notifyInsetsControlChanged. - Move duplicated logic from addWindow and getWindowInsets to getLayoutHint and make it fixed-rotation-transform aware. - Get navigation bar position by display frames for calculating insets frame, so it isn't always associated to real display. Fix: 146415226 Test: atest DisplayPolicyLayoutTests Change-Id: I581d8c234063ad399cb453f53fccc176089a020b --- .../com/android/server/wm/DisplayPolicy.java | 36 +++++++++------- .../server/wm/InsetsSourceProvider.java | 5 ++- .../server/wm/WindowManagerService.java | 42 ++----------------- .../com/android/server/wm/WindowState.java | 7 ++-- .../server/wm/DisplayPolicyLayoutTests.java | 37 +++++++++------- .../server/wm/SystemServiceTestsBase.java | 22 ++++++++++ 6 files changed, 76 insertions(+), 73 deletions(-) diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index f02a9dd611074..2c4502062667c 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -1032,7 +1032,9 @@ public class DisplayPolicy { // In Gesture Nav, navigation bar frame is larger than frame to // calculate inset. - if (mNavigationBarPosition == NAV_BAR_BOTTOM) { + if (navigationBarPosition(displayFrames.mDisplayWidth, + displayFrames.mDisplayHeight, + displayFrames.mRotation) == NAV_BAR_BOTTOM) { sTmpRect.set(displayFrames.mUnrestricted); sTmpRect.intersectUnchecked(displayFrames.mDisplayCutoutSafe); inOutFrame.top = sTmpRect.bottom @@ -1266,10 +1268,7 @@ public class DisplayPolicy { * most recent layout, so they are not guaranteed to be correct. * * @param attrs The LayoutParams of the window. - * @param taskBounds The bounds of the task this window is on or {@code null} if no task is - * associated with the window. - * @param displayFrames display frames. - * @param floatingStack Whether the window's stack is floating. + * @param windowToken The token of the window. * @param outFrame The frame of the window. * @param outContentInsets The areas covered by system windows, expressed as positive insets. * @param outStableInsets The areas covered by stable system windows irrespective of their @@ -1278,8 +1277,7 @@ public class DisplayPolicy { * @return Whether to always consume the system bars. * See {@link #areSystemBarsForcedShownLw(WindowState)}. */ - public boolean getLayoutHintLw(LayoutParams attrs, Rect taskBounds, - DisplayFrames displayFrames, boolean floatingStack, Rect outFrame, + boolean getLayoutHint(LayoutParams attrs, WindowToken windowToken, Rect outFrame, Rect outContentInsets, Rect outStableInsets, DisplayCutout.ParcelableWrapper outDisplayCutout) { final int fl = PolicyControl.getWindowFlags(null, attrs); @@ -1292,6 +1290,18 @@ public class DisplayPolicy { && (fl & FLAG_LAYOUT_INSET_DECOR) != 0; final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0; + final boolean isFixedRotationTransforming = + windowToken != null && windowToken.isFixedRotationTransforming(); + final ActivityRecord activity = windowToken != null ? windowToken.asActivityRecord() : null; + final Task task = activity != null ? activity.getTask() : null; + final Rect taskBounds = isFixedRotationTransforming + // Use token (activity) bounds if it is rotated because its task is not rotated. + ? windowToken.getBounds() + : (task != null ? task.getBounds() : null); + final DisplayFrames displayFrames = isFixedRotationTransforming + ? windowToken.getFixedRotationTransformDisplayFrames() + : mDisplayContent.mDisplayFrames; + if (layoutInScreenAndInsetDecor && !screenDecor) { if ((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0 || (attrs.getFitInsetsTypes() & Type.navigationBars()) == 0) { @@ -1300,15 +1310,10 @@ public class DisplayPolicy { outFrame.set(displayFrames.mRestricted); } - final Rect sf; - if (floatingStack) { - sf = null; - } else { - sf = displayFrames.mStable; - } - + final boolean isFloatingTask = task != null && task.isFloating(); + final Rect sf = isFloatingTask ? null : displayFrames.mStable; final Rect cf; - if (floatingStack) { + if (isFloatingTask) { cf = null; } else if ((sysUiVis & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) { if ((fl & FLAG_FULLSCREEN) != 0) { @@ -1457,6 +1462,7 @@ public class DisplayPolicy { */ void simulateLayoutDisplay(DisplayFrames displayFrames, InsetsState insetsState, int uiMode) { displayFrames.onBeginLayout(); + insetsState.setDisplayFrame(displayFrames.mUnrestricted); final WindowFrames simulatedWindowFrames = new WindowFrames(); if (mNavigationBar != null) { simulateLayoutDecorWindow( diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java index 0d3f6b98f4836..58aefdc0e5477 100644 --- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java +++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java @@ -190,7 +190,10 @@ class InsetsSourceProvider { /** @return A new source computed by the specified window frame in the given display frames. */ InsetsSource createSimulatedSource(DisplayFrames displayFrames, WindowFrames windowFrames) { - final InsetsSource source = new InsetsSource(mSource); + // Don't copy visible frame because it might not be calculated in the provided display + // frames and it is not significant for this usage. + final InsetsSource source = new InsetsSource(mSource.getType()); + source.setVisible(mSource.isVisible()); mTmpRect.set(windowFrames.mFrame); if (mFrameProvider != null) { mFrameProvider.accept(displayFrames, mWin, mTmpRect); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index e0f8f0e9aee92..eb11a02b14976 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1656,23 +1656,8 @@ public class WindowManagerService extends IWindowManager.Stub prepareNoneTransitionForRelaunching(activity); } - final DisplayFrames displayFrames = displayContent.mDisplayFrames; - // TODO: Not sure if onDisplayInfoUpdated() call is needed. - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - displayFrames.onDisplayInfoUpdated(displayInfo, - displayContent.calculateDisplayCutoutForRotation(displayInfo.rotation)); - final Rect taskBounds; - final boolean floatingStack; - if (activity != null && activity.getTask() != null) { - taskBounds = mTmpRect; - tokenActivity.getTask().getBounds(mTmpRect); - floatingStack = activity.getTask().isFloating(); - } else { - taskBounds = null; - floatingStack = false; - } - if (displayPolicy.getLayoutHintLw(win.mAttrs, taskBounds, displayFrames, floatingStack, - outFrame, outContentInsets, outStableInsets, outDisplayCutout)) { + if (displayPolicy.getLayoutHint(win.mAttrs, token, outFrame, outContentInsets, + outStableInsets, outDisplayCutout)) { res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS; } outInsetsState.set(win.getInsetsState(), @@ -8084,27 +8069,8 @@ public class WindowManagerService extends IWindowManager.Stub + "could not be found!"); } final WindowToken windowToken = dc.getWindowToken(attrs.token); - final ActivityRecord activity; - if (windowToken != null && windowToken.asActivityRecord() != null) { - activity = windowToken.asActivityRecord(); - } else { - activity = null; - } - final Rect taskBounds; - final boolean floatingStack; - if (activity != null && activity.getTask() != null) { - final Task task = activity.getTask(); - taskBounds = new Rect(); - task.getBounds(taskBounds); - floatingStack = task.isFloating(); - } else { - taskBounds = null; - floatingStack = false; - } - final DisplayFrames displayFrames = dc.mDisplayFrames; - final DisplayPolicy policy = dc.getDisplayPolicy(); - policy.getLayoutHintLw(attrs, taskBounds, displayFrames, floatingStack, - new Rect(), outContentInsets, outStableInsets, displayCutout); + dc.getDisplayPolicy().getLayoutHint(attrs, windowToken, mTmpRect /* outFrame */, + outContentInsets, outStableInsets, displayCutout); } } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 37597fbc7c457..9c91e0bf39fdb 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1449,6 +1449,7 @@ class WindowState extends WindowContainer implements WindowManagerP } } + /** @return The display frames in use by this window. */ DisplayFrames getDisplayFrames(DisplayFrames originalFrames) { final DisplayFrames diplayFrames = mToken.getFixedRotationTransformDisplayFrames(); if (diplayFrames != null) { @@ -3507,8 +3508,7 @@ class WindowState extends WindowContainer implements WindowManagerP */ void notifyInsetsChanged() { try { - mClient.insetsChanged( - getDisplayContent().getInsetsPolicy().getInsetsForDispatch(this)); + mClient.insetsChanged(getInsetsState()); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver inset state change w=" + this, e); } @@ -3518,9 +3518,8 @@ class WindowState extends WindowContainer implements WindowManagerP public void notifyInsetsControlChanged() { final InsetsStateController stateController = getDisplayContent().getInsetsStateController(); - final InsetsPolicy policy = getDisplayContent().getInsetsPolicy(); try { - mClient.insetsControlChanged(policy.getInsetsForDispatch(this), + mClient.insetsControlChanged(getInsetsState(), stateController.getControlsForDispatch(this)); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver inset state change", e); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java index 2b0ad890aae1a..203fa61b75464 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java @@ -50,6 +50,7 @@ import static org.junit.Assume.assumeTrue; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; +import android.app.WindowConfiguration; import android.graphics.Insets; import android.graphics.PixelFormat; import android.graphics.Rect; @@ -855,9 +856,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { final DisplayCutout.ParcelableWrapper outDisplayCutout = new DisplayCutout.ParcelableWrapper(); - mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, null, mFrames, - false /* floatingStack */, outFrame, outContentInsets, outStableInsets, - outDisplayCutout); + mDisplayPolicy.getLayoutHint(mWindow.mAttrs, null /* windowToken */, outFrame, + outContentInsets, outStableInsets, outDisplayCutout); assertThat(outFrame, is(mFrames.mUnrestricted)); assertThat(outContentInsets, is(new Rect(0, STATUS_BAR_HEIGHT, 0, NAV_BAR_HEIGHT))); @@ -874,6 +874,9 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */); final Rect taskBounds = new Rect(100, 100, 200, 200); + final Task task = mWindow.getTask(); + // Force the bounds because the task may resolve different bounds from Task#setBounds. + task.getWindowConfiguration().setBounds(taskBounds); final Rect outFrame = new Rect(); final Rect outContentInsets = new Rect(); @@ -881,9 +884,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { final DisplayCutout.ParcelableWrapper outDisplayCutout = new DisplayCutout.ParcelableWrapper(); - mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, - false /* floatingStack */, outFrame, outContentInsets, outStableInsets, - outDisplayCutout); + mDisplayPolicy.getLayoutHint(mWindow.mAttrs, mWindow.mToken, outFrame, + outContentInsets, outStableInsets, outDisplayCutout); assertThat(outFrame, is(taskBounds)); assertThat(outContentInsets, is(new Rect())); @@ -904,15 +906,20 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { final Rect taskBounds = new Rect(100, mFrames.mContent.bottom + 1, 200, mFrames.mContent.bottom + 10); + final Task task = mWindow.getTask(); + // Make the task floating. + task.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); + // Force the bounds because the task may resolve different bounds from Task#setBounds. + task.getWindowConfiguration().setBounds(taskBounds); + final Rect outFrame = new Rect(); final Rect outContentInsets = new Rect(); final Rect outStableInsets = new Rect(); final DisplayCutout.ParcelableWrapper outDisplayCutout = new DisplayCutout.ParcelableWrapper(); - mDisplayPolicy.getLayoutHintLw(mWindow.mAttrs, taskBounds, mFrames, - true /* floatingStack */, outFrame, outContentInsets, outStableInsets, - outDisplayCutout); + mDisplayPolicy.getLayoutHint(mWindow.mAttrs, mWindow.mToken, outFrame, outContentInsets, + outStableInsets, outDisplayCutout); assertThat(outFrame, is(taskBounds)); assertThat(outContentInsets, is(new Rect())); @@ -939,6 +946,8 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { final InsetsState simulatedInsetsState = new InsetsState(); final DisplayFrames simulatedDisplayFrames = createDisplayFrames(); mDisplayPolicy.beginLayoutLw(mFrames, uiMode); + // Force the display bounds because it is not synced with display frames in policy test. + mDisplayContent.getWindowConfiguration().setBounds(mFrames.mUnrestricted); mDisplayContent.getInsetsStateController().onPostLayout(); mDisplayPolicy.simulateLayoutDisplay(simulatedDisplayFrames, simulatedInsetsState, uiMode); @@ -947,20 +956,18 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase { final StringWriter simulatedFramesDump = new StringWriter(); simulatedDisplayFrames.dump(prefix, new PrintWriter(simulatedFramesDump)); - assertEquals(realFramesDump.toString(), simulatedFramesDump.toString()); + assertEquals(new ToStringComparatorWrapper<>(realFramesDump), + new ToStringComparatorWrapper<>(simulatedFramesDump)); - final StringWriter realInsetsDump = new StringWriter(); final InsetsState realInsetsState = new InsetsState( mDisplayContent.getInsetsStateController().getRawInsetsState()); // Exclude comparing IME insets because currently the simulated layout only focuses on the // insets from status bar and navigation bar. realInsetsState.removeSource(InsetsState.ITYPE_IME); realInsetsState.removeSource(InsetsState.ITYPE_CAPTION_BAR); - realInsetsState.dump(prefix, new PrintWriter(realInsetsDump)); - final StringWriter simulatedInsetsDump = new StringWriter(); - simulatedInsetsState.dump(prefix, new PrintWriter(simulatedInsetsDump)); - assertEquals(realInsetsDump.toString(), simulatedInsetsDump.toString()); + assertEquals(new ToStringComparatorWrapper<>(realInsetsState), + new ToStringComparatorWrapper<>(simulatedInsetsState)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java index 7e31895aa9917..f6ed31455f18d 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServiceTestsBase.java @@ -60,4 +60,26 @@ class SystemServiceTestsBase { T awaitInWmLock(Callable callable) { return mLockRule.waitForLocked(callable); } + + /** + * Utility class to compare the output of T#toString. It is convenient to have readable output + * of assertion if the string content can represent the expected states. + */ + static class ToStringComparatorWrapper { + final T mObject; + + ToStringComparatorWrapper(T object) { + mObject = object; + } + + @Override + public boolean equals(Object obj) { + return mObject.toString().equals(obj.toString()); + } + + @Override + public String toString() { + return mObject.toString(); + } + } }