Loading services/core/java/com/android/server/wm/ActivityRecord.java +106 −28 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ import android.view.InputApplicationHandle; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationTarget; import android.view.Surface.Rotation; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.WindowInsets.Type; Loading Loading @@ -780,6 +781,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ private final Configuration mTmpConfig = new Configuration(); private final Rect mTmpBounds = new Rect(); private final Rect mTmpOutNonDecorBounds = new Rect(); // Token for targeting this activity for assist purposes. final Binder assistToken = new Binder(); Loading Loading @@ -7173,8 +7175,53 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** * Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation * change and the requested orientation is different from the parent. * In some cases, applying insets to bounds changes the orientation. For example, if a * close-to-square display rotates to portrait to respect a portrait orientation activity, after * insets such as the status and nav bars are applied, the activity may actually have a * landscape orientation. This method checks whether the orientations of the activity window * with and without insets match or if the orientation with insets already matches the * requested orientation. If not, it may be necessary to letterbox the window. * @param parentBounds are the new parent bounds passed down to the activity and should be used * to compute the stable bounds. * @param outBounds will store the stable bounds, which are the bounds with insets applied. * These should be used to compute letterboxed bounds if orientation is not * respected when insets are applied. */ private boolean orientationRespectedWithInsets(Rect parentBounds, Rect outBounds) { if (mDisplayContent == null) { return true; } // Only need to make changes if activity sets an orientation final int requestedOrientation = getRequestedConfigurationOrientation(); if (requestedOrientation == ORIENTATION_UNDEFINED) { return true; } // Compute parent orientation from bounds final int orientation = parentBounds.height() >= parentBounds.width() ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; // Compute orientation from stable parent bounds (= parent bounds with insets applied) final Task task = getTask(); task.calculateInsetFrames(mTmpOutNonDecorBounds /* outNonDecorBounds */, outBounds /* outStableBounds */, parentBounds /* bounds */, mDisplayContent.getDisplayInfo()); final int orientationWithInsets = outBounds.height() >= outBounds.width() ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; // If orientation does not match the orientation with insets applied, then a // display rotation will not be enough to respect orientation. However, even if they do // not match but the orientation with insets applied matches the requested orientation, then // there is no need to modify the bounds because when insets are applied, the activity will // have the desired orientation. return orientation == orientationWithInsets || orientationWithInsets == requestedOrientation; } /** * Computes bounds (letterbox or pillarbox) when either: * 1. The parent doesn't handle the orientation change and the requested orientation is * different from the parent (see {@link DisplayContent#setIgnoreOrientationRequest()}. * 2. The parent handling the orientation is not enough. This occurs when the display rotation * may not be enough to respect orientation requests (see {@link * ActivityRecord#orientationRespectedWithInsets}). * * <p>If letterboxed due to fixed orientation then aspect ratio restrictions are also applied * in this method. Loading @@ -7182,9 +7229,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig, int windowingMode) { mLetterboxBoundsForFixedOrientationAndAspectRatio = null; if (handlesOrientationChangeFromDescendant()) { final Rect parentBounds = newParentConfig.windowConfiguration.getBounds(); final Rect containerBounds = new Rect(parentBounds); boolean orientationRespectedWithInsets = orientationRespectedWithInsets(parentBounds, containerBounds); if (handlesOrientationChangeFromDescendant() && orientationRespectedWithInsets) { // No need to letterbox because of fixed orientation. Display will handle // fixed-orientation requests. // fixed-orientation requests and a display rotation is enough to respect requested // orientation with insets applied. return; } if (WindowConfiguration.inMultiWindowMode(windowingMode) && isResizeable()) { Loading @@ -7204,7 +7256,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // If the activity requires a different orientation (either by override or activityInfo), // make it fit the available bounds by scaling down its bounds. final int forcedOrientation = getRequestedConfigurationOrientation(); if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) { if (forcedOrientation == ORIENTATION_UNDEFINED || (forcedOrientation == parentOrientation && orientationRespectedWithInsets)) { return; } Loading @@ -7216,53 +7269,75 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } final Rect parentBounds = newParentConfig.windowConfiguration.getBounds(); final int parentWidth = parentBounds.width(); final int parentHeight = parentBounds.height(); float aspect = Math.max(parentWidth, parentHeight) / (float) Math.min(parentWidth, parentHeight); // TODO(b/182268157) merge aspect ratio logic here and in // {@link ActivityRecord#applyAspectRatio} // if no aspect ratio constraints are provided, parent aspect ratio is used float aspectRatio = computeAspectRatio(parentBounds); // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with // set-fixed-orientation-letterbox-aspect-ratio. final float letterboxAspectRatioOverride = mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspect; aspectRatio = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspectRatio; // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in // order to use the extra available space. final float maxAspectRatio = info.getMaxAspectRatio(); final float minAspectRatio = info.getMinAspectRatio(); if (aspect > maxAspectRatio && maxAspectRatio != 0) { aspect = maxAspectRatio; } else if (aspect < minAspectRatio) { aspect = minAspectRatio; if (aspectRatio > maxAspectRatio && maxAspectRatio != 0) { aspectRatio = maxAspectRatio; } else if (aspectRatio < minAspectRatio) { aspectRatio = minAspectRatio; } // Store the current bounds to be able to revert to size compat mode values below if needed. Rect mTmpFullBounds = new Rect(resolvedBounds); final Rect prevResolvedBounds = new Rect(resolvedBounds); // Compute other dimension based on aspect ratio. Use bounds intersected with insets, stored // in containerBounds after calling {@link ActivityRecord#orientationRespectedWithInsets()}, // to ensure that aspect ratio is respected after insets are applied. int activityWidth; int activityHeight; if (forcedOrientation == ORIENTATION_LANDSCAPE) { final int height = (int) Math.rint(parentWidth / aspect); final int top = parentBounds.centerY() - height / 2; resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + height); activityWidth = parentBounds.width(); // Compute height from stable bounds width to ensure orientation respected after insets. activityHeight = (int) Math.rint(containerBounds.width() / aspectRatio); // Landscape is defined as width > height. To ensure activity is landscape when aspect // ratio is close to 1, reduce the height by one pixel. if (activityWidth == activityHeight) { activityHeight -= 1; } // Center vertically within stable bounds in landscape to ensure insets do not trim // height. final int top = containerBounds.centerY() - activityHeight / 2; resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + activityHeight); } else { final int width = (int) Math.rint(parentHeight / aspect); activityHeight = parentBounds.height(); // Compute width from stable bounds height to ensure orientation respected after insets. activityWidth = (int) Math.rint(containerBounds.height() / aspectRatio); // Center horizontally in portrait. For now, align to left and allow // {@link ActivityRecord#updateResolvedBoundsHorizontalPosition()} to center // horizontally. Exclude left insets from parent to ensure cutout does not trim width. final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds(); final int left = width <= parentAppBounds.width() // Avoid overlapping with the horizontal decor area when possible. ? parentAppBounds.left : parentBounds.centerX() - width / 2; resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom); resolvedBounds.set(parentAppBounds.left, parentBounds.top, parentAppBounds.left + activityWidth, parentBounds.bottom); } if (mCompatDisplayInsets != null) { mCompatDisplayInsets.getBoundsByRotation( mTmpBounds, newParentConfig.windowConfiguration.getRotation()); if (resolvedBounds.width() != mTmpBounds.width() || resolvedBounds.height() != mTmpBounds.height()) { // Insets may differ between different rotations, for example in the case of a display // cutout. To ensure consistent bounds across rotations, compare the activity dimensions // minus insets from the rotation the compat bounds were computed in. Task.intersectWithInsetsIfFits(mTmpBounds, parentBounds, mCompatDisplayInsets.mStableInsets[mCompatDisplayInsets.mOriginalRotation]); if (activityWidth != mTmpBounds.width() || activityHeight != mTmpBounds.height()) { // The app shouldn't be resized, we only do fixed orientation letterboxing if the // compat bounds are also from the same fixed orientation letterbox. Otherwise, // clear the fixed orientation bounds to show app in size compat mode. resolvedBounds.set(mTmpFullBounds); resolvedBounds.set(prevResolvedBounds); return; } } Loading Loading @@ -8507,6 +8582,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * compatibility mode activity compute the configuration without relying on its current display. */ static class CompatDisplayInsets { /** The original rotation the compat insets were computed in */ final @Rotation int mOriginalRotation; /** The container width on rotation 0. */ private final int mWidth; /** The container height on rotation 0. */ Loading @@ -8533,6 +8610,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A /** Constructs the environment to simulate the bounds behavior of the given container. */ CompatDisplayInsets(DisplayContent display, ActivityRecord container, @Nullable Rect fixedOrientationBounds) { mOriginalRotation = display.getRotation(); mIsFloating = container.getWindowConfiguration().tasksAreFloating(); if (mIsFloating) { final Rect containerBounds = container.getWindowConfiguration().getBounds(); Loading services/core/java/com/android/server/wm/Task.java +1 −1 Original line number Diff line number Diff line Loading @@ -2587,7 +2587,7 @@ class Task extends TaskFragment { * @param outStableBounds where to place bounds with stable insets applied. * @param bounds the bounds to inset. */ private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds, void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds, DisplayInfo displayInfo) { outNonDecorBounds.set(bounds); outStableBounds.set(bounds); Loading services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +34 −0 Original line number Diff line number Diff line Loading @@ -2700,6 +2700,40 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse("Starting window should not be present", activity.hasStartingWindow()); } @Test public void testCloseToSquareFixedOrientationPortrait() { // create a square display final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000) .setSystemDecorations(true).build(); final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); // create a fixed portrait activity final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT).build(); // check that both the configuration and app bounds are portrait assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation); assertTrue(activity.getConfiguration().windowConfiguration.getAppBounds().width() <= activity.getConfiguration().windowConfiguration.getAppBounds().height()); } @Test public void testCloseToSquareFixedOrientationLandscape() { // create a square display final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000) .setSystemDecorations(true).build(); final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); // create a fixed landscape activity final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task) .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE).build(); // check that both the configuration and app bounds are landscape assertEquals(ORIENTATION_LANDSCAPE, activity.getConfiguration().orientation); assertTrue(activity.getConfiguration().windowConfiguration.getAppBounds().width() > activity.getConfiguration().windowConfiguration.getAppBounds().height()); } private void assertHasStartingWindow(ActivityRecord atoken) { assertNotNull(atoken.mStartingSurface); assertNotNull(atoken.mStartingData); Loading services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +3 −2 Original line number Diff line number Diff line Loading @@ -395,6 +395,7 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); final Rect currentBounds = mActivity.getWindowConfiguration().getBounds(); final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds(); final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); final int notchHeight = 100; Loading Loading @@ -422,8 +423,8 @@ public class SizeCompatTests extends WindowTestsBase { // Because the display cannot rotate, the portrait activity will fit the short side of // display with keeping portrait bounds [200, 0 - 700, 1000] in center. assertEquals(newDisplayBounds.height(), currentBounds.height()); assertEquals(currentBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentBounds.width()); assertEquals(currentAppBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentAppBounds.width()); assertFitted(); // The appBounds should be [200, 100 - 700, 1000]. final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds(); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +106 −28 Original line number Diff line number Diff line Loading @@ -299,6 +299,7 @@ import android.view.InputApplicationHandle; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationDefinition; import android.view.RemoteAnimationTarget; import android.view.Surface.Rotation; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.WindowInsets.Type; Loading Loading @@ -780,6 +781,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A */ private final Configuration mTmpConfig = new Configuration(); private final Rect mTmpBounds = new Rect(); private final Rect mTmpOutNonDecorBounds = new Rect(); // Token for targeting this activity for assist purposes. final Binder assistToken = new Binder(); Loading Loading @@ -7173,8 +7175,53 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } /** * Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation * change and the requested orientation is different from the parent. * In some cases, applying insets to bounds changes the orientation. For example, if a * close-to-square display rotates to portrait to respect a portrait orientation activity, after * insets such as the status and nav bars are applied, the activity may actually have a * landscape orientation. This method checks whether the orientations of the activity window * with and without insets match or if the orientation with insets already matches the * requested orientation. If not, it may be necessary to letterbox the window. * @param parentBounds are the new parent bounds passed down to the activity and should be used * to compute the stable bounds. * @param outBounds will store the stable bounds, which are the bounds with insets applied. * These should be used to compute letterboxed bounds if orientation is not * respected when insets are applied. */ private boolean orientationRespectedWithInsets(Rect parentBounds, Rect outBounds) { if (mDisplayContent == null) { return true; } // Only need to make changes if activity sets an orientation final int requestedOrientation = getRequestedConfigurationOrientation(); if (requestedOrientation == ORIENTATION_UNDEFINED) { return true; } // Compute parent orientation from bounds final int orientation = parentBounds.height() >= parentBounds.width() ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; // Compute orientation from stable parent bounds (= parent bounds with insets applied) final Task task = getTask(); task.calculateInsetFrames(mTmpOutNonDecorBounds /* outNonDecorBounds */, outBounds /* outStableBounds */, parentBounds /* bounds */, mDisplayContent.getDisplayInfo()); final int orientationWithInsets = outBounds.height() >= outBounds.width() ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE; // If orientation does not match the orientation with insets applied, then a // display rotation will not be enough to respect orientation. However, even if they do // not match but the orientation with insets applied matches the requested orientation, then // there is no need to modify the bounds because when insets are applied, the activity will // have the desired orientation. return orientation == orientationWithInsets || orientationWithInsets == requestedOrientation; } /** * Computes bounds (letterbox or pillarbox) when either: * 1. The parent doesn't handle the orientation change and the requested orientation is * different from the parent (see {@link DisplayContent#setIgnoreOrientationRequest()}. * 2. The parent handling the orientation is not enough. This occurs when the display rotation * may not be enough to respect orientation requests (see {@link * ActivityRecord#orientationRespectedWithInsets}). * * <p>If letterboxed due to fixed orientation then aspect ratio restrictions are also applied * in this method. Loading @@ -7182,9 +7229,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig, int windowingMode) { mLetterboxBoundsForFixedOrientationAndAspectRatio = null; if (handlesOrientationChangeFromDescendant()) { final Rect parentBounds = newParentConfig.windowConfiguration.getBounds(); final Rect containerBounds = new Rect(parentBounds); boolean orientationRespectedWithInsets = orientationRespectedWithInsets(parentBounds, containerBounds); if (handlesOrientationChangeFromDescendant() && orientationRespectedWithInsets) { // No need to letterbox because of fixed orientation. Display will handle // fixed-orientation requests. // fixed-orientation requests and a display rotation is enough to respect requested // orientation with insets applied. return; } if (WindowConfiguration.inMultiWindowMode(windowingMode) && isResizeable()) { Loading @@ -7204,7 +7256,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // If the activity requires a different orientation (either by override or activityInfo), // make it fit the available bounds by scaling down its bounds. final int forcedOrientation = getRequestedConfigurationOrientation(); if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) { if (forcedOrientation == ORIENTATION_UNDEFINED || (forcedOrientation == parentOrientation && orientationRespectedWithInsets)) { return; } Loading @@ -7216,53 +7269,75 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } final Rect parentBounds = newParentConfig.windowConfiguration.getBounds(); final int parentWidth = parentBounds.width(); final int parentHeight = parentBounds.height(); float aspect = Math.max(parentWidth, parentHeight) / (float) Math.min(parentWidth, parentHeight); // TODO(b/182268157) merge aspect ratio logic here and in // {@link ActivityRecord#applyAspectRatio} // if no aspect ratio constraints are provided, parent aspect ratio is used float aspectRatio = computeAspectRatio(parentBounds); // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with // set-fixed-orientation-letterbox-aspect-ratio. final float letterboxAspectRatioOverride = mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio(); aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspect; aspectRatio = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspectRatio; // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in // order to use the extra available space. final float maxAspectRatio = info.getMaxAspectRatio(); final float minAspectRatio = info.getMinAspectRatio(); if (aspect > maxAspectRatio && maxAspectRatio != 0) { aspect = maxAspectRatio; } else if (aspect < minAspectRatio) { aspect = minAspectRatio; if (aspectRatio > maxAspectRatio && maxAspectRatio != 0) { aspectRatio = maxAspectRatio; } else if (aspectRatio < minAspectRatio) { aspectRatio = minAspectRatio; } // Store the current bounds to be able to revert to size compat mode values below if needed. Rect mTmpFullBounds = new Rect(resolvedBounds); final Rect prevResolvedBounds = new Rect(resolvedBounds); // Compute other dimension based on aspect ratio. Use bounds intersected with insets, stored // in containerBounds after calling {@link ActivityRecord#orientationRespectedWithInsets()}, // to ensure that aspect ratio is respected after insets are applied. int activityWidth; int activityHeight; if (forcedOrientation == ORIENTATION_LANDSCAPE) { final int height = (int) Math.rint(parentWidth / aspect); final int top = parentBounds.centerY() - height / 2; resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + height); activityWidth = parentBounds.width(); // Compute height from stable bounds width to ensure orientation respected after insets. activityHeight = (int) Math.rint(containerBounds.width() / aspectRatio); // Landscape is defined as width > height. To ensure activity is landscape when aspect // ratio is close to 1, reduce the height by one pixel. if (activityWidth == activityHeight) { activityHeight -= 1; } // Center vertically within stable bounds in landscape to ensure insets do not trim // height. final int top = containerBounds.centerY() - activityHeight / 2; resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + activityHeight); } else { final int width = (int) Math.rint(parentHeight / aspect); activityHeight = parentBounds.height(); // Compute width from stable bounds height to ensure orientation respected after insets. activityWidth = (int) Math.rint(containerBounds.height() / aspectRatio); // Center horizontally in portrait. For now, align to left and allow // {@link ActivityRecord#updateResolvedBoundsHorizontalPosition()} to center // horizontally. Exclude left insets from parent to ensure cutout does not trim width. final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds(); final int left = width <= parentAppBounds.width() // Avoid overlapping with the horizontal decor area when possible. ? parentAppBounds.left : parentBounds.centerX() - width / 2; resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom); resolvedBounds.set(parentAppBounds.left, parentBounds.top, parentAppBounds.left + activityWidth, parentBounds.bottom); } if (mCompatDisplayInsets != null) { mCompatDisplayInsets.getBoundsByRotation( mTmpBounds, newParentConfig.windowConfiguration.getRotation()); if (resolvedBounds.width() != mTmpBounds.width() || resolvedBounds.height() != mTmpBounds.height()) { // Insets may differ between different rotations, for example in the case of a display // cutout. To ensure consistent bounds across rotations, compare the activity dimensions // minus insets from the rotation the compat bounds were computed in. Task.intersectWithInsetsIfFits(mTmpBounds, parentBounds, mCompatDisplayInsets.mStableInsets[mCompatDisplayInsets.mOriginalRotation]); if (activityWidth != mTmpBounds.width() || activityHeight != mTmpBounds.height()) { // The app shouldn't be resized, we only do fixed orientation letterboxing if the // compat bounds are also from the same fixed orientation letterbox. Otherwise, // clear the fixed orientation bounds to show app in size compat mode. resolvedBounds.set(mTmpFullBounds); resolvedBounds.set(prevResolvedBounds); return; } } Loading Loading @@ -8507,6 +8582,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * compatibility mode activity compute the configuration without relying on its current display. */ static class CompatDisplayInsets { /** The original rotation the compat insets were computed in */ final @Rotation int mOriginalRotation; /** The container width on rotation 0. */ private final int mWidth; /** The container height on rotation 0. */ Loading @@ -8533,6 +8610,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A /** Constructs the environment to simulate the bounds behavior of the given container. */ CompatDisplayInsets(DisplayContent display, ActivityRecord container, @Nullable Rect fixedOrientationBounds) { mOriginalRotation = display.getRotation(); mIsFloating = container.getWindowConfiguration().tasksAreFloating(); if (mIsFloating) { final Rect containerBounds = container.getWindowConfiguration().getBounds(); Loading
services/core/java/com/android/server/wm/Task.java +1 −1 Original line number Diff line number Diff line Loading @@ -2587,7 +2587,7 @@ class Task extends TaskFragment { * @param outStableBounds where to place bounds with stable insets applied. * @param bounds the bounds to inset. */ private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds, void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds, DisplayInfo displayInfo) { outNonDecorBounds.set(bounds); outStableBounds.set(bounds); Loading
services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +34 −0 Original line number Diff line number Diff line Loading @@ -2700,6 +2700,40 @@ public class ActivityRecordTests extends WindowTestsBase { assertFalse("Starting window should not be present", activity.hasStartingWindow()); } @Test public void testCloseToSquareFixedOrientationPortrait() { // create a square display final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000) .setSystemDecorations(true).build(); final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); // create a fixed portrait activity final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task) .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT).build(); // check that both the configuration and app bounds are portrait assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation); assertTrue(activity.getConfiguration().windowConfiguration.getAppBounds().width() <= activity.getConfiguration().windowConfiguration.getAppBounds().height()); } @Test public void testCloseToSquareFixedOrientationLandscape() { // create a square display final DisplayContent squareDisplay = new TestDisplayContent.Builder(mAtm, 2000, 2000) .setSystemDecorations(true).build(); final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); // create a fixed landscape activity final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task) .setScreenOrientation(SCREEN_ORIENTATION_LANDSCAPE).build(); // check that both the configuration and app bounds are landscape assertEquals(ORIENTATION_LANDSCAPE, activity.getConfiguration().orientation); assertTrue(activity.getConfiguration().windowConfiguration.getAppBounds().width() > activity.getConfiguration().windowConfiguration.getAppBounds().height()); } private void assertHasStartingWindow(ActivityRecord atoken) { assertNotNull(atoken.mStartingSurface); assertNotNull(atoken.mStartingData); Loading
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +3 −2 Original line number Diff line number Diff line Loading @@ -395,6 +395,7 @@ public class SizeCompatTests extends WindowTestsBase { assertFitted(); final Rect currentBounds = mActivity.getWindowConfiguration().getBounds(); final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds(); final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds()); final int notchHeight = 100; Loading Loading @@ -422,8 +423,8 @@ public class SizeCompatTests extends WindowTestsBase { // Because the display cannot rotate, the portrait activity will fit the short side of // display with keeping portrait bounds [200, 0 - 700, 1000] in center. assertEquals(newDisplayBounds.height(), currentBounds.height()); assertEquals(currentBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentBounds.width()); assertEquals(currentAppBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(), currentAppBounds.width()); assertFitted(); // The appBounds should be [200, 100 - 700, 1000]. final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds(); Loading