Loading services/core/java/com/android/server/wm/ActivityRecord.java +22 −23 Original line number Diff line number Diff line Loading @@ -8042,11 +8042,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Horizontal position int offsetX = 0; if (parentBounds.width() != screenResolvedBounds.width()) { if (screenResolvedBounds.width() >= parentAppBounds.width()) { // If resolved bounds overlap with insets, center within app bounds. offsetX = getCenterOffset( parentAppBounds.width(), screenResolvedBounds.width()); } else { if (screenResolvedBounds.width() <= parentAppBounds.width()) { float positionMultiplier = mLetterboxUiController.getHorizontalPositionMultiplier( newParentConfiguration); Loading @@ -8058,11 +8054,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Vertical position int offsetY = 0; if (parentBounds.height() != screenResolvedBounds.height()) { if (screenResolvedBounds.height() >= parentAppBounds.height()) { // If resolved bounds overlap with insets, center within app bounds. offsetY = getCenterOffset( parentAppBounds.height(), screenResolvedBounds.height()); } else { if (screenResolvedBounds.height() <= parentAppBounds.height()) { float positionMultiplier = mLetterboxUiController.getVerticalPositionMultiplier( newParentConfiguration); Loading @@ -8080,6 +8072,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A offsetBounds(resolvedConfig, offsetX, offsetY); } // If the top is aligned with parentAppBounds add the vertical insets back so that the app // content aligns with the status bar if (resolvedConfig.windowConfiguration.getAppBounds().top == parentAppBounds.top) { resolvedConfig.windowConfiguration.getBounds().top = parentBounds.top; if (mSizeCompatBounds != null) { mSizeCompatBounds.top = parentBounds.top; } } // Since bounds has changed, the configuration needs to be computed accordingly. getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration); } Loading Loading @@ -8803,24 +8804,22 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Also account for the insets (e.g. display cutouts, navigation bar), which will be // clipped away later in {@link Task#computeConfigResourceOverrides()}, i.e., the out // bounds are the app bounds restricted by aspect ratio + clippable insets. Otherwise, // the app bounds would end up too small. // the app bounds would end up too small. To achieve this we will also add clippable insets // when the corresponding dimension fully fills the parent int right = activityWidth + containingAppBounds.left; int left = containingAppBounds.left; if (right >= containingAppBounds.right) { right += containingBounds.right - containingAppBounds.right; right = containingBounds.right; left = containingBounds.left; } int bottom = activityHeight + containingAppBounds.top; int top = containingAppBounds.top; if (bottom >= containingAppBounds.bottom) { bottom += containingBounds.bottom - containingAppBounds.bottom; bottom = containingBounds.bottom; top = containingBounds.top; } outBounds.set(containingBounds.left, containingBounds.top, right, bottom); // If the bounds are restricted by fixed aspect ratio, then out bounds should be put in the // container app bounds. Otherwise the entire container bounds are available. if (!outBounds.equals(containingBounds)) { // The horizontal position should not cover insets (e.g. display cutout). outBounds.left = containingAppBounds.left; } outBounds.set(left, top, right, bottom); return true; } Loading services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +79 −6 Original line number Diff line number Diff line Loading @@ -210,10 +210,8 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); // After the orientation of activity is changed, the display is rotated, the aspect // ratio should be the same (bounds=[100, 0 - 800, 583], appBounds=[100, 0 - 800, 583]). // ratio should be the same (bounds=[0, 0 - 800, 583], appBounds=[100, 0 - 800, 583]). assertEquals(appBounds.width(), appBounds.height() * aspectRatio, 0.5f /* delta */); // The notch is no longer on top. assertEquals(appBounds, mActivity.getBounds()); // Activity max bounds are sandboxed. assertActivityMaxBoundsSandboxed(); Loading Loading @@ -467,8 +465,6 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(ROTATION_270, mTask.getWindowConfiguration().getRotation()); assertEquals(origBounds.width(), currentBounds.width()); // The notch is on horizontal side, so current height changes from 1460 to 1400. assertEquals(origBounds.height() - notchHeight, currentBounds.height()); // Make sure the app size is the same assertEquals(origAppBounds.width(), appBounds.width()); assertEquals(origAppBounds.height(), appBounds.height()); Loading Loading @@ -2354,7 +2350,7 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.mRootWindowContainer.performSurfacePlacement(); Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); assertEquals(mBounds, new Rect(0, 750, 1000, 1950)); assertEquals(mBounds, new Rect(0, 900, 1000, 2000)); DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy(); LetterboxDetails[] expectedLetterboxDetails = {new LetterboxDetails( Loading Loading @@ -2533,6 +2529,64 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(sizeCompatScaled, mActivity.getBounds()); } @Test public void testApplyAspectRatio_activityAlignWithParentAppVertical() { // The display's app bounds will be (0, 100, 1000, 2350) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500) .setCanRotate(false) .setCutout(0, 100, 0, 150) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity height is 2100 and the display's app bounds height is 2250, so the activity // can be aligned inside parentAppBounds assertEquals(mActivity.getBounds(), new Rect(0, 0, 1000, 2200)); } @Test public void testApplyAspectRatio_activityCannotAlignWithParentAppVertical() { // The display's app bounds will be (0, 100, 1000, 2150) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2300) .setCanRotate(false) .setCutout(0, 100, 0, 150) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity height is 2100 and the display's app bounds height is 2050, so the activity // cannot be aligned inside parentAppBounds and it will fill the parentBounds of the display assertEquals(mActivity.getBounds(), display.getBounds()); } @Test public void testApplyAspectRatio_activityAlignWithParentAppHorizontal() { // The display's app bounds will be (100, 0, 2350, 1000) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 2500, 1000) .setCanRotate(false) .setCutout(100, 0, 150, 0) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity width is 2100 and the display's app bounds width is 2250, so the activity // can be aligned inside parentAppBounds assertEquals(mActivity.getBounds(), new Rect(175, 0, 2275, 1000)); } @Test public void testApplyAspectRatio_activityCannotAlignWithParentAppHorizontal() { // The display's app bounds will be (100, 0, 2150, 1000) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 2300, 1000) .setCanRotate(false) .setCutout(100, 0, 150, 0) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity width is 2100 and the display's app bounds width is 2050, so the activity // cannot be aligned inside parentAppBounds and it will fill the parentBounds of the display assertEquals(mActivity.getBounds(), display.getBounds()); } @Test public void testUpdateResolvedBoundsHorizontalPosition_activityFillParentWidth() { // When activity width equals parent width, multiplier shouldn't have any effect. Loading Loading @@ -2608,6 +2662,25 @@ public class SizeCompatTests extends WindowTestsBase { /* sizeCompatScaled */ new Rect(0, 1050, 700, 1400)); } @Test public void testUpdateResolvedBoundsPosition_alignToTop() { final int notchHeight = 100; final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2800) .setNotch(notchHeight) .build(); setUpApp(display); // Prepare unresizable activity with max aspect ratio prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED); Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); Rect appBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds()); // The insets should be cut for aspect ratio and then added back because the appBounds // are aligned to the top of the parentAppBounds assertEquals(mBounds, new Rect(0, 0, 1000, 1200)); assertEquals(appBounds, new Rect(0, notchHeight, 1000, 1200)); } private void assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity( float letterboxVerticalPositionMultiplier, Rect fixedOrientationLetterbox, Rect sizeCompatUnscaled, Rect sizeCompatScaled) { Loading services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +15 −2 Original line number Diff line number Diff line Loading @@ -143,11 +143,24 @@ class TestDisplayContent extends DisplayContent { mInfo.ownerUid = ownerUid; return this; } Builder setNotch(int height) { Builder setCutout(int left, int top, int right, int bottom) { final int cutoutFillerSize = 80; Rect boundLeft = left != 0 ? new Rect(0, 0, left, cutoutFillerSize) : null; Rect boundTop = top != 0 ? new Rect(0, 0, cutoutFillerSize, top) : null; Rect boundRight = right != 0 ? new Rect(mInfo.logicalWidth - right, 0, mInfo.logicalWidth, cutoutFillerSize) : null; Rect boundBottom = bottom != 0 ? new Rect(0, mInfo.logicalHeight - bottom, cutoutFillerSize, mInfo.logicalHeight) : null; mInfo.displayCutout = new DisplayCutout( Insets.of(0, height, 0, 0), null, new Rect(20, 0, 80, height), null, null); Insets.of(left, top, right, bottom), boundLeft, boundTop, boundRight, boundBottom); return this; } Builder setNotch(int height) { return setCutout(0, height, 0, 0); } Builder setStatusBarHeight(int height) { mStatusBarHeight = height; return this; Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +22 −23 Original line number Diff line number Diff line Loading @@ -8042,11 +8042,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Horizontal position int offsetX = 0; if (parentBounds.width() != screenResolvedBounds.width()) { if (screenResolvedBounds.width() >= parentAppBounds.width()) { // If resolved bounds overlap with insets, center within app bounds. offsetX = getCenterOffset( parentAppBounds.width(), screenResolvedBounds.width()); } else { if (screenResolvedBounds.width() <= parentAppBounds.width()) { float positionMultiplier = mLetterboxUiController.getHorizontalPositionMultiplier( newParentConfiguration); Loading @@ -8058,11 +8054,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Vertical position int offsetY = 0; if (parentBounds.height() != screenResolvedBounds.height()) { if (screenResolvedBounds.height() >= parentAppBounds.height()) { // If resolved bounds overlap with insets, center within app bounds. offsetY = getCenterOffset( parentAppBounds.height(), screenResolvedBounds.height()); } else { if (screenResolvedBounds.height() <= parentAppBounds.height()) { float positionMultiplier = mLetterboxUiController.getVerticalPositionMultiplier( newParentConfiguration); Loading @@ -8080,6 +8072,15 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A offsetBounds(resolvedConfig, offsetX, offsetY); } // If the top is aligned with parentAppBounds add the vertical insets back so that the app // content aligns with the status bar if (resolvedConfig.windowConfiguration.getAppBounds().top == parentAppBounds.top) { resolvedConfig.windowConfiguration.getBounds().top = parentBounds.top; if (mSizeCompatBounds != null) { mSizeCompatBounds.top = parentBounds.top; } } // Since bounds has changed, the configuration needs to be computed accordingly. getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration); } Loading Loading @@ -8803,24 +8804,22 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Also account for the insets (e.g. display cutouts, navigation bar), which will be // clipped away later in {@link Task#computeConfigResourceOverrides()}, i.e., the out // bounds are the app bounds restricted by aspect ratio + clippable insets. Otherwise, // the app bounds would end up too small. // the app bounds would end up too small. To achieve this we will also add clippable insets // when the corresponding dimension fully fills the parent int right = activityWidth + containingAppBounds.left; int left = containingAppBounds.left; if (right >= containingAppBounds.right) { right += containingBounds.right - containingAppBounds.right; right = containingBounds.right; left = containingBounds.left; } int bottom = activityHeight + containingAppBounds.top; int top = containingAppBounds.top; if (bottom >= containingAppBounds.bottom) { bottom += containingBounds.bottom - containingAppBounds.bottom; bottom = containingBounds.bottom; top = containingBounds.top; } outBounds.set(containingBounds.left, containingBounds.top, right, bottom); // If the bounds are restricted by fixed aspect ratio, then out bounds should be put in the // container app bounds. Otherwise the entire container bounds are available. if (!outBounds.equals(containingBounds)) { // The horizontal position should not cover insets (e.g. display cutout). outBounds.left = containingAppBounds.left; } outBounds.set(left, top, right, bottom); return true; } Loading
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +79 −6 Original line number Diff line number Diff line Loading @@ -210,10 +210,8 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); // After the orientation of activity is changed, the display is rotated, the aspect // ratio should be the same (bounds=[100, 0 - 800, 583], appBounds=[100, 0 - 800, 583]). // ratio should be the same (bounds=[0, 0 - 800, 583], appBounds=[100, 0 - 800, 583]). assertEquals(appBounds.width(), appBounds.height() * aspectRatio, 0.5f /* delta */); // The notch is no longer on top. assertEquals(appBounds, mActivity.getBounds()); // Activity max bounds are sandboxed. assertActivityMaxBoundsSandboxed(); Loading Loading @@ -467,8 +465,6 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(ROTATION_270, mTask.getWindowConfiguration().getRotation()); assertEquals(origBounds.width(), currentBounds.width()); // The notch is on horizontal side, so current height changes from 1460 to 1400. assertEquals(origBounds.height() - notchHeight, currentBounds.height()); // Make sure the app size is the same assertEquals(origAppBounds.width(), appBounds.width()); assertEquals(origAppBounds.height(), appBounds.height()); Loading Loading @@ -2354,7 +2350,7 @@ public class SizeCompatTests extends WindowTestsBase { mActivity.mRootWindowContainer.performSurfacePlacement(); Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); assertEquals(mBounds, new Rect(0, 750, 1000, 1950)); assertEquals(mBounds, new Rect(0, 900, 1000, 2000)); DisplayPolicy displayPolicy = mActivity.getDisplayContent().getDisplayPolicy(); LetterboxDetails[] expectedLetterboxDetails = {new LetterboxDetails( Loading Loading @@ -2533,6 +2529,64 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(sizeCompatScaled, mActivity.getBounds()); } @Test public void testApplyAspectRatio_activityAlignWithParentAppVertical() { // The display's app bounds will be (0, 100, 1000, 2350) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2500) .setCanRotate(false) .setCutout(0, 100, 0, 150) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity height is 2100 and the display's app bounds height is 2250, so the activity // can be aligned inside parentAppBounds assertEquals(mActivity.getBounds(), new Rect(0, 0, 1000, 2200)); } @Test public void testApplyAspectRatio_activityCannotAlignWithParentAppVertical() { // The display's app bounds will be (0, 100, 1000, 2150) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2300) .setCanRotate(false) .setCutout(0, 100, 0, 150) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity height is 2100 and the display's app bounds height is 2050, so the activity // cannot be aligned inside parentAppBounds and it will fill the parentBounds of the display assertEquals(mActivity.getBounds(), display.getBounds()); } @Test public void testApplyAspectRatio_activityAlignWithParentAppHorizontal() { // The display's app bounds will be (100, 0, 2350, 1000) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 2500, 1000) .setCanRotate(false) .setCutout(100, 0, 150, 0) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity width is 2100 and the display's app bounds width is 2250, so the activity // can be aligned inside parentAppBounds assertEquals(mActivity.getBounds(), new Rect(175, 0, 2275, 1000)); } @Test public void testApplyAspectRatio_activityCannotAlignWithParentAppHorizontal() { // The display's app bounds will be (100, 0, 2150, 1000) final DisplayContent display = new TestDisplayContent.Builder(mAtm, 2300, 1000) .setCanRotate(false) .setCutout(100, 0, 150, 0) .build(); setUpApp(display); prepareUnresizable(mActivity, 2.1f /* maxAspect */, SCREEN_ORIENTATION_UNSPECIFIED); // The activity width is 2100 and the display's app bounds width is 2050, so the activity // cannot be aligned inside parentAppBounds and it will fill the parentBounds of the display assertEquals(mActivity.getBounds(), display.getBounds()); } @Test public void testUpdateResolvedBoundsHorizontalPosition_activityFillParentWidth() { // When activity width equals parent width, multiplier shouldn't have any effect. Loading Loading @@ -2608,6 +2662,25 @@ public class SizeCompatTests extends WindowTestsBase { /* sizeCompatScaled */ new Rect(0, 1050, 700, 1400)); } @Test public void testUpdateResolvedBoundsPosition_alignToTop() { final int notchHeight = 100; final DisplayContent display = new TestDisplayContent.Builder(mAtm, 1000, 2800) .setNotch(notchHeight) .build(); setUpApp(display); // Prepare unresizable activity with max aspect ratio prepareUnresizable(mActivity, /* maxAspect */ 1.1f, SCREEN_ORIENTATION_UNSPECIFIED); Rect mBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); Rect appBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds()); // The insets should be cut for aspect ratio and then added back because the appBounds // are aligned to the top of the parentAppBounds assertEquals(mBounds, new Rect(0, 0, 1000, 1200)); assertEquals(appBounds, new Rect(0, notchHeight, 1000, 1200)); } private void assertVerticalPositionForDifferentDisplayConfigsForLandscapeActivity( float letterboxVerticalPositionMultiplier, Rect fixedOrientationLetterbox, Rect sizeCompatUnscaled, Rect sizeCompatScaled) { Loading
services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java +15 −2 Original line number Diff line number Diff line Loading @@ -143,11 +143,24 @@ class TestDisplayContent extends DisplayContent { mInfo.ownerUid = ownerUid; return this; } Builder setNotch(int height) { Builder setCutout(int left, int top, int right, int bottom) { final int cutoutFillerSize = 80; Rect boundLeft = left != 0 ? new Rect(0, 0, left, cutoutFillerSize) : null; Rect boundTop = top != 0 ? new Rect(0, 0, cutoutFillerSize, top) : null; Rect boundRight = right != 0 ? new Rect(mInfo.logicalWidth - right, 0, mInfo.logicalWidth, cutoutFillerSize) : null; Rect boundBottom = bottom != 0 ? new Rect(0, mInfo.logicalHeight - bottom, cutoutFillerSize, mInfo.logicalHeight) : null; mInfo.displayCutout = new DisplayCutout( Insets.of(0, height, 0, 0), null, new Rect(20, 0, 80, height), null, null); Insets.of(left, top, right, bottom), boundLeft, boundTop, boundRight, boundBottom); return this; } Builder setNotch(int height) { return setCutout(0, height, 0, 0); } Builder setStatusBarHeight(int height) { mStatusBarHeight = height; return this; Loading