summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java14
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java2
-rw-r--r--services/core/java/com/android/server/wm/Task.java14
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java92
5 files changed, 118 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b40154e8db0c..d9faaf868b3a 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -6543,14 +6543,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mCompatDisplayInsets = new CompatDisplayInsets(mDisplayContent, this);
}
- @VisibleForTesting
- void clearSizeCompatMode() {
+ void clearSizeCompatMode(boolean recomputeTask) {
mSizeCompatScale = 1f;
mSizeCompatBounds = null;
mCompatDisplayInsets = null;
- // Recompute from Task because letterbox can also happen on Task level.
- task.onRequestedOverrideConfigurationChanged(task.getRequestedOverrideConfiguration());
+ if (recomputeTask) {
+ // Recompute from Task because letterbox can also happen on Task level.
+ task.onRequestedOverrideConfigurationChanged(task.getRequestedOverrideConfiguration());
+ }
+ }
+
+ @VisibleForTesting
+ void clearSizeCompatMode() {
+ clearSizeCompatMode(true /* recomputeTask */);
}
@Override
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 98a1bacf27e0..e8a4dc3814d0 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1303,7 +1303,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
@Override
boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
- ConfigurationContainer requestingContainer) {
+ WindowContainer requestingContainer) {
final Configuration config = updateOrientation(
getRequestedOverrideConfiguration(), freezeDisplayToken, false /* forceUpdate */);
// If display rotation class tells us that it doesn't consider app requested orientation,
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4b12fe1c5e38..d423766e9430 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3274,7 +3274,7 @@ class Task extends WindowContainer<WindowContainer> {
@Override
public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
- ConfigurationContainer requestingContainer) {
+ WindowContainer requestingContainer) {
if (super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer)) {
return true;
}
@@ -3282,6 +3282,18 @@ class Task extends WindowContainer<WindowContainer> {
// No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
// it if possible.
if (getParent() != null) {
+ final ActivityRecord activity = requestingContainer.asActivityRecord();
+ if (activity != null) {
+ // Clear the size compat cache to recompute the bounds for requested orientation;
+ // otherwise when Task#computeFullscreenBounds(), it will not try to do Task level
+ // letterboxing because app may prefer to keep its original size (size compat).
+ //
+ // Normally, ActivityRecord#clearSizeCompatMode() recomputes from its parent Task,
+ // which is the leaf Task. However, because this orientation request is new to all
+ // Tasks, pass false to clearSizeCompatMode, and trigger onConfigurationChanged from
+ // here (root Task) to make sure all Tasks are up-to-date.
+ activity.clearSizeCompatMode(false /* recomputeTask */);
+ }
onConfigurationChanged(getParent().getConfiguration());
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index da3a92856fe5..cec2b7335554 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -1144,7 +1144,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* @return {@code true} if handled; {@code false} otherwise.
*/
boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
- @Nullable ConfigurationContainer requestingContainer) {
+ @Nullable WindowContainer requestingContainer) {
final WindowContainer parent = getParent();
if (parent == null) {
return false;
@@ -1156,7 +1156,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
/**
* Check if this container or its parent will handle orientation changes from descendants. It's
* different from the return value of {@link #onDescendantOrientationChanged(IBinder,
- * ConfigurationContainer)} in the sense that the return value of this method tells if this
+ * WindowContainer)} in the sense that the return value of this method tells if this
* container or its parent will handle the request eventually, while the return value of the
* other method is if it handled the request synchronously.
*
@@ -1230,7 +1230,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
* to ensure it gets correct configuration.
*/
void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
- @Nullable ConfigurationContainer requestingContainer) {
+ @Nullable WindowContainer requestingContainer) {
if (mOrientation == orientation) {
return;
}
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 7a1b17dfead7..b7f6564b4135 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -28,6 +28,7 @@ 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.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.Task.ActivityState.STOPPED;
@@ -35,8 +36,11 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doCallRealMethod;
import android.app.ActivityManager;
@@ -628,7 +632,6 @@ public class SizeCompatTests extends WindowTestsBase {
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
final Rect displayBounds = mActivity.mDisplayContent.getBounds();
- final Rect newTaskBounds = mTask.getBounds();
final Rect newActivityBounds = mActivity.getBounds();
assertTrue(displayBounds.width() < displayBounds.height());
@@ -673,6 +676,93 @@ public class SizeCompatTests extends WindowTestsBase {
activityBounds.width());
}
+ @Test
+ public void testDisplayIgnoreOrientationRequest_newLaunchedOrientationAppInTaskLetterbox() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Portrait fixed app without max aspect.
+ prepareUnresizable(0, SCREEN_ORIENTATION_PORTRAIT);
+
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+
+ // Launch another portrait fixed app.
+ spyOn(mTask);
+ setBooted(display.mWmService.mAtmService);
+ final ActivityRecord newActivity = new ActivityBuilder(display.mWmService.mAtmService)
+ .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .setTask(mTask)
+ .build();
+
+ // Update with new activity requested orientation and recompute bounds with no previous
+ // size compat cache.
+ verify(mTask).onDescendantOrientationChanged(any(), same(newActivity));
+ verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
+ verify(newActivity).clearSizeCompatMode(false /* recomputeTask */);
+
+ final Rect displayBounds = display.getBounds();
+ final Rect taskBounds = mTask.getBounds();
+ final Rect newActivityBounds = newActivity.getBounds();
+
+ // Task and app bounds should be 700x1400 with the ratio as the display.
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(newActivity.inSizeCompatMode());
+ assertEquals(taskBounds, newActivityBounds);
+ assertEquals(displayBounds.height(), taskBounds.height());
+ assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
+ taskBounds.width());
+ }
+
+ @Test
+ public void testDisplayIgnoreOrientationRequest_newLaunchedMaxAspectApp() {
+ // Set up a display in landscape and ignoring orientation request.
+ setUpDisplaySizeWithApp(2800, 1400);
+ final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+
+ // Portrait fixed app without max aspect.
+ prepareUnresizable(0, SCREEN_ORIENTATION_PORTRAIT);
+
+ assertTrue(mTask.isTaskLetterboxed());
+ assertFalse(mActivity.inSizeCompatMode());
+
+ // Launch another portrait fixed app with max aspect ratio as 1.3.
+ spyOn(mTask);
+ setBooted(display.mWmService.mAtmService);
+ final ActivityRecord newActivity = new ActivityBuilder(display.mWmService.mAtmService)
+ .setResizeMode(RESIZE_MODE_UNRESIZEABLE)
+ .setMaxAspectRatio(1.3f)
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .setTask(mTask)
+ .build();
+
+ // Update with new activity requested orientation and recompute bounds with no previous
+ // size compat cache.
+ verify(mTask).onDescendantOrientationChanged(any(), same(newActivity));
+ verify(mTask).computeFullscreenBounds(any(), any(), any(), anyInt());
+ verify(newActivity).clearSizeCompatMode(false /* recomputeTask */);
+
+ final Rect displayBounds = display.getBounds();
+ final Rect taskBounds = mTask.getBounds();
+ final Rect newActivityBounds = newActivity.getBounds();
+
+ // Task bounds should be 700x1400 with the ratio as the display.
+ assertTrue(mTask.isTaskLetterboxed());
+ assertEquals(displayBounds.height(), taskBounds.height());
+ assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
+ taskBounds.width());
+
+ // App bounds should be 700x(710 x 1.3 = 910)
+ assertFalse(newActivity.inSizeCompatMode());
+ assertEquals(taskBounds.width(), newActivityBounds.width());
+ assertEquals((long) Math.rint(taskBounds.width() * newActivity.info.maxAspectRatio),
+ newActivityBounds.height());
+ }
+
private static WindowState addWindowToActivity(ActivityRecord activity) {
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;