Loading services/core/java/com/android/server/wm/AppCompatDisplayCompatModePolicy.java +11 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,9 @@ class AppCompatDisplayCompatModePolicy { @NonNull private final ActivityRecord mActivityRecord; /** * {@code true} if the activity has moved to a different display and has not been restarted yet. */ private boolean mDisplayChangedWithoutRestart; AppCompatDisplayCompatModePolicy(@NonNull ActivityRecord activityRecord) { Loading Loading @@ -107,6 +110,14 @@ class AppCompatDisplayCompatModePolicy { } } /** * Returns {@code true} if the activity has moved to a different display and has not been * restarted yet. */ boolean getDisplayChangedWithoutRestart() { return mDisplayChangedWithoutRestart; } /** * Called when the activity's process is restarted. */ Loading services/core/java/com/android/server/wm/AppCompatDisplayInsets.java +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static com.android.server.wm.AppCompatUtils.computeAspectRatio; import static com.android.server.wm.AppCompatUtils.isInDesktopMode; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -64,6 +65,11 @@ class AppCompatDisplayInsets { * {@link Configuration#screenHeightDp}. */ final Rect[] mStableInsets = new Rect[4]; /** * Whether the activity was originally launched in desktop mode or not. Used for the heuristic * to determine whether the app should be upscaled or not. */ final boolean mInDesktopMode; /** Constructs the environment to simulate the bounds behavior of the given container. */ AppCompatDisplayInsets(@NonNull DisplayContent display, @NonNull ActivityRecord container, Loading @@ -71,6 +77,8 @@ class AppCompatDisplayInsets { mOriginalRotation = display.getRotation(); mIsFloating = container.getWindowConfiguration().tasksAreFloating(); mOriginalRequestedOrientation = container.getRequestedConfigurationOrientation(); mInDesktopMode = isInDesktopMode(container.mAtmService.mContext, container.getWindowConfiguration().getWindowingMode()); if (mIsFloating) { final Rect containerBounds = container.getWindowConfiguration().getBounds(); mWidth = containerBounds.width(); Loading services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java +38 −4 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.internal.perfetto.protos.Windowmanagerservice.ActivityRecordProto.IN_SIZE_COMPAT_MODE; import static android.window.DesktopExperienceFlags.ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS; import static android.window.DesktopExperienceFlags.ENABLE_UPSCALING_SIZE_COMPAT_ON_EXITING_DESKTOP_BUGFIX; import static com.android.server.wm.AppCompatUtils.isInDesktopMode; Loading @@ -33,6 +34,7 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.util.proto.ProtoOutputStream; import android.view.Display; import java.io.PrintWriter; import java.util.function.DoubleSupplier; Loading Loading @@ -572,12 +574,44 @@ class AppCompatSizeCompatModePolicy { final int contentH = resolvedAppBounds.height(); final int viewportW = containerAppBounds.width(); final int viewportH = containerAppBounds.height(); // Allow an application to be up-scaled if its window is smaller than its // original container or if it's a freeform window in desktop mode. boolean shouldAllowUpscaling = !(contentW <= viewportW && contentH <= viewportH) || isInDesktopMode(mActivityRecord.mAtmService.mContext, final boolean isInDesktopMode = isInDesktopMode(mActivityRecord.mAtmService.mContext, newParentConfig.windowConfiguration.getWindowingMode()); // Allow an application to be up-scaled if its window is smaller than its // original container, if it's a freeform window in desktop mode, or if display or windowing // mode has changed in some special conditions. final boolean shouldAllowUpscaling = !(contentW <= viewportW && contentH <= viewportH) || isInDesktopMode || shouldAllowUpscalingForDisplayOrWindowingModeChange(isInDesktopMode); return shouldAllowUpscaling ? Math.min( (float) viewportW / contentW, (float) viewportH / contentH) : 1f; } /** * Returns whether the activity should be upscaled due to a change in display or windowing * mode. Upscaling is generally disabled in fullscreen to avoid pixelation etc. However, it is * enabled in specific scenarios to prevent the app from becoming too small in a parent window, * such as when: * - Moving from an external display to a smaller phone screen. * - Transitioning from desktop mode to fullscreen. * This treatment is not applied to internal displays that ignore orientation requests to * maintain consistent scaling behavior with orientation changes on those displays. */ private boolean shouldAllowUpscalingForDisplayOrWindowingModeChange(boolean isInDesktopMode) { final boolean launchedInAndExitedFromDesktop = getAppCompatDisplayInsets() != null && getAppCompatDisplayInsets().mInDesktopMode && !isInDesktopMode; final boolean hasMovedBetweenDisplays = mActivityRecord.mAppCompatController .getDisplayCompatModePolicy().getDisplayChangedWithoutRestart(); final boolean isOnIgnoreOrientationRequestInternalDisplay = isOnInternalDisplay() && mActivityRecord.getDisplayContent().getIgnoreOrientationRequest(); // TODO(b/432329483): Polish the policy for desktop-first devices. return ENABLE_UPSCALING_SIZE_COMPAT_ON_EXITING_DESKTOP_BUGFIX.isTrue() && (launchedInAndExitedFromDesktop || hasMovedBetweenDisplays) && !isOnIgnoreOrientationRequestInternalDisplay; } /** Returns whether the activity is on an internal display. */ private boolean isOnInternalDisplay() { return mActivityRecord.getDisplayContent().getDisplay().getType() == Display.TYPE_INTERNAL; } } services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +58 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCRE import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.TYPE_EXTERNAL; import static android.view.Display.TYPE_INTERNAL; import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; Loading Loading @@ -67,7 +70,6 @@ import static com.android.server.wm.ActivityRecord.State.STOPPED; import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_POSITION_MULTIPLIER_CENTER; import static com.android.server.wm.AppCompatUtils.computeAspectRatio; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.window.flags.Flags.FLAG_ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -564,7 +566,7 @@ public class SizeCompatTests extends WindowTestsBase { assertDownScaled(); } @EnableFlags(FLAG_ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS) @EnableFlags(Flags.FLAG_ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS) @Test public void testFixedMiscConfigurationWhenMovingToDisplay() { setUpDisplaySizeWithApp(1000, 2500); Loading Loading @@ -4594,6 +4596,60 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(notchHeight, appBounds.top - bounds.top); } @Test @EnableFlags(Flags.FLAG_ENABLE_UPSCALING_SIZE_COMPAT_ON_EXITING_DESKTOP_BUGFIX) public void testUpscaling_boundsUpscaledWithWindowingModeChange() { allowDesktopMode(); // Launch an SCM app in freeform on an external display. final int dw = 2000; final int dh = 1600; final DisplayInfo displayInfo = new DisplayInfo(); displayInfo.copyFrom(mDisplayInfo); displayInfo.type = TYPE_EXTERNAL; displayInfo.displayId = DEFAULT_DISPLAY + 1; displayInfo.logicalWidth = dw; displayInfo.logicalHeight = dh; final DisplayContent display = new TestDisplayContent.Builder(mAtm, displayInfo).build(); display.getDefaultTaskDisplayArea() .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); final TaskBuilder taskBuilder = new TaskBuilder(mSupervisor).setWindowingMode(WINDOWING_MODE_FREEFORM); setUpApp(display, null /* appBuilder */, taskBuilder); Rect bounds = new Rect(0, 0, 600, 800); mTask.setBounds(bounds); mTask.onConfigurationChanged(mTask.getDisplayArea().getConfiguration()); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM, mTask.getWindowingMode()); assertFitted(); // Exit freeform into fullscreen. display.getDefaultTaskDisplayArea() .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN); mTask.setBounds(null); mActivity.onConfigurationChanged(mTask.getConfiguration()); assertUpScaled(); // Move to a fullscreen, ignore-orientation-request, internal display. final DisplayInfo internalDisplayInfo = new DisplayInfo(); internalDisplayInfo.copyFrom(display.getDisplayInfo()); internalDisplayInfo.type = TYPE_INTERNAL; internalDisplayInfo.displayId = display.getDisplayInfo().displayId + 1; final DisplayContent internalDisplay = new TestDisplayContent.Builder(mAtm, internalDisplayInfo).build(); mTask.mWmService.mRoot.moveRootTaskToDisplay(mTask.mTaskId, internalDisplay.mDisplayId, true /* onTop */); internalDisplay.setIgnoreOrientationRequest(true); mActivity.onConfigurationChanged(mTask.getConfiguration()); assertTrue(mActivity.inSizeCompatMode()); assertEquals(1f, mActivity.getCompatScale(), 1e7); // Make the display not ignore-orientation-request. internalDisplay.setIgnoreOrientationRequest(false); mActivity.onConfigurationChanged(mTask.getConfiguration()); assertUpScaled(); } @Test @EnableFlags(Flags.FLAG_IGNORE_ASPECT_RATIO_RESTRICTIONS_FOR_RESIZEABLE_FREEFORM_ACTIVITIES) Loading Loading
services/core/java/com/android/server/wm/AppCompatDisplayCompatModePolicy.java +11 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,9 @@ class AppCompatDisplayCompatModePolicy { @NonNull private final ActivityRecord mActivityRecord; /** * {@code true} if the activity has moved to a different display and has not been restarted yet. */ private boolean mDisplayChangedWithoutRestart; AppCompatDisplayCompatModePolicy(@NonNull ActivityRecord activityRecord) { Loading Loading @@ -107,6 +110,14 @@ class AppCompatDisplayCompatModePolicy { } } /** * Returns {@code true} if the activity has moved to a different display and has not been * restarted yet. */ boolean getDisplayChangedWithoutRestart() { return mDisplayChangedWithoutRestart; } /** * Called when the activity's process is restarted. */ Loading
services/core/java/com/android/server/wm/AppCompatDisplayInsets.java +8 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static com.android.server.wm.AppCompatUtils.computeAspectRatio; import static com.android.server.wm.AppCompatUtils.isInDesktopMode; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -64,6 +65,11 @@ class AppCompatDisplayInsets { * {@link Configuration#screenHeightDp}. */ final Rect[] mStableInsets = new Rect[4]; /** * Whether the activity was originally launched in desktop mode or not. Used for the heuristic * to determine whether the app should be upscaled or not. */ final boolean mInDesktopMode; /** Constructs the environment to simulate the bounds behavior of the given container. */ AppCompatDisplayInsets(@NonNull DisplayContent display, @NonNull ActivityRecord container, Loading @@ -71,6 +77,8 @@ class AppCompatDisplayInsets { mOriginalRotation = display.getRotation(); mIsFloating = container.getWindowConfiguration().tasksAreFloating(); mOriginalRequestedOrientation = container.getRequestedConfigurationOrientation(); mInDesktopMode = isInDesktopMode(container.mAtmService.mContext, container.getWindowConfiguration().getWindowingMode()); if (mIsFloating) { final Rect containerBounds = container.getWindowConfiguration().getBounds(); mWidth = containerBounds.width(); Loading
services/core/java/com/android/server/wm/AppCompatSizeCompatModePolicy.java +38 −4 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.SIZE_CHANGES_UNSUPPORTED_OVERRIDE; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.internal.perfetto.protos.Windowmanagerservice.ActivityRecordProto.IN_SIZE_COMPAT_MODE; import static android.window.DesktopExperienceFlags.ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS; import static android.window.DesktopExperienceFlags.ENABLE_UPSCALING_SIZE_COMPAT_ON_EXITING_DESKTOP_BUGFIX; import static com.android.server.wm.AppCompatUtils.isInDesktopMode; Loading @@ -33,6 +34,7 @@ import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.util.proto.ProtoOutputStream; import android.view.Display; import java.io.PrintWriter; import java.util.function.DoubleSupplier; Loading Loading @@ -572,12 +574,44 @@ class AppCompatSizeCompatModePolicy { final int contentH = resolvedAppBounds.height(); final int viewportW = containerAppBounds.width(); final int viewportH = containerAppBounds.height(); // Allow an application to be up-scaled if its window is smaller than its // original container or if it's a freeform window in desktop mode. boolean shouldAllowUpscaling = !(contentW <= viewportW && contentH <= viewportH) || isInDesktopMode(mActivityRecord.mAtmService.mContext, final boolean isInDesktopMode = isInDesktopMode(mActivityRecord.mAtmService.mContext, newParentConfig.windowConfiguration.getWindowingMode()); // Allow an application to be up-scaled if its window is smaller than its // original container, if it's a freeform window in desktop mode, or if display or windowing // mode has changed in some special conditions. final boolean shouldAllowUpscaling = !(contentW <= viewportW && contentH <= viewportH) || isInDesktopMode || shouldAllowUpscalingForDisplayOrWindowingModeChange(isInDesktopMode); return shouldAllowUpscaling ? Math.min( (float) viewportW / contentW, (float) viewportH / contentH) : 1f; } /** * Returns whether the activity should be upscaled due to a change in display or windowing * mode. Upscaling is generally disabled in fullscreen to avoid pixelation etc. However, it is * enabled in specific scenarios to prevent the app from becoming too small in a parent window, * such as when: * - Moving from an external display to a smaller phone screen. * - Transitioning from desktop mode to fullscreen. * This treatment is not applied to internal displays that ignore orientation requests to * maintain consistent scaling behavior with orientation changes on those displays. */ private boolean shouldAllowUpscalingForDisplayOrWindowingModeChange(boolean isInDesktopMode) { final boolean launchedInAndExitedFromDesktop = getAppCompatDisplayInsets() != null && getAppCompatDisplayInsets().mInDesktopMode && !isInDesktopMode; final boolean hasMovedBetweenDisplays = mActivityRecord.mAppCompatController .getDisplayCompatModePolicy().getDisplayChangedWithoutRestart(); final boolean isOnIgnoreOrientationRequestInternalDisplay = isOnInternalDisplay() && mActivityRecord.getDisplayContent().getIgnoreOrientationRequest(); // TODO(b/432329483): Polish the policy for desktop-first devices. return ENABLE_UPSCALING_SIZE_COMPAT_ON_EXITING_DESKTOP_BUGFIX.isTrue() && (launchedInAndExitedFromDesktop || hasMovedBetweenDisplays) && !isOnIgnoreOrientationRequestInternalDisplay; } /** Returns whether the activity is on an internal display. */ private boolean isOnInternalDisplay() { return mActivityRecord.getDisplayContent().getDisplay().getType() == Display.TYPE_INTERNAL; } }
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +58 −2 Original line number Diff line number Diff line Loading @@ -34,6 +34,9 @@ import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_SPLIT_SCRE import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.TYPE_EXTERNAL; import static android.view.Display.TYPE_INTERNAL; import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; Loading Loading @@ -67,7 +70,6 @@ import static com.android.server.wm.ActivityRecord.State.STOPPED; import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_POSITION_MULTIPLIER_CENTER; import static com.android.server.wm.AppCompatUtils.computeAspectRatio; import static com.android.server.wm.WindowContainer.POSITION_TOP; import static com.android.window.flags.Flags.FLAG_ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS; import static com.google.common.truth.Truth.assertThat; Loading Loading @@ -564,7 +566,7 @@ public class SizeCompatTests extends WindowTestsBase { assertDownScaled(); } @EnableFlags(FLAG_ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS) @EnableFlags(Flags.FLAG_ENABLE_SIZE_COMPAT_MODE_IMPROVEMENTS_FOR_CONNECTED_DISPLAYS) @Test public void testFixedMiscConfigurationWhenMovingToDisplay() { setUpDisplaySizeWithApp(1000, 2500); Loading Loading @@ -4594,6 +4596,60 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(notchHeight, appBounds.top - bounds.top); } @Test @EnableFlags(Flags.FLAG_ENABLE_UPSCALING_SIZE_COMPAT_ON_EXITING_DESKTOP_BUGFIX) public void testUpscaling_boundsUpscaledWithWindowingModeChange() { allowDesktopMode(); // Launch an SCM app in freeform on an external display. final int dw = 2000; final int dh = 1600; final DisplayInfo displayInfo = new DisplayInfo(); displayInfo.copyFrom(mDisplayInfo); displayInfo.type = TYPE_EXTERNAL; displayInfo.displayId = DEFAULT_DISPLAY + 1; displayInfo.logicalWidth = dw; displayInfo.logicalHeight = dh; final DisplayContent display = new TestDisplayContent.Builder(mAtm, displayInfo).build(); display.getDefaultTaskDisplayArea() .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); final TaskBuilder taskBuilder = new TaskBuilder(mSupervisor).setWindowingMode(WINDOWING_MODE_FREEFORM); setUpApp(display, null /* appBuilder */, taskBuilder); Rect bounds = new Rect(0, 0, 600, 800); mTask.setBounds(bounds); mTask.onConfigurationChanged(mTask.getDisplayArea().getConfiguration()); prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM, mTask.getWindowingMode()); assertFitted(); // Exit freeform into fullscreen. display.getDefaultTaskDisplayArea() .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN); mTask.setBounds(null); mActivity.onConfigurationChanged(mTask.getConfiguration()); assertUpScaled(); // Move to a fullscreen, ignore-orientation-request, internal display. final DisplayInfo internalDisplayInfo = new DisplayInfo(); internalDisplayInfo.copyFrom(display.getDisplayInfo()); internalDisplayInfo.type = TYPE_INTERNAL; internalDisplayInfo.displayId = display.getDisplayInfo().displayId + 1; final DisplayContent internalDisplay = new TestDisplayContent.Builder(mAtm, internalDisplayInfo).build(); mTask.mWmService.mRoot.moveRootTaskToDisplay(mTask.mTaskId, internalDisplay.mDisplayId, true /* onTop */); internalDisplay.setIgnoreOrientationRequest(true); mActivity.onConfigurationChanged(mTask.getConfiguration()); assertTrue(mActivity.inSizeCompatMode()); assertEquals(1f, mActivity.getCompatScale(), 1e7); // Make the display not ignore-orientation-request. internalDisplay.setIgnoreOrientationRequest(false); mActivity.onConfigurationChanged(mTask.getConfiguration()); assertUpScaled(); } @Test @EnableFlags(Flags.FLAG_IGNORE_ASPECT_RATIO_RESTRICTIONS_FOR_RESIZEABLE_FREEFORM_ACTIVITIES) Loading