Remove aspect ratio limit for unresizable apps.

We recently merged I750b8fd464b041f16bf18c3bdbfb1a28a2132902 to ensure CDD requirement 7.1.1.2 that was removed shortly after changes were landed. This change:
- Removes default aspect ratio limitation from the framework
- Allows to set different aspect ratio limitations for apps that eligible or not for a size compat mode.
- Fixes a bug in split screen aspect ratio logic that wrongly applied split divider insets twice.

Fix: 236165529
Test: atest WmTests:SizeCompatTests
Change-Id: I9251e7f34f108f5bed420e5b1949d081f25a0d72
This commit is contained in:
Mariia Sandrikova
2022-06-15 22:31:52 +00:00
parent cebc8fc6b8
commit 7cae7c6a36
7 changed files with 55 additions and 68 deletions

View File

@@ -5180,11 +5180,11 @@
<!-- Whether displaying letterbox education is enabled for letterboxed fullscreen apps. -->
<bool name="config_letterboxIsEducationEnabled">false</bool>
<!-- Default min aspect ratio for unresizable apps which is used when an app doesn't specify
android:minAspectRatio in accordance with CDD 7.1.1.2 requirement:
https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio.
An exception will be thrown if the given aspect ratio < 4:3. -->
<item name="config_letterboxDefaultMinAspectRatioForUnresizableApps" format="float" type="dimen">1.5</item>
<!-- Default min aspect ratio for unresizable apps which are eligible for size compat mode.
Values <= 1.0 will be ignored. Activity min/max aspect ratio restrictions will still be
espected so this override can control the maximum screen area that can be occupied by
the app in the letterbox mode. -->
<item name="config_letterboxDefaultMinAspectRatioForUnresizableApps" format="float" type="dimen">0.0</item>
<!-- Whether using split screen aspect ratio as a default aspect ratio for unresizable apps. -->
<bool name="config_letterboxIsSplitScreenAspectRatioForUnresizableAppsEnabled">false</bool>

View File

