From 7a7c6d387fdb04b564f48d014eac97392fc94e76 Mon Sep 17 00:00:00 2001 From: Oleg Blinnikov Date: Mon, 10 Oct 2022 15:25:21 +0000 Subject: [PATCH] Fix rounded corners cropping for letterbox When using two apps in horizontal split-screen, taskbar is shown, and the bottom app is "portrait-only" and letterboxed, this bottom application is partially covered by taskbar. This is because, the top of taskbar is calculated relative to the whole screen, while cropBounds.offsetTo(0, 0) makes cropBounds coordinates relative to the lower part of the screen. Reordering the statements of "adjustment of crop bounds" and "offsetting coordinates" fixes this issue Change-Id: Id1ac9252fbf102e321a89330aefda9ca2624fe66 Test: atest SizeCompatTests Bug: 245521412 --- .../server/wm/LetterboxUiController.java | 8 ++- .../android/server/wm/SizeCompatTests.java | 49 +++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index ea82417a2389b..74a236bd862c7 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -501,12 +501,16 @@ final class LetterboxUiController { if (hasVisibleTaskbar(mainWindow)) { cropBounds = new Rect(mActivityRecord.getBounds()); + + // Rounded corners should be displayed above the taskbar. + // It is important to call adjustBoundsForTaskbarUnchecked before offsetTo + // because taskbar bounds are in screen coordinates + adjustBoundsForTaskbarUnchecked(mainWindow, cropBounds); + // Activity bounds are in screen coordinates while (0,0) for activity's surface // control is at the top left corner of an app window so offsetting bounds // accordingly. cropBounds.offsetTo(0, 0); - // Rounded corners should be displayed above the taskbar. - adjustBoundsForTaskbarUnchecked(mainWindow, cropBounds); } transaction diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index c906abcdc9860..e5842b400ba3e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -25,6 +25,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS; +import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.InsetsState.ITYPE_TOP_MANDATORY_GESTURES; import static android.view.InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT; @@ -71,6 +72,7 @@ import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doCallRealMethod; +import static org.mockito.Mockito.times; import android.annotation.Nullable; import android.app.ActivityManager; @@ -87,6 +89,8 @@ import android.platform.test.annotations.Presubmit; import android.provider.DeviceConfig; import android.provider.DeviceConfig.Properties; import android.view.InsetsFrameProvider; +import android.view.InsetsSource; +import android.view.InsetsVisibilities; import android.view.WindowManager; import androidx.test.filters.MediumTest; @@ -105,6 +109,9 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; + +import java.util.List; /** * Tests for Size Compatibility mode. @@ -2367,6 +2374,48 @@ public class SizeCompatTests extends WindowTestsBase { any(), anyBoolean(), anyInt(), anyInt(), isNull(), eq(expectedLetterboxDetails)); } + @Test + public void testLetterboxDetailsForTaskBar_letterboxNotOverlappingTaskBar() { + mAtm.mDevEnableNonResizableMultiWindow = true; + final int screenHeight = 2200; + final int screenWidth = 1400; + final int taskbarHeight = 200; + setUpDisplaySizeWithApp(screenWidth, screenHeight); + + final TestSplitOrganizer organizer = + new TestSplitOrganizer(mAtm, mActivity.getDisplayContent()); + + // Move first activity to split screen which takes half of the screen. + organizer.mPrimary.setBounds(0, screenHeight / 2, screenWidth, screenHeight); + organizer.putTaskToPrimary(mTask, true); + + final InsetsSource navSource = new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR); + navSource.setFrame(new Rect(0, screenHeight - taskbarHeight, screenWidth, screenHeight)); + + mActivity.mWmService.mLetterboxConfiguration.setLetterboxActivityCornersRadius(15); + + final WindowState w1 = addWindowToActivity(mActivity); + w1.mAboveInsetsState.addSource(navSource); + + // Prepare unresizable activity with max aspect ratio + prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED); + + // Refresh the letterboxes + mActivity.mRootWindowContainer.performSurfacePlacement(); + + final ArgumentCaptor cropCapturer = ArgumentCaptor.forClass(Rect.class); + verify(mTransaction, times(2)).setWindowCrop( + eq(w1.getSurfaceControl()), + cropCapturer.capture() + ); + final List capturedCrops = cropCapturer.getAllValues(); + + final int expectedHeight = screenHeight / 2 - taskbarHeight; + assertEquals(2, capturedCrops.size()); + assertEquals(expectedHeight, capturedCrops.get(0).bottom); + assertEquals(expectedHeight, capturedCrops.get(1).bottom); + } + @Test public void testSplitScreenLetterboxDetailsForStatusBar_twoLetterboxedApps() { mAtm.mDevEnableNonResizableMultiWindow = true;