Merge "Revert "Sandbox letterbox and size compat apps"" into sc-dev

This commit is contained in:
Winson Chung
2021-02-05 17:52:07 +00:00
committed by Android (Google) Code Review
8 changed files with 67 additions and 834 deletions

View File

@@ -25,8 +25,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.app.KeyguardManager;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -59,8 +59,12 @@ import java.util.List;
* an application window, excluding the system decorations. The application display area may
* be smaller than the real display area because the system subtracts the space needed
* for decor elements such as the status bar. Use {@link WindowMetrics#getBounds()} to query the
* application window bounds. Generally, use {@link WindowManager#getCurrentWindowMetrics()} to
* query the metrics and perform UI-related actions.</li>
* application window bounds.</li>
* <li>The real display area specifies the part of the display that contains content
* including the system decorations. Even so, the real display area may be smaller than the
* physical size of the display if the window manager is emulating a smaller display
* using (adb shell wm size). Use the following methods to query the
* real display area: {@link #getRealSize}, {@link #getRealMetrics}.</li>
* </ul>
* </p><p>
* A logical display does not necessarily represent a particular physical display device
@@ -673,9 +677,9 @@ public final class Display {
@UnsupportedAppUsage
public DisplayAdjustments getDisplayAdjustments() {
if (mResources != null) {
final DisplayAdjustments currentAdjustments = mResources.getDisplayAdjustments();
if (!mDisplayAdjustments.equals(currentAdjustments)) {
mDisplayAdjustments = new DisplayAdjustments(currentAdjustments);
final DisplayAdjustments currentAdjustements = mResources.getDisplayAdjustments();
if (!mDisplayAdjustments.equals(currentAdjustements)) {
mDisplayAdjustments = new DisplayAdjustments(currentAdjustements);
}
}
@@ -1213,34 +1217,30 @@ public final class Display {
}
/**
* Provides the largest {@link Point outSize} an app may expect in the current system state,
* without subtracting any window decor.
* Gets the real size of the display without subtracting any window decor or
* applying any compatibility scale factors.
* <p>
* The size describes the largest potential area the window might occupy. The size is adjusted
* based on the current rotation of the display.
* The size is adjusted based on the current rotation of the display.
* </p><p>
* The real size may be smaller than the physical size of the screen when the
* window manager is emulating a smaller display (using adb shell wm size).
* </p>
* </p><p>
* In general, {@link #getRealSize(Point)} and {@link WindowManager#getMaximumWindowMetrics()}
* report the same bounds except that certain areas of the display may not be available to
* windows created in the {@link WindowManager}'s {@link Context}.
*
* For example, imagine a device which has a multi-task mode that limits windows to half of the
* screen. In this case, {@link WindowManager#getMaximumWindowMetrics()} reports the
* bounds of the screen half where the window is located, while {@link #getRealSize(Point)}
* still reports the bounds of the whole display.
*
* @param outSize Set to the real size of the display.
*
* @see WindowManager#getMaximumWindowMetrics()
*/
public void getRealSize(Point outSize) {
synchronized (this) {
updateDisplayInfoLocked();
if (shouldReportMaxBounds()) {
final Rect bounds = mResources.getConfiguration()
.windowConfiguration.getMaxBounds();
outSize.x = bounds.width();
outSize.y = bounds.height();
if (DEBUG) {
Log.d(TAG, "getRealSize determined from max bounds: " + outSize
+ " for uid " + Process.myUid());
}
// Skip adjusting by fixed rotation, since if it is necessary, the configuration
// should already reflect the expected rotation.
return;
}
outSize.x = mDisplayInfo.logicalWidth;
outSize.y = mDisplayInfo.logicalHeight;
if (mMayAdjustByFixedRotation) {
@@ -1250,11 +1250,9 @@ public final class Display {
}
/**
* Provides the largest {@link DisplayMetrics outMetrics} an app may expect in the current
* system state, without subtracting any window decor.
* Gets display metrics based on the real size of this display.
* <p>
* The size describes the largest potential area the window might occupy. The size is adjusted
* based on the current rotation of the display.
* The size is adjusted based on the current rotation of the display.
* </p><p>
* The real size may be smaller than the physical size of the screen when the
* window manager is emulating a smaller display (using adb shell wm size).
@@ -1265,18 +1263,6 @@ public final class Display {
public void getRealMetrics(DisplayMetrics outMetrics) {
synchronized (this) {
updateDisplayInfoLocked();
if (shouldReportMaxBounds()) {
mDisplayInfo.getMaxBoundsMetrics(outMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO,
mResources.getConfiguration());
if (DEBUG) {
Log.d(TAG, "getRealMetrics determined from max bounds: " + outMetrics
+ " for uid " + Process.myUid());
}
// Skip adjusting by fixed rotation, since if it is necessary, the configuration
// should already reflect the expected rotation.
return;
}
mDisplayInfo.getLogicalMetrics(outMetrics,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
if (mMayAdjustByFixedRotation) {
@@ -1285,20 +1271,6 @@ public final class Display {
}
}
/**
* Determines if {@link WindowConfiguration#getMaxBounds()} should be reported as the
* display dimensions. The max bounds field may be smaller than the logical dimensions
* when apps need to be sandboxed.
* @return {@code true} when max bounds should be applied.
*/
private boolean shouldReportMaxBounds() {
if (mResources == null) {
return false;
}
final Configuration config = mResources.getConfiguration();
return config != null && !config.windowConfiguration.getMaxBounds().isEmpty();
}
/**
* Gets the state of the display, such as whether it is on or off.
*

View File

@@ -24,7 +24,6 @@ import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
import static android.view.DisplayInfoProto.NAME;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
@@ -616,29 +615,11 @@ public final class DisplayInfo implements Parcelable {
getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
}
/**
* Populates {@code outMetrics} with details of the logical display. Bounds are limited
* by the logical size of the display.
*
* @param outMetrics the {@link DisplayMetrics} to be populated
* @param compatInfo the {@link CompatibilityInfo} to be applied
* @param configuration the {@link Configuration}
*/
public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
Configuration configuration) {
getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
}
/**
* Similar to {@link #getLogicalMetrics}, but the limiting bounds are determined from
* {@link WindowConfiguration#getMaxBounds()}
*/
public void getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
Configuration configuration) {
Rect bounds = configuration.windowConfiguration.getMaxBounds();
getMetricsWithSize(outMetrics, compatInfo, configuration, bounds.width(), bounds.height());
}
public int getNaturalWidth() {
return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
logicalWidth : logicalHeight;

View File

@@ -1,527 +0,0 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_90;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.util.DisplayMetrics;
import android.view.DisplayAdjustments.FixedRotationAdjustments;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.quality.Strictness;
import java.util.function.Consumer;
/**
* Tests for {@link Display}.
*
* <p>Build/Install/Run:
*
* atest FrameworksMockingCoreTests:android.view.DisplayTests
*/
@RunWith(AndroidJUnit4.class)
public class DisplayTests {
private static final int APP_WIDTH = 272;
private static final int APP_HEIGHT = 700;
// Tablet size device, ROTATION_0 corresponds to portrait.
private static final int LOGICAL_WIDTH = 700;
private static final int LOGICAL_HEIGHT = 1800;
// Bounds of the app when the device is in portrait mode.
private static Rect sAppBoundsPortrait = buildAppBounds(LOGICAL_WIDTH, LOGICAL_HEIGHT);
private static Rect sAppBoundsLandscape = buildAppBounds(LOGICAL_HEIGHT, LOGICAL_WIDTH);
private StaticMockitoSession mMockitoSession;
private DisplayManagerGlobal mDisplayManagerGlobal;
private Context mApplicationContext;
private DisplayInfo mDisplayInfo = new DisplayInfo();
@Before
public void setupTests() {
mMockitoSession = mockitoSession()
.mockStatic(DisplayManagerGlobal.class)
.strictness(Strictness.LENIENT)
.startMocking();
// Ensure no adjustments are set before each test.
mApplicationContext = ApplicationProvider.getApplicationContext();
DisplayAdjustments displayAdjustments =
mApplicationContext.getResources().getDisplayAdjustments();
displayAdjustments.setFixedRotationAdjustments(null);
mApplicationContext.getResources().overrideDisplayAdjustments(null);
mApplicationContext.getResources().getConfiguration().windowConfiguration.setAppBounds(
null);
mApplicationContext.getResources().getConfiguration().windowConfiguration.setMaxBounds(
null);
mDisplayInfo.rotation = ROTATION_0;
mDisplayManagerGlobal = mock(DisplayManagerGlobal.class);
doReturn(mDisplayInfo).when(mDisplayManagerGlobal).getDisplayInfo(anyInt());
}
@After
public void teardownTests() {
if (mMockitoSession != null) {
mMockitoSession.finishMocking();
}
Mockito.framework().clearInlineMocks();
}
@Test
public void testConstructor_defaultDisplayAdjustments_matchesDisplayInfo() {
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
assertThat(display.getDisplayAdjustments()).isEqualTo(
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
DisplayInfo actualDisplayInfo = new DisplayInfo();
display.getDisplayInfo(actualDisplayInfo);
verifyDisplayInfo(actualDisplayInfo, mDisplayInfo);
}
@Test
public void testConstructor_defaultResources_matchesDisplayInfo() {
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
assertThat(display.getDisplayAdjustments()).isEqualTo(
mApplicationContext.getResources().getDisplayAdjustments());
DisplayInfo actualDisplayInfo = new DisplayInfo();
display.getDisplayInfo(actualDisplayInfo);
verifyDisplayInfo(actualDisplayInfo, mDisplayInfo);
}
@Test
public void testGetRotation_defaultDisplayAdjustments_rotationNotAdjusted() {
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
assertThat(display.getRotation()).isEqualTo(ROTATION_0);
}
@Test
public void testGetRotation_displayAdjustmentsWithoutOverride_rotationNotAdjusted() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated, but no override is set.
DisplayAdjustments displayAdjustments = DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
final FixedRotationAdjustments fixedRotationAdjustments =
new FixedRotationAdjustments(ROTATION_90, APP_WIDTH, APP_HEIGHT,
DisplayCutout.NO_CUTOUT);
displayAdjustments.setFixedRotationAdjustments(fixedRotationAdjustments);
// GIVEN display is constructed with display adjustments.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
displayAdjustments);
// THEN rotation is not adjusted since no override was set.
assertThat(display.getRotation()).isEqualTo(ROTATION_0);
}
@Test
public void testGetRotation_resourcesWithoutOverride_rotationNotAdjusted() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated, but no override is set.
setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN rotation is not adjusted since no override is set.
assertThat(display.getRotation()).isEqualTo(ROTATION_0);
}
@Test
public void testGetRotation_resourcesWithOverrideDisplayAdjustments_rotationAdjusted() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated, and an override is set.
setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN rotation is adjusted since an override is set.
assertThat(display.getRotation()).isEqualTo(ROTATION_90);
}
@Test
public void testGetRealSize_defaultResourcesPortrait_matchesLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches display orientation.
verifyRealSizeIsPortrait(display);
}
@Test
public void testGetRealSize_defaultResourcesLandscape_matchesRotatedLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches display orientation.
verifyRealSizeIsLandscape(display);
}
@Test
public void testGetRealSize_defaultDisplayAdjustmentsPortrait_matchesLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
// THEN real size matches display orientation.
verifyRealSizeIsPortrait(display);
}
@Test
public void testGetRealSize_defaultDisplayAdjustmentsLandscape_matchesLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
// THEN real size matches display orientation.
verifyRealSizeIsLandscape(display);
}
@Test
public void testGetRealSize_resourcesPortraitWithFixedRotation_notRotatedLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated.
setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches display orientation.
verifyRealSizeIsLandscape(display);
}
@Test
public void testGetRealSize_resourcesWithLandscapeFixedRotation_notRotatedLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated.
setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches display orientation.
verifyRealSizeIsPortrait(display);
}
@Test
public void testGetRealSize_resourcesWithPortraitOverrideRotation_rotatedLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated, and an override is set.
setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches app orientation.
verifyRealSizeIsPortrait(display);
}
@Test
public void testGetRealSize_resourcesWithLandscapeOverrideRotation_rotatedLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated, and an override is set.
setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches app orientation.
verifyRealSizeIsLandscape(display);
}
@Test
public void testGetRealSize_resourcesPortraitSandboxed_matchesSandboxBounds() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN app is letterboxed.
setMaxBoundsSandboxedToMatchAppBounds(mApplicationContext.getResources(),
sAppBoundsPortrait);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches app bounds.
verifyRealSizeMatchesApp(display, sAppBoundsPortrait);
}
@Test
public void testGetRealSize_resourcesLandscapeSandboxed_matchesSandboxBounds() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
// GIVEN app is letterboxed.
setMaxBoundsSandboxedToMatchAppBounds(mApplicationContext.getResources(),
sAppBoundsLandscape);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real size matches app bounds.
verifyRealSizeMatchesApp(display, sAppBoundsLandscape);
}
@Test
public void testGetRealMetrics_defaultResourcesPortrait_matchesLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches display orientation.
verifyRealMetricsIsPortrait(display);
}
@Test
public void testGetRealMetrics_defaultResourcesLandscape_matchesRotatedLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches display orientation.
verifyRealMetricsIsLandscape(display);
}
@Test
public void testGetRealMetrics_defaultDisplayAdjustmentsPortrait_matchesLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
// THEN real metrics matches display orientation.
verifyRealMetricsIsPortrait(display);
}
@Test
public void testGetRealMetrics_defaultDisplayAdjustmentsLandscape_matchesLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
// THEN real metrics matches display orientation.
verifyRealMetricsIsLandscape(display);
}
@Test
public void testGetRealMetrics_resourcesPortraitWithFixedRotation_notRotatedLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated.
setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches display orientation.
verifyRealMetricsIsLandscape(display);
}
@Test
public void testGetRealMetrics_resourcesWithLandscapeFixedRotation_notRotatedLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated.
setFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches display orientation.
verifyRealMetricsIsPortrait(display);
}
@Test
public void testGetRealMetrics_resourcesWithPortraitOverrideRotation_rotatedLogicalSize() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated with an override.
setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_0);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches app orientation.
verifyRealMetricsIsPortrait(display);
}
@Test
public void testGetRealMetrics_resourcesWithLandscapeOverrideRotation_rotatedLogicalSize() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN fixed rotation adjustments are rotated.
setOverrideFixedRotationAdjustments(mApplicationContext.getResources(), ROTATION_90);
// GIVEN display is constructed with default resources.
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches app orientation.
verifyRealMetricsIsLandscape(display);
}
@Test
public void testGetRealMetrics_resourcesPortraitSandboxed_matchesSandboxBounds() {
// GIVEN display is not rotated.
setDisplayInfoPortrait(mDisplayInfo);
// GIVEN app is letterboxed.
setMaxBoundsSandboxedToMatchAppBounds(mApplicationContext.getResources(),
sAppBoundsPortrait);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches app bounds.
verifyRealMetricsMatchesApp(display, sAppBoundsPortrait);
}
@Test
public void testGetRealMetrics_resourcesLandscapeSandboxed_matchesSandboxBounds() {
// GIVEN display is rotated.
setDisplayInfoLandscape(mDisplayInfo);
// GIVEN app is letterboxed.
setMaxBoundsSandboxedToMatchAppBounds(mApplicationContext.getResources(),
sAppBoundsLandscape);
final Display display = new Display(mDisplayManagerGlobal, DEFAULT_DISPLAY, mDisplayInfo,
mApplicationContext.getResources());
// THEN real metrics matches app bounds.
verifyRealMetricsMatchesApp(display, sAppBoundsLandscape);
}
// Given rotated display dimensions, calculate the letterboxed app bounds.
private static Rect buildAppBounds(int displayWidth, int displayHeight) {
final int midWidth = displayWidth / 2;
final int left = midWidth - (APP_WIDTH / 2);
final int right = midWidth + (APP_WIDTH / 2);
final int midHeight = displayHeight / 2;
// Coordinate system starts at top left.
final int top = midHeight - (APP_HEIGHT / 2);
final int bottom = midHeight + (APP_HEIGHT / 2);
return new Rect(left, top, right, bottom);
}
private static void setDisplayInfoLandscape(DisplayInfo displayInfo) {
displayInfo.rotation = ROTATION_90;
// Flip width & height assignment since the device is rotated.
displayInfo.logicalWidth = LOGICAL_HEIGHT;
displayInfo.logicalHeight = LOGICAL_WIDTH;
}
private static void setDisplayInfoPortrait(DisplayInfo displayInfo) {
displayInfo.rotation = ROTATION_0;
displayInfo.logicalWidth = LOGICAL_WIDTH;
displayInfo.logicalHeight = LOGICAL_HEIGHT;
}
/**
* Set max bounds to be sandboxed to the app bounds, indicating the app is in
* size compat mode or letterbox.
*/
private static void setMaxBoundsSandboxedToMatchAppBounds(Resources resources, Rect appBounds) {
resources.getConfiguration().windowConfiguration.setMaxBounds(appBounds);
}
/**
* Do not compare entire display info, since it is updated to match display the test is run on.
*/
private static void verifyDisplayInfo(DisplayInfo actual, DisplayInfo expected) {
assertThat(actual.displayId).isEqualTo(expected.displayId);
assertThat(actual.rotation).isEqualTo(expected.rotation);
assertThat(actual.logicalWidth).isEqualTo(LOGICAL_WIDTH);
assertThat(actual.logicalHeight).isEqualTo(LOGICAL_HEIGHT);
}
private static void verifyRealSizeIsLandscape(Display display) {
Point size = new Point();
display.getRealSize(size);
// Flip the width and height check since the device is rotated.
assertThat(size).isEqualTo(new Point(LOGICAL_HEIGHT, LOGICAL_WIDTH));
}
private static void verifyRealMetricsIsLandscape(Display display) {
DisplayMetrics metrics = new DisplayMetrics();
display.getRealMetrics(metrics);
// Flip the width and height check since the device is rotated.
assertThat(metrics.widthPixels).isEqualTo(LOGICAL_HEIGHT);
assertThat(metrics.heightPixels).isEqualTo(LOGICAL_WIDTH);
}
private static void verifyRealSizeIsPortrait(Display display) {
Point size = new Point();
display.getRealSize(size);
assertThat(size).isEqualTo(new Point(LOGICAL_WIDTH, LOGICAL_HEIGHT));
}
private static void verifyRealMetricsIsPortrait(Display display) {
DisplayMetrics metrics = new DisplayMetrics();
display.getRealMetrics(metrics);
assertThat(metrics.widthPixels).isEqualTo(LOGICAL_WIDTH);
assertThat(metrics.heightPixels).isEqualTo(LOGICAL_HEIGHT);
}
private static void verifyRealSizeMatchesApp(Display display, Rect appBounds) {
Point size = new Point();
display.getRealSize(size);
assertThat(size).isEqualTo(new Point(appBounds.width(), appBounds.height()));
}
private static void verifyRealMetricsMatchesApp(Display display, Rect appBounds) {
DisplayMetrics metrics = new DisplayMetrics();
display.getRealMetrics(metrics);
assertThat(metrics.widthPixels).isEqualTo(appBounds.width());
assertThat(metrics.heightPixels).isEqualTo(appBounds.height());
}
private static FixedRotationAdjustments setOverrideFixedRotationAdjustments(
Resources resources, @Surface.Rotation int rotation) {
FixedRotationAdjustments fixedRotationAdjustments =
setFixedRotationAdjustments(resources, rotation);
resources.overrideDisplayAdjustments(
buildOverrideRotationAdjustments(fixedRotationAdjustments));
return fixedRotationAdjustments;
}
private static FixedRotationAdjustments setFixedRotationAdjustments(Resources resources,
@Surface.Rotation int rotation) {
final FixedRotationAdjustments fixedRotationAdjustments =
new FixedRotationAdjustments(rotation, APP_WIDTH, APP_HEIGHT,
DisplayCutout.NO_CUTOUT);
resources.getDisplayAdjustments().setFixedRotationAdjustments(fixedRotationAdjustments);
return fixedRotationAdjustments;
}
private static Consumer<DisplayAdjustments> buildOverrideRotationAdjustments(
FixedRotationAdjustments fixedRotationAdjustments) {
return consumedDisplayAdjustments
-> consumedDisplayAdjustments.setFixedRotationAdjustments(fixedRotationAdjustments);
}
}

