Merge "Show letterbox rounded corners behind navbar" into tm-qpr-dev am: 6f20d51b7a
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20882605 Change-Id: I280417578f5f6b0b19a6caa1c3156e8cb7386da3 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -105,6 +105,12 @@ final class LetterboxUiController {
|
|||||||
|
|
||||||
private final ActivityRecord mActivityRecord;
|
private final ActivityRecord mActivityRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Taskbar expanded height. Used to determine when to crop an app window to display the
|
||||||
|
* rounded corners above the expanded taskbar.
|
||||||
|
*/
|
||||||
|
private final float mExpandedTaskBarHeight;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WindowContainerListener responsible to make translucent activities inherit
|
* WindowContainerListener responsible to make translucent activities inherit
|
||||||
* constraints from the first opaque activity beneath them. It's null for not
|
* constraints from the first opaque activity beneath them. It's null for not
|
||||||
@@ -184,6 +190,9 @@ final class LetterboxUiController {
|
|||||||
() -> mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
|
() -> mLetterboxConfiguration.isCameraCompatTreatmentEnabled(
|
||||||
/* checkDeviceConfig */ true),
|
/* checkDeviceConfig */ true),
|
||||||
PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE);
|
PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE);
|
||||||
|
|
||||||
|
mExpandedTaskBarHeight =
|
||||||
|
getResources().getDimensionPixelSize(R.dimen.taskbar_frame_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -422,7 +431,7 @@ final class LetterboxUiController {
|
|||||||
if (w == null) {
|
if (w == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
adjustBoundsForTaskbar(w, outBounds);
|
adjustBoundsIfNeeded(w, outBounds);
|
||||||
} else {
|
} else {
|
||||||
outBounds.setEmpty();
|
outBounds.setEmpty();
|
||||||
}
|
}
|
||||||
@@ -465,13 +474,13 @@ final class LetterboxUiController {
|
|||||||
if (w == null || winHint != null && w != winHint) {
|
if (w == null || winHint != null && w != winHint) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateRoundedCorners(w);
|
updateRoundedCornersIfNeeded(w);
|
||||||
// If there is another main window that is not an application-starting window, we should
|
// If there is another main window that is not an application-starting window, we should
|
||||||
// update rounded corners for it as well, to avoid flickering rounded corners.
|
// update rounded corners for it as well, to avoid flickering rounded corners.
|
||||||
final WindowState nonStartingAppW = mActivityRecord.findMainWindow(
|
final WindowState nonStartingAppW = mActivityRecord.findMainWindow(
|
||||||
/* includeStartingApp= */ false);
|
/* includeStartingApp= */ false);
|
||||||
if (nonStartingAppW != null && nonStartingAppW != w) {
|
if (nonStartingAppW != null && nonStartingAppW != w) {
|
||||||
updateRoundedCorners(nonStartingAppW);
|
updateRoundedCornersIfNeeded(nonStartingAppW);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateWallpaperForLetterbox(w);
|
updateWallpaperForLetterbox(w);
|
||||||
@@ -775,8 +784,8 @@ final class LetterboxUiController {
|
|||||||
return isSurfaceReadyAndVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed()
|
return isSurfaceReadyAndVisible(mainWindow) && mainWindow.areAppWindowBoundsLetterboxed()
|
||||||
// Check for FLAG_SHOW_WALLPAPER explicitly instead of using
|
// Check for FLAG_SHOW_WALLPAPER explicitly instead of using
|
||||||
// WindowContainer#showWallpaper because the later will return true when this
|
// WindowContainer#showWallpaper because the later will return true when this
|
||||||
// activity is using blurred wallpaper for letterbox backgroud.
|
// activity is using blurred wallpaper for letterbox background.
|
||||||
&& (mainWindow.mAttrs.flags & FLAG_SHOW_WALLPAPER) == 0;
|
&& (mainWindow.getAttrs().flags & FLAG_SHOW_WALLPAPER) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -828,106 +837,107 @@ final class LetterboxUiController {
|
|||||||
return mLetterboxConfiguration.getLetterboxBackgroundColor();
|
return mLetterboxConfiguration.getLetterboxBackgroundColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRoundedCorners(WindowState mainWindow) {
|
private void updateRoundedCornersIfNeeded(final WindowState mainWindow) {
|
||||||
final SurfaceControl windowSurface = mainWindow.getSurfaceControl();
|
final SurfaceControl windowSurface = mainWindow.getSurfaceControl();
|
||||||
if (windowSurface != null && windowSurface.isValid()) {
|
if (windowSurface == null || !windowSurface.isValid()) {
|
||||||
final Transaction transaction = mActivityRecord.getSyncTransaction();
|
return;
|
||||||
|
|
||||||
if (!requiresRoundedCorners(mainWindow) || mActivityRecord.isInLetterboxAnimation()) {
|
|
||||||
// We don't want corner radius on the window.
|
|
||||||
// In the case the ActivityRecord requires a letterboxed animation we never want
|
|
||||||
// rounded corners on the window because rounded corners are applied at the
|
|
||||||
// animation-bounds surface level and rounded corners on the window would interfere
|
|
||||||
// with that leading to unexpected rounded corner positioning during the animation.
|
|
||||||
transaction
|
|
||||||
.setWindowCrop(windowSurface, null)
|
|
||||||
.setCornerRadius(windowSurface, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect cropBounds = null;
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
transaction
|
|
||||||
.setWindowCrop(windowSurface, cropBounds)
|
|
||||||
.setCornerRadius(windowSurface, getRoundedCornersRadius(mainWindow));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cropBounds must be non-null for the cornerRadius to be ever applied.
|
||||||
|
mActivityRecord.getSyncTransaction()
|
||||||
|
.setCrop(windowSurface, getCropBoundsIfNeeded(mainWindow))
|
||||||
|
.setCornerRadius(windowSurface, getRoundedCornersRadius(mainWindow));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean requiresRoundedCorners(WindowState mainWindow) {
|
@VisibleForTesting
|
||||||
final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow);
|
@Nullable
|
||||||
|
Rect getCropBoundsIfNeeded(final WindowState mainWindow) {
|
||||||
|
if (!requiresRoundedCorners(mainWindow) || mActivityRecord.isInLetterboxAnimation()) {
|
||||||
|
// We don't want corner radius on the window.
|
||||||
|
// In the case the ActivityRecord requires a letterboxed animation we never want
|
||||||
|
// rounded corners on the window because rounded corners are applied at the
|
||||||
|
// animation-bounds surface level and rounded corners on the window would interfere
|
||||||
|
// with that leading to unexpected rounded corner positioning during the animation.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Rect cropBounds = new Rect(mActivityRecord.getBounds());
|
||||||
|
|
||||||
|
// It is important to call {@link #adjustBoundsIfNeeded} before {@link cropBounds.offsetTo}
|
||||||
|
// because taskbar bounds used in {@link #adjustBoundsIfNeeded}
|
||||||
|
// are in screen coordinates
|
||||||
|
adjustBoundsIfNeeded(mainWindow, cropBounds);
|
||||||
|
|
||||||
|
// ActivityRecord bounds are in screen coordinates while (0,0) for activity's surface
|
||||||
|
// control is in the top left corner of an app window so offsetting bounds
|
||||||
|
// accordingly.
|
||||||
|
cropBounds.offsetTo(0, 0);
|
||||||
|
return cropBounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean requiresRoundedCorners(final WindowState mainWindow) {
|
||||||
return isLetterboxedNotForDisplayCutout(mainWindow)
|
return isLetterboxedNotForDisplayCutout(mainWindow)
|
||||||
&& mLetterboxConfiguration.isLetterboxActivityCornersRounded()
|
&& mLetterboxConfiguration.isLetterboxActivityCornersRounded();
|
||||||
&& taskbarInsetsSource != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns rounded corners radius the letterboxed activity should have based on override in
|
// Returns rounded corners radius the letterboxed activity should have based on override in
|
||||||
// R.integer.config_letterboxActivityCornersRadius or min device bottom corner radii.
|
// R.integer.config_letterboxActivityCornersRadius or min device bottom corner radii.
|
||||||
// Device corners can be different on the right and left sides but we use the same radius
|
// Device corners can be different on the right and left sides, but we use the same radius
|
||||||
// for all corners for consistency and pick a minimal bottom one for consistency with a
|
// for all corners for consistency and pick a minimal bottom one for consistency with a
|
||||||
// taskbar rounded corners.
|
// taskbar rounded corners.
|
||||||
int getRoundedCornersRadius(WindowState mainWindow) {
|
int getRoundedCornersRadius(final WindowState mainWindow) {
|
||||||
if (!requiresRoundedCorners(mainWindow)) {
|
if (!requiresRoundedCorners(mainWindow) || mActivityRecord.isInLetterboxAnimation()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int radius;
|
||||||
if (mLetterboxConfiguration.getLetterboxActivityCornersRadius() >= 0) {
|
if (mLetterboxConfiguration.getLetterboxActivityCornersRadius() >= 0) {
|
||||||
return mLetterboxConfiguration.getLetterboxActivityCornersRadius();
|
radius = mLetterboxConfiguration.getLetterboxActivityCornersRadius();
|
||||||
|
} else {
|
||||||
|
final InsetsState insetsState = mainWindow.getInsetsState();
|
||||||
|
radius = Math.min(
|
||||||
|
getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_LEFT),
|
||||||
|
getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_RIGHT));
|
||||||
}
|
}
|
||||||
|
|
||||||
final InsetsState insetsState = mainWindow.getInsetsState();
|
final float scale = mainWindow.mInvGlobalScale;
|
||||||
return Math.min(
|
return (scale != 1f && scale > 0f) ? (int) (scale * radius) : radius;
|
||||||
getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_LEFT),
|
|
||||||
getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_RIGHT));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether the taskbar is visible. Returns false if the window is in immersive mode,
|
* Returns the taskbar in case it is visible and expanded in height, otherwise returns null.
|
||||||
* since the user can swipe to show/hide the taskbar as an overlay.
|
|
||||||
*/
|
*/
|
||||||
private boolean hasVisibleTaskbar(WindowState mainWindow) {
|
@VisibleForTesting
|
||||||
final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow);
|
@Nullable
|
||||||
|
InsetsSource getExpandedTaskbarOrNull(final WindowState mainWindow) {
|
||||||
return taskbarInsetsSource != null
|
final InsetsSource taskbar = mainWindow.getInsetsState().peekSource(
|
||||||
&& taskbarInsetsSource.isVisible();
|
InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
|
||||||
|
if (taskbar != null && taskbar.isVisible()
|
||||||
|
&& taskbar.getFrame().height() >= mExpandedTaskBarHeight) {
|
||||||
|
return taskbar;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InsetsSource getTaskbarInsetsSource(WindowState mainWindow) {
|
private void adjustBoundsIfNeeded(final WindowState mainWindow, final Rect bounds) {
|
||||||
final InsetsState insetsState = mainWindow.getInsetsState();
|
|
||||||
return insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void adjustBoundsForTaskbar(WindowState mainWindow, Rect bounds) {
|
|
||||||
// Rounded corners should be displayed above the taskbar. When taskbar is hidden,
|
// Rounded corners should be displayed above the taskbar. When taskbar is hidden,
|
||||||
// an insets frame is equal to a navigation bar which shouldn't affect position of
|
// an insets frame is equal to a navigation bar which shouldn't affect position of
|
||||||
// rounded corners since apps are expected to handle navigation bar inset.
|
// rounded corners since apps are expected to handle navigation bar inset.
|
||||||
// This condition checks whether the taskbar is visible.
|
// This condition checks whether the taskbar is visible.
|
||||||
// Do not crop the taskbar inset if the window is in immersive mode - the user can
|
// Do not crop the taskbar inset if the window is in immersive mode - the user can
|
||||||
// swipe to show/hide the taskbar as an overlay.
|
// swipe to show/hide the taskbar as an overlay.
|
||||||
if (hasVisibleTaskbar(mainWindow)) {
|
// Adjust the bounds only in case there is an expanded taskbar,
|
||||||
adjustBoundsForTaskbarUnchecked(mainWindow, bounds);
|
// otherwise the rounded corners will be shown behind the navbar.
|
||||||
|
final InsetsSource expandedTaskbarOrNull = getExpandedTaskbarOrNull(mainWindow);
|
||||||
|
if (expandedTaskbarOrNull != null) {
|
||||||
|
// Rounded corners should be displayed above the expanded taskbar.
|
||||||
|
bounds.bottom = Math.min(bounds.bottom, expandedTaskbarOrNull.getFrame().top);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private void adjustBoundsForTaskbarUnchecked(WindowState mainWindow, Rect bounds) {
|
final float scale = mainWindow.mInvGlobalScale;
|
||||||
// Rounded corners should be displayed above the taskbar.
|
if (scale != 1f && scale > 0f) {
|
||||||
bounds.bottom =
|
bounds.scale(scale);
|
||||||
Math.min(bounds.bottom, getTaskbarInsetsSource(mainWindow).getFrame().top);
|
}
|
||||||
scaleIfNeeded(bounds);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getInsetsStateCornerRadius(
|
private int getInsetsStateCornerRadius(
|
||||||
@@ -1269,20 +1279,4 @@ final class LetterboxUiController {
|
|||||||
mInheritedSizeCompatScale = 1f;
|
mInheritedSizeCompatScale = 1f;
|
||||||
mInheritedCompatDisplayInsets = null;
|
mInheritedCompatDisplayInsets = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scaleIfNeeded(Rect bounds) {
|
|
||||||
if (boundsNeedToScale()) {
|
|
||||||
bounds.scale(1.0f / mActivityRecord.getCompatScale());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean boundsNeedToScale() {
|
|
||||||
if (hasInheritedLetterboxBehavior()) {
|
|
||||||
return mIsInheritedInSizeCompatMode
|
|
||||||
&& mInheritedSizeCompatScale < 1.0f;
|
|
||||||
} else {
|
|
||||||
return mActivityRecord.inSizeCompatMode()
|
|
||||||
&& mActivityRecord.getCompatScale() < 1.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,21 +28,36 @@ import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENT
|
|||||||
|
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.compat.testing.PlatformCompatChangeRule;
|
import android.compat.testing.PlatformCompatChangeRule;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.Property;
|
import android.content.pm.PackageManager.Property;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.view.InsetsSource;
|
||||||
|
import android.view.InsetsState;
|
||||||
|
import android.view.RoundedCorner;
|
||||||
|
import android.view.RoundedCorners;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.internal.R;
|
||||||
|
|
||||||
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
|
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -61,6 +76,14 @@ import org.junit.runner.RunWith;
|
|||||||
@Presubmit
|
@Presubmit
|
||||||
@RunWith(WindowTestRunner.class)
|
@RunWith(WindowTestRunner.class)
|
||||||
public class LetterboxUiControllerTest extends WindowTestsBase {
|
public class LetterboxUiControllerTest extends WindowTestsBase {
|
||||||
|
private static final int TASKBAR_COLLAPSED_HEIGHT = 10;
|
||||||
|
private static final int TASKBAR_EXPANDED_HEIGHT = 20;
|
||||||
|
private static final int SCREEN_WIDTH = 200;
|
||||||
|
private static final int SCREEN_HEIGHT = 100;
|
||||||
|
private static final Rect TASKBAR_COLLAPSED_BOUNDS = new Rect(0,
|
||||||
|
SCREEN_HEIGHT - TASKBAR_COLLAPSED_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
private static final Rect TASKBAR_EXPANDED_BOUNDS = new Rect(0,
|
||||||
|
SCREEN_HEIGHT - TASKBAR_EXPANDED_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public TestRule compatChangeRule = new PlatformCompatChangeRule();
|
public TestRule compatChangeRule = new PlatformCompatChangeRule();
|
||||||
@@ -69,6 +92,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
|
|||||||
private DisplayContent mDisplayContent;
|
private DisplayContent mDisplayContent;
|
||||||
private LetterboxUiController mController;
|
private LetterboxUiController mController;
|
||||||
private LetterboxConfiguration mLetterboxConfiguration;
|
private LetterboxConfiguration mLetterboxConfiguration;
|
||||||
|
private final Rect mLetterboxedPortraitTaskBounds = new Rect();
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -308,6 +332,162 @@ public class LetterboxUiControllerTest extends WindowTestsBase {
|
|||||||
assertTrue(mController.shouldForceRotateForCameraCompat());
|
assertTrue(mController.shouldForceRotateForCameraCompat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetCropBoundsIfNeeded_noCrop() {
|
||||||
|
final InsetsSource taskbar = new InsetsSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
|
||||||
|
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
|
||||||
|
|
||||||
|
// Do not apply crop if taskbar is collapsed
|
||||||
|
taskbar.setFrame(TASKBAR_COLLAPSED_BOUNDS);
|
||||||
|
assertNull(mController.getExpandedTaskbarOrNull(mainWindow));
|
||||||
|
|
||||||
|
mLetterboxedPortraitTaskBounds.set(SCREEN_WIDTH / 4, SCREEN_HEIGHT / 4,
|
||||||
|
SCREEN_WIDTH - SCREEN_WIDTH / 4, SCREEN_HEIGHT - SCREEN_HEIGHT / 4);
|
||||||
|
|
||||||
|
final Rect noCrop = mController.getCropBoundsIfNeeded(mainWindow);
|
||||||
|
assertNotEquals(null, noCrop);
|
||||||
|
assertEquals(0, noCrop.left);
|
||||||
|
assertEquals(0, noCrop.top);
|
||||||
|
assertEquals(mLetterboxedPortraitTaskBounds.width(), noCrop.right);
|
||||||
|
assertEquals(mLetterboxedPortraitTaskBounds.height(), noCrop.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetCropBoundsIfNeeded_appliesCrop() {
|
||||||
|
final InsetsSource taskbar = new InsetsSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
|
||||||
|
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
|
||||||
|
|
||||||
|
// Apply crop if taskbar is expanded
|
||||||
|
taskbar.setFrame(TASKBAR_EXPANDED_BOUNDS);
|
||||||
|
assertNotNull(mController.getExpandedTaskbarOrNull(mainWindow));
|
||||||
|
|
||||||
|
mLetterboxedPortraitTaskBounds.set(SCREEN_WIDTH / 4, 0, SCREEN_WIDTH - SCREEN_WIDTH / 4,
|
||||||
|
SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
final Rect crop = mController.getCropBoundsIfNeeded(mainWindow);
|
||||||
|
assertNotEquals(null, crop);
|
||||||
|
assertEquals(0, crop.left);
|
||||||
|
assertEquals(0, crop.top);
|
||||||
|
assertEquals(mLetterboxedPortraitTaskBounds.width(), crop.right);
|
||||||
|
assertEquals(mLetterboxedPortraitTaskBounds.height() - TASKBAR_EXPANDED_HEIGHT,
|
||||||
|
crop.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetCropBoundsIfNeeded_appliesCropWithSizeCompatScaling() {
|
||||||
|
final InsetsSource taskbar = new InsetsSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
|
||||||
|
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar);
|
||||||
|
final float scaling = 2.0f;
|
||||||
|
|
||||||
|
// Apply crop if taskbar is expanded
|
||||||
|
taskbar.setFrame(TASKBAR_EXPANDED_BOUNDS);
|
||||||
|
assertNotNull(mController.getExpandedTaskbarOrNull(mainWindow));
|
||||||
|
// With SizeCompat scaling
|
||||||
|
doReturn(true).when(mActivity).inSizeCompatMode();
|
||||||
|
mainWindow.mInvGlobalScale = scaling;
|
||||||
|
|
||||||
|
mLetterboxedPortraitTaskBounds.set(SCREEN_WIDTH / 4, 0, SCREEN_WIDTH - SCREEN_WIDTH / 4,
|
||||||
|
SCREEN_HEIGHT);
|
||||||
|
|
||||||
|
final int appWidth = mLetterboxedPortraitTaskBounds.width();
|
||||||
|
final int appHeight = mLetterboxedPortraitTaskBounds.height();
|
||||||
|
|
||||||
|
final Rect crop = mController.getCropBoundsIfNeeded(mainWindow);
|
||||||
|
assertNotEquals(null, crop);
|
||||||
|
assertEquals(0, crop.left);
|
||||||
|
assertEquals(0, crop.top);
|
||||||
|
assertEquals((int) (appWidth * scaling), crop.right);
|
||||||
|
assertEquals((int) ((appHeight - TASKBAR_EXPANDED_HEIGHT) * scaling), crop.bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRoundedCornersRadius_withRoundedCornersFromInsets() {
|
||||||
|
final float invGlobalScale = 0.5f;
|
||||||
|
final int expectedRadius = 7;
|
||||||
|
final int configurationRadius = 15;
|
||||||
|
|
||||||
|
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(/*taskbar=*/ null);
|
||||||
|
mainWindow.mInvGlobalScale = invGlobalScale;
|
||||||
|
final InsetsState insets = mainWindow.getInsetsState();
|
||||||
|
|
||||||
|
RoundedCorners roundedCorners = new RoundedCorners(
|
||||||
|
/*topLeft=*/ null,
|
||||||
|
/*topRight=*/ null,
|
||||||
|
/*bottomRight=*/ new RoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT,
|
||||||
|
configurationRadius, /*centerX=*/ 1, /*centerY=*/ 1),
|
||||||
|
/*bottomLeft=*/ new RoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT,
|
||||||
|
configurationRadius * 2 /*2 is to test selection of the min radius*/,
|
||||||
|
/*centerX=*/ 1, /*centerY=*/ 1)
|
||||||
|
);
|
||||||
|
doReturn(roundedCorners).when(insets).getRoundedCorners();
|
||||||
|
mLetterboxConfiguration.setLetterboxActivityCornersRadius(-1);
|
||||||
|
|
||||||
|
assertEquals(expectedRadius, mController.getRoundedCornersRadius(mainWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRoundedCornersRadius_withLetterboxActivityCornersRadius() {
|
||||||
|
final float invGlobalScale = 0.5f;
|
||||||
|
final int expectedRadius = 7;
|
||||||
|
final int configurationRadius = 15;
|
||||||
|
|
||||||
|
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(/*taskbar=*/ null);
|
||||||
|
mainWindow.mInvGlobalScale = invGlobalScale;
|
||||||
|
mLetterboxConfiguration.setLetterboxActivityCornersRadius(configurationRadius);
|
||||||
|
|
||||||
|
assertEquals(expectedRadius, mController.getRoundedCornersRadius(mainWindow));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetRoundedCornersRadius_noScalingApplied() {
|
||||||
|
final int configurationRadius = 15;
|
||||||
|
|
||||||
|
final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(/*taskbar=*/ null);
|
||||||
|
mLetterboxConfiguration.setLetterboxActivityCornersRadius(configurationRadius);
|
||||||
|
|
||||||
|
mainWindow.mInvGlobalScale = -1f;
|
||||||
|
assertEquals(configurationRadius, mController.getRoundedCornersRadius(mainWindow));
|
||||||
|
|
||||||
|
mainWindow.mInvGlobalScale = 0f;
|
||||||
|
assertEquals(configurationRadius, mController.getRoundedCornersRadius(mainWindow));
|
||||||
|
|
||||||
|
mainWindow.mInvGlobalScale = 1f;
|
||||||
|
assertEquals(configurationRadius, mController.getRoundedCornersRadius(mainWindow));
|
||||||
|
}
|
||||||
|
|
||||||
|
private WindowState mockForGetCropBoundsAndRoundedCorners(@Nullable InsetsSource taskbar) {
|
||||||
|
final WindowState mainWindow = mock(WindowState.class);
|
||||||
|
final InsetsState insets = mock(InsetsState.class);
|
||||||
|
final Resources resources = mWm.mContext.getResources();
|
||||||
|
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams();
|
||||||
|
|
||||||
|
mainWindow.mInvGlobalScale = 1f;
|
||||||
|
spyOn(resources);
|
||||||
|
spyOn(mActivity);
|
||||||
|
|
||||||
|
if (taskbar != null) {
|
||||||
|
taskbar.setVisible(true);
|
||||||
|
doReturn(taskbar).when(insets).peekSource(taskbar.getType());
|
||||||
|
}
|
||||||
|
doReturn(mLetterboxedPortraitTaskBounds).when(mActivity).getBounds();
|
||||||
|
doReturn(true).when(mActivity).isVisible();
|
||||||
|
doReturn(true).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
|
||||||
|
doReturn(insets).when(mainWindow).getInsetsState();
|
||||||
|
doReturn(attrs).when(mainWindow).getAttrs();
|
||||||
|
doReturn(true).when(mainWindow).isDrawn();
|
||||||
|
doReturn(false).when(mainWindow).isLetterboxedForDisplayCutout();
|
||||||
|
doReturn(true).when(mainWindow).areAppWindowBoundsLetterboxed();
|
||||||
|
doReturn(true).when(mLetterboxConfiguration).isLetterboxActivityCornersRounded();
|
||||||
|
doReturn(TASKBAR_EXPANDED_HEIGHT).when(resources).getDimensionPixelSize(
|
||||||
|
R.dimen.taskbar_frame_height);
|
||||||
|
|
||||||
|
// Need to reinitialise due to the change in resources getDimensionPixelSize output.
|
||||||
|
mController = new LetterboxUiController(mWm, mActivity);
|
||||||
|
|
||||||
|
return mainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
private void mockThatProperty(String propertyName, boolean value) throws Exception {
|
private void mockThatProperty(String propertyName, boolean value) throws Exception {
|
||||||
Property property = new Property(propertyName, /* value */ value, /* packageName */ "",
|
Property property = new Property(propertyName, /* value */ value, /* packageName */ "",
|
||||||
/* className */ "");
|
/* className */ "");
|
||||||
|
|||||||
@@ -2821,7 +2821,7 @@ public class SizeCompatTests extends WindowTestsBase {
|
|||||||
mActivity.mRootWindowContainer.performSurfacePlacement();
|
mActivity.mRootWindowContainer.performSurfacePlacement();
|
||||||
|
|
||||||
final ArgumentCaptor<Rect> cropCapturer = ArgumentCaptor.forClass(Rect.class);
|
final ArgumentCaptor<Rect> cropCapturer = ArgumentCaptor.forClass(Rect.class);
|
||||||
verify(mTransaction, times(2)).setWindowCrop(
|
verify(mTransaction, times(2)).setCrop(
|
||||||
eq(w1.getSurfaceControl()),
|
eq(w1.getSurfaceControl()),
|
||||||
cropCapturer.capture()
|
cropCapturer.capture()
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user