@@ -8168,7 +8168,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolvedBounds.set(containingBounds);
final float letterboxAspectRatioOverride =
mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
mLetterboxUiController.getFixedOrientationLetterboxAspectRatio();
final float desiredAspectRatio =
letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
? letterboxAspectRatioOverride : computeAspectRatio(parentBounds);
@@ -8721,18 +8721,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* Returns the min aspect ratio of this activity.
*/
private float getMinAspectRatio() {
float infoAspectRatio = info.getMinAspectRatio(getRequestedOrientation());
// Complying with the CDD 7.1.1.2 requirement for unresizble apps:
// https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio
return infoAspectRatio < 1f && info.resizeMode == RESIZE_MODE_UNRESIZEABLE
// TODO(233582832): Consider removing fixed-orientation condition.
// Some apps switching from tablet to phone layout at the certain size
// threshold. This may lead to flickering on tablets in landscape orientation
// if an app sets orientation to portrait dynamically because of aspect ratio
// restriction applied here.
&& getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED
? mLetterboxUiController.getDefaultMinAspectRatioForUnresizableApps()
: infoAspectRatio;
return info.getMinAspectRatio(getRequestedOrientation());
}
/**

View File

@@ -37,11 +37,6 @@ final class LetterboxConfiguration {
*/
static final float MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO = 1.0f;
// Min allowed aspect ratio for unresizable apps which is used when an app doesn't specify
// android:minAspectRatio in accordance with the CDD 7.1.1.2 requirement:
// https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio
static final float MIN_UNRESIZABLE_ASPECT_RATIO = 4 / 3f;
/** Enum for Letterbox background type. */
@Retention(RetentionPolicy.SOURCE)
@IntDef({LETTERBOX_BACKGROUND_SOLID_COLOR, LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND,
@@ -109,9 +104,7 @@ final class LetterboxConfiguration {
// MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO will be ignored.
private float mFixedOrientationLetterboxAspectRatio;
// Default min aspect ratio for unresizable apps which is used when an app doesn't specify
// android:minAspectRatio in accordance with the CDD 7.1.1.2 requirement:
// https://source.android.com/compatibility/12/android-12-cdd#7112_screen_aspect_ratio
// Default min aspect ratio for unresizable apps that are eligible for the size compat mode.
private float mDefaultMinAspectRatioForUnresizableApps;
// Corners radius for activities presented in the letterbox mode, values < 0 will be ignored.
@@ -250,13 +243,7 @@ final class LetterboxConfiguration {
}
/**
* Resets the min aspect ratio for unresizable apps which is used when an app doesn't specify
* {@code android:minAspectRatio} to {@link
* R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps}.
*
* @throws AssertionError if {@link
* R.dimen.config_letterboxDefaultMinAspectRatioForUnresizableApps} is < {@link
* #MIN_UNRESIZABLE_ASPECT_RATIO}.
* Resets the min aspect ratio for unresizable apps that are eligible for size compat mode.
*/
void resetDefaultMinAspectRatioForUnresizableApps() {
setDefaultMinAspectRatioForUnresizableApps(mContext.getResources().getFloat(
@@ -264,25 +251,16 @@ final class LetterboxConfiguration {
}
/**
* Gets the min aspect ratio for unresizable apps which is used when an app doesn't specify
* {@code android:minAspectRatio}.
* Gets the min aspect ratio for unresizable apps that are eligible for size compat mode.
*/
float getDefaultMinAspectRatioForUnresizableApps() {
return mDefaultMinAspectRatioForUnresizableApps;
}
/**
* Overrides the min aspect ratio for unresizable apps which is used when an app doesn't
* specify {@code android:minAspectRatio}.
*
* @throws AssertionError if given value is < {@link #MIN_UNRESIZABLE_ASPECT_RATIO}.
* Overrides the min aspect ratio for unresizable apps that are eligible for size compat mode.
*/
void setDefaultMinAspectRatioForUnresizableApps(float aspectRatio) {
if (aspectRatio < MIN_UNRESIZABLE_ASPECT_RATIO) {
throw new AssertionError(
"Unexpected min aspect ratio for unresizable apps, it should be <= "
+ MIN_UNRESIZABLE_ASPECT_RATIO + " but was " + aspectRatio);
}
mDefaultMinAspectRatioForUnresizableApps = aspectRatio;
}

View File

@@ -28,6 +28,7 @@ import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_APP_COLOR_BACKGROUND_FLOATING;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_SOLID_COLOR;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_BACKGROUND_WALLPAPER;
import static com.android.server.wm.LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO;
import static com.android.server.wm.LetterboxConfiguration.letterboxBackgroundTypeToString;
import android.annotation.Nullable;
@@ -211,10 +212,19 @@ final class LetterboxUiController {
: mLetterboxConfiguration.getLetterboxVerticalPositionMultiplier();
}
float getDefaultMinAspectRatioForUnresizableApps() {
float getFixedOrientationLetterboxAspectRatio() {
return mActivityRecord.shouldCreateCompatDisplayInsets()
? getDefaultMinAspectRatioForUnresizableApps()
: mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
}
private float getDefaultMinAspectRatioForUnresizableApps() {
if (!mLetterboxConfiguration.getIsSplitScreenAspectRatioForUnresizableAppsEnabled()
|| mActivityRecord.getDisplayContent() == null) {
return mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps();
return mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps()
> MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
? mLetterboxConfiguration.getDefaultMinAspectRatioForUnresizableApps()
: mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
}
int dividerWindowWidth =
@@ -226,10 +236,10 @@ final class LetterboxUiController {
// Getting the same aspect ratio that apps get in split screen.
Rect bounds = new Rect(mActivityRecord.getDisplayContent().getBounds());
if (bounds.width() >= bounds.height()) {
bounds.inset(/* dx */ dividerSize, /* dy */ 0);
bounds.inset(/* dx */ dividerSize / 2, /* dy */ 0);
bounds.right = bounds.centerX();
} else {
bounds.inset(/* dx */ 0, /* dy */ dividerSize);
bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2);
bounds.bottom = bounds.centerY();
}
return computeAspectRatio(bounds);

View File

@@ -1370,9 +1370,10 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" be ignored and framework implementation will determine aspect ratio.");
pw.println(" --minAspectRatioForUnresizable aspectRatio");
pw.println(" Default min aspect ratio for unresizable apps which is used when an");
pw.println(" app doesn't specify android:minAspectRatio. An exception will be");
pw.println(" thrown if aspectRatio < "
+ LetterboxConfiguration.MIN_UNRESIZABLE_ASPECT_RATIO);
pw.println(" app is eligible for the size compat mode. If aspectRatio <= "
+ LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO);
pw.println(" both it and R.dimen.config_fixedOrientationLetterboxAspectRatio will");
pw.println(" be ignored and framework implementation will determine aspect ratio.");
pw.println(" --cornerRadius radius");
pw.println(" Corners radius for activities in the letterbox mode. If radius < 0,");
pw.println(" both it and R.integer.config_letterboxActivityCornersRadius will be");

View File

@@ -39,7 +39,6 @@ import static com.android.server.wm.SizeCompatTests.rotateDisplay;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -211,10 +210,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
assertThat(activityConfigBounds.width()).isEqualTo(activityBounds.width());
assertThat(activityConfigBounds.height()).isEqualTo(activityBounds.height());
assertThat(activitySizeCompatBounds.height()).isEqualTo(newTaskBounds.height());
final float defaultAspectRatio = mFirstActivity.mWmService.mLetterboxConfiguration
.getDefaultMinAspectRatioForUnresizableApps();
assertEquals(activitySizeCompatBounds.width(),
newTaskBounds.height() / defaultAspectRatio, 0.5);
assertThat(activitySizeCompatBounds.width()).isEqualTo(
newTaskBounds.height() * newTaskBounds.height() / newTaskBounds.width());
}
@Test
@@ -234,9 +231,8 @@ public class DualDisplayAreaGroupPolicyTest extends WindowTestsBase {
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
assertThat(taskBounds).isEqualTo(dagBounds);
assertThat(activityBounds.width()).isEqualTo(dagBounds.width());
final float defaultAspectRatio = mFirstActivity.mWmService.mLetterboxConfiguration
.getDefaultMinAspectRatioForUnresizableApps();
assertEquals(activityBounds.height(), dagBounds.width() / defaultAspectRatio, 0.5);
assertThat(activityBounds.height())
.isEqualTo(dagBounds.width() * dagBounds.width() / dagBounds.height());
}
@Test

View File

@@ -1471,6 +1471,8 @@ public class SizeCompatTests extends WindowTestsBase {
final float fixedOrientationLetterboxAspectRatio = 1.1f;
mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(
fixedOrientationLetterboxAspectRatio);
mActivity.mWmService.mLetterboxConfiguration.setDefaultMinAspectRatioForUnresizableApps(
1.5f);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
final Rect displayBounds = new Rect(mActivity.mDisplayContent.getBounds());
@@ -1496,7 +1498,9 @@ public class SizeCompatTests extends WindowTestsBase {
@Test
public void testSplitAspectRatioForUnresizablePortraitApps() {
// Set up a display in landscape and ignoring orientation request.
setUpDisplaySizeWithApp(1600, 1400);
int screenWidth = 1600;
int screenHeight = 1400;
setUpDisplaySizeWithApp(screenWidth, screenHeight);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mActivity.mWmService.mLetterboxConfiguration
.setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);
@@ -1520,6 +1524,7 @@ public class SizeCompatTests extends WindowTestsBase {
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
organizer.mPrimary.setBounds(0, 0, getExpectedSplitSize(screenWidth), screenHeight);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Checking that there is no size compat mode.
@@ -1528,8 +1533,10 @@ public class SizeCompatTests extends WindowTestsBase {
@Test
public void testSplitAspectRatioForUnresizableLandscapeApps() {
// Set up a display in landscape and ignoring orientation request.
setUpDisplaySizeWithApp(1400, 1600);
// Set up a display in portrait and ignoring orientation request.
int screenWidth = 1400;
int screenHeight = 1600;
setUpDisplaySizeWithApp(screenWidth, screenHeight);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mActivity.mWmService.mLetterboxConfiguration
.setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);
@@ -1553,6 +1560,7 @@ public class SizeCompatTests extends WindowTestsBase {
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// Checking that there is no size compat mode.
@@ -2071,12 +2079,7 @@ public class SizeCompatTests extends WindowTestsBase {
// Activity bounds fill split screen.
final Rect primarySplitBounds = new Rect(organizer.mPrimary.getBounds());
final Rect letterboxedBounds = new Rect(mActivity.getBounds());
// Activity is letterboxed for aspect ratio.
assertEquals(primarySplitBounds.height(), letterboxedBounds.height());
final float defaultAspectRatio = mActivity.mWmService.mLetterboxConfiguration
.getDefaultMinAspectRatioForUnresizableApps();
assertEquals(primarySplitBounds.height() / defaultAspectRatio,
letterboxedBounds.width(), 0.5);
assertEquals(primarySplitBounds, letterboxedBounds);
}
@Test
@@ -2618,6 +2621,16 @@ public class SizeCompatTests extends WindowTestsBase {
assertEquals(newDensity, mActivity.getConfiguration().densityDpi);
}
private int getExpectedSplitSize(int dimensionToSplit) {
int dividerWindowWidth =
mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_thickness);
int dividerInsets =
mActivity.mWmService.mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.docked_stack_divider_insets);
return (dimensionToSplit - (dividerWindowWidth - dividerInsets * 2)) / 2;
}
private void assertHorizontalPositionForDifferentDisplayConfigsForLandscapeActivity(
float letterboxHorizontalPositionMultiplier) {
// Set up a display in landscape and ignoring orientation request.