View File

@@ -1903,6 +1903,12 @@
"group": "WM_DEBUG_FOCUS_LIGHT",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
"123161180": {
"message": "SEVER CHILDREN",
"level": "INFO",
"group": "WM_SHOW_TRANSACTIONS",
"at": "com\/android\/server\/wm\/WindowSurfaceController.java"
},
"140319294": {
"message": "IME target changed within ActivityRecord",
"level": "DEBUG",
@@ -2137,12 +2143,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
"332390227": {
"message": "Sandbox max bounds for uid %s to bounds %s due to letterboxing? %s mismatch with parent bounds? %s size compat mode %s",
"level": "DEBUG",
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
"342460966": {
"message": "DRAG %s: pos=(%d,%d)",
"level": "INFO",
@@ -2623,12 +2623,6 @@
"group": "WM_DEBUG_WINDOW_ORGANIZER",
"at": "com\/android\/server\/wm\/WindowOrganizerController.java"
},
"910200295": {
"message": "Sandbox max bounds due to mismatched orientation with parent, to %s vs DisplayArea %s",
"level": "DEBUG",
"group": "WM_DEBUG_CONFIGURATION",
"at": "com\/android\/server\/wm\/Task.java"
},
"913494177": {
"message": "removeAllWindowsIfPossible: removing win=%s",
"level": "WARN",

View File

@@ -16,7 +16,6 @@
package com.android.server.wm;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
@@ -82,7 +81,6 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
@@ -203,7 +201,6 @@ import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.ACTIVITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -273,7 +270,6 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.permission.PermissionManager;
import android.service.dreams.DreamActivity;
import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession;
@@ -6779,20 +6775,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// layout traversals.
mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
getResolvedOverrideConfiguration().seq = mConfigurationSeq;
// Sandbox max bounds by setting it to the app bounds, if activity is letterboxed or in
// size compat mode.
if (providesMaxBounds()) {
if (DEBUG_CONFIGURATION) {
ProtoLog.d(WM_DEBUG_CONFIGURATION, "Sandbox max bounds for uid %s to bounds %s "
+ "due to letterboxing? %s mismatch with parent bounds? %s size compat "
+ "mode %s", getUid(),
resolvedConfig.windowConfiguration.getBounds(), mLetterbox != null,
!matchParentBounds(), inSizeCompatMode());
}
resolvedConfig.windowConfiguration
.setMaxBounds(resolvedConfig.windowConfiguration.getBounds());
}
}
/**
@@ -6976,19 +6958,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return super.getBounds();
}
@Override
public boolean providesMaxBounds() {
// System and SystemUI should always be able to access the physical display bounds,
// so do not provide it with the overridden maximum bounds.
// TODO(b/179179513) check WindowState#mOwnerCanAddInternalSystemWindow instead
if (getUid() == SYSTEM_UID || PermissionManager.checkPermission(INTERNAL_SYSTEM_WINDOW,
getPid(), info.applicationInfo.uid) == PERMISSION_GRANTED) {
return false;
}
// Max bounds should be sandboxed when this is letterboxed or in size compat mode.
return mLetterbox != null || !matchParentBounds() || inSizeCompatMode();
}
@VisibleForTesting
@Override
Rect getAnimationBounds(int appRootTaskClipMode) {

View File

@@ -77,7 +77,6 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
@@ -145,7 +144,6 @@ import static com.android.server.wm.TaskProto.WINDOW_CONTAINER;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowContainerChildProto.TASK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -2867,16 +2865,6 @@ class Task extends WindowContainer<WindowContainer> {
// In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
outBounds.setEmpty();
computeLetterboxBounds(outBounds, newParentConfig);
// Since the task is letterboxed due to mismatched orientation against its parent,
// sandbox max bounds to the app bounds.
if (!outBounds.isEmpty()) {
if (DEBUG_CONFIGURATION) {
ProtoLog.d(WM_DEBUG_CONFIGURATION, "Sandbox max bounds due to mismatched "
+ "orientation with parent, to %s vs DisplayArea %s", outBounds,
getDisplayArea() != null ? getDisplayArea().getBounds() : "null");
}
getResolvedOverrideConfiguration().windowConfiguration.setMaxBounds(outBounds);
}
}
/** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FREEFORM}. */

View File

@@ -39,8 +39,6 @@ import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.Task.ActivityState.STOPPED;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -119,13 +117,13 @@ public class SizeCompatTests extends WindowTestsBase {
@Test
public void testKeepBoundsWhenChangingFromFreeformToFullscreen() {
removeGlobalMinSizeRestriction();
// Create landscape freeform display and a freeform app.
// create freeform display and a freeform app
DisplayContent display = new TestDisplayContent.Builder(mAtm, 2000, 1000)
.setCanRotate(false)
.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM).build();
setUpApp(display);
// Put app window into portrait freeform and then make it a compat app.
// Put app window into freeform and then make it a compat app.
final Rect bounds = new Rect(100, 100, 400, 600);
mTask.setBounds(bounds);
prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
@@ -138,7 +136,7 @@ public class SizeCompatTests extends WindowTestsBase {
final int density = mActivity.getConfiguration().densityDpi;
// Change display configuration to fullscreen.
// change display configuration to fullscreen
Configuration c = new Configuration(display.getRequestedOverrideConfiguration());
c.windowConfiguration.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
display.onRequestedOverrideConfigurationChanged(c);
@@ -148,8 +146,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(bounds.width(), mActivity.getBounds().width());
assertEquals(bounds.height(), mActivity.getBounds().height());
assertEquals(density, mActivity.getConfiguration().densityDpi);
// Size compat mode is sandboxed at the activity level.
assertActivityMaxBoundsSandboxedForSizeCompat();
}
@Test
@@ -175,12 +171,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(appBounds.height(), appBounds.width() * aspectRatio, 0.5f /* delta */);
// The decor height should be a part of the effective bounds.
assertEquals(mActivity.getBounds().height(), appBounds.height() + notchHeight);
// Activity max bounds should be sandboxed; activity is letterboxed due to aspect ratio.
assertActivityMaxBoundsSandboxedForLetterbox();
// Activity max bounds ignore notch, since an app can be shown past the notch (although app
// is currently limited by the notch).
assertThat(mActivity.getWindowConfiguration().getMaxBounds().height())
.isEqualTo(displayBounds.height());
mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
assertFitted();
@@ -190,17 +180,9 @@ public class SizeCompatTests extends WindowTestsBase {
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.
assertActivityMaxBoundsSandboxedForLetterbox();
mActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertFitted();
// Activity max bounds should be sandboxed; activity is letterboxed due to aspect ratio.
assertActivityMaxBoundsSandboxedForLetterbox();
// Activity max bounds ignore notch, since an app can be shown past the notch (although app
// is currently limited by the notch).
assertThat(mActivity.getWindowConfiguration().getMaxBounds().height())
.isEqualTo(displayBounds.height());
}
@Test
@@ -228,9 +210,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(originalBounds.width(), mActivity.getBounds().width());
assertEquals(originalBounds.height(), mActivity.getBounds().height());
assertEquals(originalDpi, mActivity.getConfiguration().densityDpi);
// Activity is sandboxed; it is in size compat mode since it is not resizable and has a
// max aspect ratio.
assertActivityMaxBoundsSandboxedForSizeCompat();
assertScaled();
}
@@ -238,13 +217,11 @@ public class SizeCompatTests extends WindowTestsBase {
public void testFixedScreenBoundsWhenDisplaySizeChanged() {
setUpDisplaySizeWithApp(1000, 2500);
prepareUnresizable(mActivity, -1f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
final DisplayContent display = mActivity.mDisplayContent;
assertFitted();
// Activity and task inherit bounds from TaskDisplayArea, since not sandboxed.
assertMaxBoundsInheritDisplayAreaBounds();
final Rect origBounds = new Rect(mActivity.getBounds());
final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
final DisplayContent display = mActivity.mDisplayContent;
// Change the size of current display.
resizeDisplay(display, 1000, 2000);
@@ -261,8 +238,6 @@ public class SizeCompatTests extends WindowTestsBase {
// The position of configuration bounds should be the same as compat bounds.
assertEquals(mActivity.getBounds().left, currentBounds.left);
assertEquals(mActivity.getBounds().top, currentBounds.top);
// Activity is sandboxed to the offset size compat bounds.
assertActivityMaxBoundsSandboxedForSizeCompat();
// Change display size to a different orientation
resizeDisplay(display, 2000, 1000);
@@ -271,8 +246,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(origBounds.height(), currentBounds.height());
assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
// Activity is sandboxed to the offset size compat bounds.
assertActivityMaxBoundsSandboxedForSizeCompat();
// The previous resize operation doesn't consider the rotation change after size changed.
// These setups apply the requested orientation to rotation as real case that the top fixed
@@ -292,8 +265,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(origBounds.height(), currentBounds.height());
assertEquals(offsetX, currentBounds.left);
assertScaled();
// Activity is sandboxed due to size compat mode.
assertActivityMaxBoundsSandboxedForSizeCompat();
}
@Test
@@ -309,8 +280,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(bounds.width(), bounds.height() * maxAspect, 0.0001f /* delta */);
// The position should be horizontal centered.
assertEquals((displayWidth - bounds.width()) / 2, bounds.left);
// Activity max bounds should be sandboxed since it is letterboxed.
assertActivityMaxBoundsSandboxedForLetterbox();
mActivity.mDisplayContent.setImeLayeringTarget(addWindowToActivity(mActivity));
// Make sure IME cannot attach to the app, otherwise IME window will also be shifted.
@@ -322,8 +291,6 @@ public class SizeCompatTests extends WindowTestsBase {
// It should keep non-attachable because the resolved bounds will be computed according to
// the aspect ratio that won't match its parent bounds.
assertFalse(mActivity.mDisplayContent.isImeAttachedToApp());
// Activity max bounds should be sandboxed since it is letterboxed.
assertActivityMaxBoundsSandboxedForLetterbox();
}
@Test
@@ -349,13 +316,14 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
public void testMoveToDifferentOrientationDisplay() {
public void testMoveToDifferentOrientDisplay() {
setUpDisplaySizeWithApp(1000, 2500);
prepareUnresizable(mActivity, -1.f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
assertFitted();
final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds());
final Rect configBounds = mActivity.getWindowConfiguration().getBounds();
final int origWidth = configBounds.width();
final int origHeight = configBounds.height();
final int notchHeight = 100;
final DisplayContent newDisplay = new TestDisplayContent.Builder(mAtm, 2000, 1000)
@@ -364,44 +332,37 @@ public class SizeCompatTests extends WindowTestsBase {
// Move the non-resizable activity to the new display.
mTask.reparent(newDisplay.getDefaultTaskDisplayArea(), true /* onTop */);
// The configuration bounds [820, 0 - 1820, 2500] should keep the same.
assertEquals(originalBounds.width(), currentBounds.width());
assertEquals(originalBounds.height(), currentBounds.height());
assertEquals(origWidth, configBounds.width());
assertEquals(origHeight, configBounds.height());
assertScaled();
// Activity max bounds are sandboxed due to size compat mode on the new display.
assertActivityMaxBoundsSandboxedForSizeCompat();
final Rect newDisplayBounds = newDisplay.getWindowConfiguration().getBounds();
// The scaled bounds should exclude notch area (1000 - 100 == 360 * 2500 / 1000 = 900).
assertEquals(newDisplayBounds.height() - notchHeight,
(int) ((float) mActivity.getBounds().width() * originalBounds.height()
/ originalBounds.width()));
(int) ((float) mActivity.getBounds().width() * origHeight / origWidth));
// Recompute the natural configuration in the new display.
mActivity.clearSizeCompatMode();
mActivity.ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
// 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(newDisplayBounds.height(), configBounds.height());
assertEquals(configBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(),
configBounds.width());
assertFitted();
// The appBounds should be [200, 100 - 700, 1000].
final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();
assertEquals(currentBounds.width(), appBounds.width());
assertEquals(currentBounds.height() - notchHeight, appBounds.height());
// Task max bounds are sandboxed due to letterboxing from orientation mismatch with display.
assertTaskMaxBoundsSandboxed();
assertEquals(configBounds.width(), appBounds.width());
assertEquals(configBounds.height() - notchHeight, appBounds.height());
}
@Test
public void testFixedOrientationRotateCutoutDisplay() {
public void testFixedOrientRotateCutoutDisplay() {
// Create a display with a notch/cutout
final int notchHeight = 60;
final int width = 1000;
setUpApp(new TestDisplayContent.Builder(mAtm, width, 2500)
setUpApp(new TestDisplayContent.Builder(mAtm, 1000, 2500)
.setNotch(notchHeight).build());
// Bounds=[0, 0 - 1000, 1400], AppBounds=[0, 60 - 1000, 1460].
final float maxAspect = 1.4f;
// Bounds=[0, 0 - 1000, 1460], AppBounds=[0, 60 - 1000, 1460].
prepareUnresizable(mActivity, 1.4f /* maxAspect */, SCREEN_ORIENTATION_PORTRAIT);
final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
@@ -409,11 +370,6 @@ public class SizeCompatTests extends WindowTestsBase {
final Rect origBounds = new Rect(currentBounds);
final Rect origAppBounds = new Rect(appBounds);
// Activity is sandboxed, and bounds include the area consumed by the notch.
assertActivityMaxBoundsSandboxedForLetterbox();
assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds().height())
.isEqualTo(Math.round(width * maxAspect) + notchHeight);
// Although the activity is fixed orientation, force rotate the display.
rotateDisplay(mActivity.mDisplayContent, ROTATION_270);
assertEquals(ROTATION_270, mTask.getWindowConfiguration().getRotation());
@@ -429,13 +385,10 @@ public class SizeCompatTests extends WindowTestsBase {
// The position in configuration should be global coordinates.
assertEquals(mActivity.getBounds().left, currentBounds.left);
assertEquals(mActivity.getBounds().top, currentBounds.top);
// Activity max bounds are sandboxed due to size compat mode.
assertActivityMaxBoundsSandboxedForSizeCompat();
}
@Test
public void testFixedAspectRatioOrientationChangeOrientation() {
public void testFixedAspOrientChangeOrient() {
setUpDisplaySizeWithApp(1000, 2500);
final float maxAspect = 1.4f;
@@ -447,8 +400,6 @@ public class SizeCompatTests extends WindowTestsBase {
final Rect originalAppBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds());
assertEquals((int) (originalBounds.width() * maxAspect), originalBounds.height());
// Activity is sandboxed due to fixed aspect ratio.
assertActivityMaxBoundsSandboxedForLetterbox();
// Change the fixed orientation.
mActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
@@ -460,8 +411,6 @@ public class SizeCompatTests extends WindowTestsBase {
mActivity.getWindowConfiguration().getAppBounds().height());
assertEquals(originalAppBounds.height(),
mActivity.getWindowConfiguration().getAppBounds().width());
// Activity is sandboxed due to fixed aspect ratio.
assertActivityMaxBoundsSandboxedForLetterbox();
}
@Test
@@ -510,8 +459,6 @@ public class SizeCompatTests extends WindowTestsBase {
// restarted and the override configuration won't be cleared.
verify(mActivity, never()).restartProcessIfVisible();
assertScaled();
// Activity max bounds are sandboxed due to size compat mode, even if is not visible.
assertActivityMaxBoundsSandboxedForSizeCompat();
// Change display density
display.mBaseDisplayDensity = (int) (0.7f * display.mBaseDisplayDensity);
@@ -586,16 +533,12 @@ public class SizeCompatTests extends WindowTestsBase {
// in multi-window mode.
mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
assertFalse(activity.shouldUseSizeCompatMode());
// Activity and task should not be sandboxed.
assertMaxBoundsInheritDisplayAreaBounds();
// The non-resizable activity should not be size compat because the display support
// changing windowing mode from fullscreen to freeform.
mTask.mDisplayContent.setDisplayWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN);
assertFalse(activity.shouldUseSizeCompatMode());
// Activity and task should not be sandboxed.
assertMaxBoundsInheritDisplayAreaBounds();
}
@Test
@@ -659,9 +602,6 @@ public class SizeCompatTests extends WindowTestsBase {
// be transparent.
assertFalse(displayPolicy.isFullyTransparentAllowed(w, TYPE_STATUS_BAR));
// Activity is sandboxed.
assertActivityMaxBoundsSandboxedForLetterbox();
// Make the activity fill the display.
prepareUnresizable(mActivity, 10 /* maxAspect */, SCREEN_ORIENTATION_LANDSCAPE);
w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
@@ -671,7 +611,6 @@ public class SizeCompatTests extends WindowTestsBase {
// The letterbox should only cover the notch area, so status bar can be transparent.
assertEquals(new Rect(notchHeight, 0, 0, 0), mActivity.getLetterboxInsets());
assertTrue(displayPolicy.isFullyTransparentAllowed(w, TYPE_STATUS_BAR));
assertActivityMaxBoundsSandboxedForLetterbox();
}
@Test
@@ -696,8 +635,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertTrue(mTask.isTaskLetterboxed());
assertFalse(mActivity.inSizeCompatMode());
assertEquals(taskBounds, activityBounds);
// Activity inherits max bounds from task, since sandboxing applied to task.
assertTaskMaxBoundsSandboxed();
// Task bounds should be 700x1400 with the ratio as the display.
assertEquals(displayBounds.height(), taskBounds.height());
@@ -728,8 +665,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertScaled();
assertEquals(activityBounds.width(), newActivityBounds.width());
assertEquals(activityBounds.height(), newActivityBounds.height());
// Activity max bounds are sandboxed due to size compat mode.
assertActivityMaxBoundsSandboxedForSizeCompat();
}
@Test
@@ -741,30 +676,29 @@ public class SizeCompatTests extends WindowTestsBase {
// Portrait fixed app without max aspect.
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
Rect activityBounds = new Rect(mActivity.getBounds());
// App should launch in fullscreen.
assertFalse(mTask.isTaskLetterboxed());
assertFalse(mActivity.inSizeCompatMode());
// Activity and task inherit max bounds from TaskDisplayArea.
assertMaxBoundsInheritDisplayAreaBounds();
assertEquals(displayBounds, activityBounds);
// Rotate display to landscape.
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
final Rect rotatedDisplayBounds = new Rect(mActivity.mDisplayContent.getBounds());
final Rect rotatedActivityBounds = new Rect(mActivity.getBounds());
assertTrue(rotatedDisplayBounds.width() > rotatedDisplayBounds.height());
displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
activityBounds = new Rect(mActivity.getBounds());
assertTrue(displayBounds.width() > displayBounds.height());
// App should be in size compat.
assertFalse(mTask.isTaskLetterboxed());
assertScaled();
assertThat(mActivity.inSizeCompatMode()).isTrue();
// Activity max bounds are sandboxed due to size compat mode.
assertActivityMaxBoundsSandboxedForSizeCompat();
// App bounds should be 700x1400 with the ratio as the display.
assertEquals(rotatedDisplayBounds.height(), rotatedActivityBounds.height());
assertEquals(rotatedDisplayBounds.height() * rotatedDisplayBounds.height()
/ rotatedDisplayBounds.width(), rotatedActivityBounds.width());
assertEquals(displayBounds.height(), activityBounds.height());
assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
activityBounds.width());
}
@Test
@@ -797,17 +731,14 @@ public class SizeCompatTests extends WindowTestsBase {
final Rect displayBounds = new Rect(display.getBounds());
final Rect taskBounds = new Rect(mTask.getBounds());
final Rect newActivityBounds = new Rect(newActivity.getBounds());
final float displayAspectRatio = (float) displayBounds.height() / displayBounds.width();
// 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());
assertThat(taskBounds.width())
.isEqualTo(Math.round(displayBounds.height() * displayAspectRatio));
// Task max bounds are sandboxed due to letterbox, with the ratio of the display.
assertTaskMaxBoundsSandboxed();
assertEquals(displayBounds.height() * displayBounds.height() / displayBounds.width(),
taskBounds.width());
}
@Test
@@ -847,14 +778,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(displayBounds.height(), taskBounds.height());
assertEquals((long) Math.rint(taskBounds.height() / newActivity.info.maxAspectRatio),
taskBounds.width());
// New activity max bounds are sandboxed due to letterbox.
assertThat(newActivity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(taskBounds);
// Task max bounds are sandboxed due to letterbox, with the ratio of the display.
assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds().height())
.isEqualTo(displayBounds.height());
assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds().width())
.isEqualTo(Math.round(displayBounds.height() / newActivity.info.maxAspectRatio));
// App bounds should be fullscreen in Task bounds.
assertFalse(newActivity.inSizeCompatMode());
@@ -883,9 +806,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertFalse(mTask.isTaskLetterboxed());
assertScaled();
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
assertThat(mActivity.inSizeCompatMode()).isTrue();
// Activity max bounds are sandboxed due to size compat mode.
assertActivityMaxBoundsSandboxedForSizeCompat();
final Rect activityBounds = new Rect(mActivity.getBounds());
mTask.resumeTopActivityUncheckedLocked(null /* prev */, null /* options */);
@@ -896,8 +816,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertScaled();
assertEquals(mTask.getLastTaskBoundsComputeActivity(), mActivity);
assertEquals(activityBounds, mActivity.getBounds());
// Activity max bounds are sandboxed due to size compat.
assertActivityMaxBoundsSandboxedForSizeCompat();
}
@Test
@@ -913,7 +831,6 @@ public class SizeCompatTests extends WindowTestsBase {
// In Task letterbox
assertTrue(mTask.isTaskLetterboxed());
assertFalse(mActivity.inSizeCompatMode());
assertTaskMaxBoundsSandboxed();
// Rotate display to portrait.
rotateDisplay(display, ROTATION_90);
@@ -921,7 +838,6 @@ public class SizeCompatTests extends WindowTestsBase {
// App should be in size compat.
assertFalse(mTask.isTaskLetterboxed());
assertScaled();
assertActivityMaxBoundsSandboxedForSizeCompat();
// Rotate display to landscape.
rotateDisplay(display, ROTATION_180);
@@ -929,7 +845,6 @@ public class SizeCompatTests extends WindowTestsBase {
// In Task letterbox
assertTrue(mTask.isTaskLetterboxed());
assertFalse(mActivity.inSizeCompatMode());
assertTaskMaxBoundsSandboxed();
}
@Test
@@ -947,26 +862,20 @@ public class SizeCompatTests extends WindowTestsBase {
// In Task letterbox
assertTrue(mTask.isTaskLetterboxed());
assertFalse(mActivity.inSizeCompatMode());
// Task is letterboxed due to mismatched orientation request.
assertTaskMaxBoundsSandboxed();
// Rotate display to landscape.
// Rotate display to portrait.
rotateDisplay(display, ROTATION_90);
// App should be in size compat.
assertFalse(mTask.isTaskLetterboxed());
assertScaled();
// Activity max bounds are sandboxed due to unresizable app.
assertActivityMaxBoundsSandboxedForSizeCompat();
// Rotate display to portrait.
// Rotate display to landscape.
rotateDisplay(display, ROTATION_180);
// In Task letterbox
assertTrue(mTask.isTaskLetterboxed());
assertFalse(mActivity.inSizeCompatMode());
// Task is letterboxed, as in first case.
assertTaskMaxBoundsSandboxed();
}
@Test
@@ -983,18 +892,12 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(ORIENTATION_LANDSCAPE, display.getConfiguration().orientation);
assertEquals(2800, displayBounds.width());
assertEquals(1400, displayBounds.height());
Rect displayAreaBounds = new Rect(0, 0, 2400, 1000);
taskDisplayArea.setBounds(displayAreaBounds);
taskDisplayArea.setBounds(0, 0, 2400, 1000);
final Rect activityBounds = new Rect(mActivity.getBounds());
assertFalse(mActivity.inSizeCompatMode());
assertEquals(2400, activityBounds.width());
assertEquals(1000, activityBounds.height());
// Task and activity maximum bounds inherit from TaskDisplayArea bounds.
assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(displayAreaBounds);
assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(displayAreaBounds);
}
@Test
@@ -1142,48 +1045,6 @@ public class SizeCompatTests extends WindowTestsBase {
assertFalse(mActivity.hasSizeCompatBounds());
}
/** Asserts both the activity and task max bounds inherit from the TaskDisplayArea. */
private void assertMaxBoundsInheritDisplayAreaBounds() {
final Rect taskDisplayAreaBounds = mTask.getDisplayArea().getBounds();
assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(taskDisplayAreaBounds);
assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(taskDisplayAreaBounds);
}
/**
* Asserts task-level letterboxing, so both activity and task max bounds
* are sandboxed to the letterbox bounds.
*/
private void assertTaskMaxBoundsSandboxed() {
// Activity inherits max bounds from task, since sandboxing applied to task.
assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(mTask.getBounds());
// Task max bounds are sandboxed due to letterbox.
assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(mTask.getBounds());
}
/** Asserts activity-level size compat mode, so only activity max bounds are sandboxed. */
private void assertActivityMaxBoundsSandboxedForSizeCompat() {
// Activity max bounds are sandboxed due to size compat mode.
assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(mActivity.getWindowConfiguration().getBounds());
// Task inherits max bounds from display.
assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(mTask.getDisplayContent().getBounds());
}
/** Asserts activity-level letterboxing, so only activity max bounds are sandboxed. */
private void assertActivityMaxBoundsSandboxedForLetterbox() {
// Activity is sandboxed due to fixed aspect ratio.
assertThat(mActivity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(mActivity.getBounds());
// Task inherits bounds from display.
assertThat(mTask.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(mTask.getDisplayContent().getBounds());
}
static Configuration rotateDisplay(DisplayContent display, int rotation) {
final Configuration c = new Configuration();
display.getDisplayRotation().setRotation(rotation);

View File

@@ -136,11 +136,6 @@ class TestDisplayContent extends DisplayContent {
final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
mInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
final TestDisplayContent newDisplay = createInternal(display);
// Ensure letterbox aspect ratio is not overridden on any device target.
// {@link com.android.internal.R.dimen.config_taskLetterboxAspectRatio}, provided by
// the below method, is set on some device form factors.
mService.mWindowManager.setTaskLetterboxAspectRatio(0);
// disable the normal system decorations
final DisplayPolicy displayPolicy = newDisplay.getDisplayPolicy();
spyOn(displayPolicy);