diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java index 53dd391a01af0..75a1ddeccb221 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java @@ -19,8 +19,8 @@ package com.android.wm.shell.hidedisplaycutout; import static android.view.Display.DEFAULT_DISPLAY; import android.content.Context; +import android.content.res.Configuration; import android.graphics.Insets; -import android.graphics.Point; import android.graphics.Rect; import android.util.ArrayMap; import android.util.Log; @@ -40,13 +40,12 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.internal.R; -import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import java.io.PrintWriter; import java.util.List; -import java.util.concurrent.Executor; /** * Manages the display areas of hide display cutout feature. @@ -76,19 +75,29 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { @VisibleForTesting int mRotation; - /** - * Handles rotation based on OnDisplayChangingListener callback. - */ - private final DisplayChangeController.OnDisplayChangingListener mRotationController = - (display, fromRotation, toRotation, wct) -> { - mRotation = toRotation; - updateBoundsAndOffsets(true /* enable */); - final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - applyAllBoundsAndOffsets(wct, t); - // Only apply t here since the server will do the wct.apply when the method - // finishes. - t.apply(); - }; + private final DisplayController.OnDisplaysChangedListener mListener = + new DisplayController.OnDisplaysChangedListener() { + @Override + public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) { + if (displayId != DEFAULT_DISPLAY) { + return; + } + DisplayLayout displayLayout = + mDisplayController.getDisplayLayout(DEFAULT_DISPLAY); + if (displayLayout == null) { + return; + } + final boolean rotationChanged = mRotation != displayLayout.rotation(); + mRotation = displayLayout.rotation(); + if (rotationChanged || isDisplayBoundsChanged()) { + updateBoundsAndOffsets(true /* enabled */); + final WindowContainerTransaction wct = new WindowContainerTransaction(); + final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + applyAllBoundsAndOffsets(wct, t); + applyTransaction(wct, t); + } + } + }; HideDisplayCutoutOrganizer(Context context, DisplayController displayController, ShellExecutor mainExecutor) { @@ -154,10 +163,10 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { * Enables hide display cutout. */ void enableHideDisplayCutout() { - mDisplayController.addDisplayChangingController(mRotationController); - final Display display = mDisplayController.getDisplay(DEFAULT_DISPLAY); - if (display != null) { - mRotation = display.getRotation(); + mDisplayController.addDisplayWindowListener(mListener); + final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY); + if (displayLayout != null) { + mRotation = displayLayout.rotation(); } final List displayAreaInfos = registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT); @@ -174,7 +183,7 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { */ void disableHideDisplayCutout() { updateBoundsAndOffsets(false /* enabled */); - mDisplayController.removeDisplayChangingController(mRotationController); + mDisplayController.removeDisplayWindowListener(mListener); unregisterOrganizer(); } @@ -193,23 +202,35 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { @VisibleForTesting Rect getDisplayBoundsOfNaturalOrientation() { - Point realSize = new Point(0, 0); - final Display display = mDisplayController.getDisplay(DEFAULT_DISPLAY); - if (display != null) { - display.getRealSize(realSize); + final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY); + if (displayLayout == null) { + return new Rect(); } final boolean isDisplaySizeFlipped = isDisplaySizeFlipped(); return new Rect( 0, 0, - isDisplaySizeFlipped ? realSize.y : realSize.x, - isDisplaySizeFlipped ? realSize.x : realSize.y); + isDisplaySizeFlipped ? displayLayout.height() : displayLayout.width(), + isDisplaySizeFlipped ? displayLayout.width() : displayLayout.height()); } private boolean isDisplaySizeFlipped() { return mRotation == Surface.ROTATION_90 || mRotation == Surface.ROTATION_270; } + private boolean isDisplayBoundsChanged() { + final DisplayLayout displayLayout = mDisplayController.getDisplayLayout(DEFAULT_DISPLAY); + if (displayLayout == null) { + return false; + } + final boolean isDisplaySizeFlipped = isDisplaySizeFlipped(); + final int width = isDisplaySizeFlipped ? displayLayout.height() : displayLayout.width(); + final int height = isDisplaySizeFlipped ? displayLayout.width() : displayLayout.height(); + return mDefaultDisplayBounds.isEmpty() + || mDefaultDisplayBounds.width() != width + || mDefaultDisplayBounds.height() != height; + } + /** * Updates bounds and offsets according to current state. * @@ -237,7 +258,6 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { mCurrentDisplayBounds.right); } mCurrentDisplayBounds.inset(mCurrentCutoutInsets); - // Replace the top bound with the max(status bar height, cutout height) if there is // cutout on the top side. mStatusBarHeight = getStatusBarHeight(); @@ -256,7 +276,7 @@ class HideDisplayCutoutOrganizer extends DisplayAreaOrganizer { } private void initDefaultValuesIfNeeded() { - if (!mDefaultDisplayBounds.isEmpty()) { + if (!isDisplayBoundsChanged()) { return; } mDefaultDisplayBounds.set(getDisplayBoundsOfNaturalOrientation()); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java index 9637570454530..3c124bafc18a7 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java @@ -50,6 +50,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import org.junit.Before; @@ -82,6 +83,8 @@ public class HideDisplayCutoutOrganizerTest { @Mock private Display mDisplay; @Mock + private DisplayLayout mDisplayLayout; + @Mock private IWindowContainerToken mMockRealToken; private WindowContainerToken mToken; @@ -95,6 +98,7 @@ public class HideDisplayCutoutOrganizerTest { MockitoAnnotations.initMocks(this); when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay); + when(mMockDisplayController.getDisplayLayout(anyInt())).thenReturn(mDisplayLayout); HideDisplayCutoutOrganizer organizer = new HideDisplayCutoutOrganizer( mContext, mMockDisplayController, mMockMainExecutor); @@ -152,7 +156,7 @@ public class HideDisplayCutoutOrganizerTest { .getDisplayCutoutInsetsOfNaturalOrientation(); mContext.getOrCreateTestableResources().addOverride( R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait); - doReturn(Surface.ROTATION_0).when(mDisplay).getRotation(); + doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation(); mOrganizer.enableHideDisplayCutout(); verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT); @@ -171,7 +175,7 @@ public class HideDisplayCutoutOrganizerTest { .getDisplayCutoutInsetsOfNaturalOrientation(); mContext.getOrCreateTestableResources().addOverride( R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape); - doReturn(Surface.ROTATION_90).when(mDisplay).getRotation(); + doReturn(Surface.ROTATION_90).when(mDisplayLayout).rotation(); mOrganizer.enableHideDisplayCutout(); verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT); @@ -190,7 +194,7 @@ public class HideDisplayCutoutOrganizerTest { .getDisplayCutoutInsetsOfNaturalOrientation(); mContext.getOrCreateTestableResources().addOverride( R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape); - doReturn(Surface.ROTATION_270).when(mDisplay).getRotation(); + doReturn(Surface.ROTATION_270).when(mDisplayLayout).rotation(); mOrganizer.enableHideDisplayCutout(); verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT); @@ -219,4 +223,22 @@ public class HideDisplayCutoutOrganizerTest { assertThat(mOrganizer.mOffsetX).isEqualTo(0); assertThat(mOrganizer.mOffsetY).isEqualTo(0); } + + @Test + public void testDisplaySizeChange() { + doReturn(100).when(mDisplayLayout).width(); + doReturn(200).when(mDisplayLayout).height(); + doReturn(mFakeDefaultCutoutInsets).when(mOrganizer) + .getDisplayCutoutInsetsOfNaturalOrientation(); + mContext.getOrCreateTestableResources().addOverride( + R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait); + doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation(); + mOrganizer.enableHideDisplayCutout(); + assertThat(mOrganizer.mCurrentDisplayBounds).isEqualTo(new Rect(0, 15, 100, 200)); + + doReturn(200).when(mDisplayLayout).width(); + doReturn(400).when(mDisplayLayout).height(); + mOrganizer.updateBoundsAndOffsets(true); + assertThat(mOrganizer.mCurrentDisplayBounds).isEqualTo(new Rect(0, 15, 200, 400)); + } }