diff options
| author | 2024-03-14 12:04:59 +0000 | |
|---|---|---|
| committer | 2024-03-14 12:04:59 +0000 | |
| commit | e4fdb75f3f16e7c5757760a7446e30c82bc57c67 (patch) | |
| tree | 97c6dedc38bea04280800b637764d881cc5628a8 | |
| parent | bf3cf6db6ec7286c641f69e3d3ce6ad90435c1fa (diff) | |
| parent | 799faf13de5f028b543bc0d8c1e5f94ba01545bf (diff) | |
Merge "[1/n] Camera Compat Freeform: per-app controls for disabling the treatment." into main
3 files changed, 107 insertions, 18 deletions
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index bd04634ac4f1..535cebb1d1af 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -1280,6 +1280,26 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { 264301586L; // buganizer id /** + * Excludes the packages the override is applied to from the camera compatibility treatment + * in free-form windowing mode for fixed-orientation apps. + * + * <p>In free-form windowing mode, the compatibility treatment emulates running on a portrait + * device by letterboxing the app window and changing the camera characteristics to what apps + * commonly expect in a portrait device: 90 and 270 degree sensor rotation for back and front + * cameras, respectively, and setting display rotation to 0. + * + * <p>Use this flag to disable the compatibility treatment for apps that do not respond well to + * the treatment. + * + * @hide + */ + @ChangeId + @Overridable + @Disabled + public static final long OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT = + 314961188L; + + /** * This change id forces the packages it is applied to sandbox {@link android.view.View} API to * an activity bounds for: * diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java index 5d613cf45643..a24c02a3b677 100644 --- a/services/core/java/com/android/server/wm/LetterboxUiController.java +++ b/services/core/java/com/android/server/wm/LetterboxUiController.java @@ -22,6 +22,7 @@ import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP; import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION_TO_USER; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION; +import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; @@ -131,6 +132,7 @@ import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.LetterboxDetails; import com.android.server.wm.LetterboxConfiguration.LetterboxBackgroundType; +import com.android.window.flags.Flags; import java.io.PrintWriter; import java.util.ArrayList; @@ -194,7 +196,8 @@ final class LetterboxUiController { private final boolean mIsOverrideCameraCompatDisableRefreshEnabled; // Corresponds to OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE private final boolean mIsOverrideCameraCompatEnableRefreshViaPauseEnabled; - + // Corresponds to OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT + private final boolean mIsOverrideCameraCompatDisableFreeformWindowingTreatmentEnabled; // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION private final boolean mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled; // Corresponds to OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED @@ -321,15 +324,15 @@ final class LetterboxUiController { PROPERTY_COMPAT_ENABLE_FAKE_FOCUS); mBooleanPropertyCameraCompatAllowForceRotation = readComponentProperty(packageManager, mActivityRecord.packageName, - () -> mLetterboxConfiguration.isCameraCompatTreatmentEnabled(), + mLetterboxConfiguration::isCameraCompatTreatmentEnabled, PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION); mBooleanPropertyCameraCompatAllowRefresh = readComponentProperty(packageManager, mActivityRecord.packageName, - () -> mLetterboxConfiguration.isCameraCompatTreatmentEnabled(), + mLetterboxConfiguration::isCameraCompatTreatmentEnabled, PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH); mBooleanPropertyCameraCompatEnableRefreshViaPause = readComponentProperty(packageManager, mActivityRecord.packageName, - () -> mLetterboxConfiguration.isCameraCompatTreatmentEnabled(), + mLetterboxConfiguration::isCameraCompatTreatmentEnabled, PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE); mBooleanPropertyAllowOrientationOverride = @@ -351,11 +354,11 @@ final class LetterboxUiController { mBooleanPropertyAllowUserAspectRatioOverride = readComponentProperty(packageManager, mActivityRecord.packageName, - () -> mLetterboxConfiguration.isUserAppAspectRatioSettingsEnabled(), + mLetterboxConfiguration::isUserAppAspectRatioSettingsEnabled, PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE); mBooleanPropertyAllowUserAspectRatioFullscreenOverride = readComponentProperty(packageManager, mActivityRecord.packageName, - () -> mLetterboxConfiguration.isUserAppAspectRatioFullscreenEnabled(), + mLetterboxConfiguration::isUserAppAspectRatioFullscreenEnabled, PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE); mIsOverrideAnyOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ANY_ORIENTATION); @@ -380,6 +383,8 @@ final class LetterboxUiController { isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH); mIsOverrideCameraCompatEnableRefreshViaPauseEnabled = isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE); + mIsOverrideCameraCompatDisableFreeformWindowingTreatmentEnabled = + isCompatChangeEnabled(OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT); mIsOverrideEnableCompatIgnoreRequestedOrientationEnabled = isCompatChangeEnabled(OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION); @@ -759,8 +764,7 @@ final class LetterboxUiController { */ boolean shouldRefreshActivityForCameraCompat() { return shouldEnableWithOptOutOverrideAndProperty( - /* gatingCondition */ () -> mLetterboxConfiguration - .isCameraCompatTreatmentEnabled(), + /* gatingCondition */ mLetterboxConfiguration::isCameraCompatTreatmentEnabled, mIsOverrideCameraCompatDisableRefreshEnabled, mBooleanPropertyCameraCompatAllowRefresh); } @@ -781,8 +785,7 @@ final class LetterboxUiController { */ boolean shouldRefreshActivityViaPauseForCameraCompat() { return shouldEnableWithOverrideAndProperty( - /* gatingCondition */ () -> mLetterboxConfiguration - .isCameraCompatTreatmentEnabled(), + /* gatingCondition */ mLetterboxConfiguration::isCameraCompatTreatmentEnabled, mIsOverrideCameraCompatEnableRefreshViaPauseEnabled, mBooleanPropertyCameraCompatEnableRefreshViaPause); } @@ -800,12 +803,34 @@ final class LetterboxUiController { */ boolean shouldForceRotateForCameraCompat() { return shouldEnableWithOptOutOverrideAndProperty( - /* gatingCondition */ () -> mLetterboxConfiguration - .isCameraCompatTreatmentEnabled(), + /* gatingCondition */ mLetterboxConfiguration::isCameraCompatTreatmentEnabled, mIsOverrideCameraCompatDisableForceRotationEnabled, mBooleanPropertyCameraCompatAllowForceRotation); } + /** + * Whether activity is eligible for camera compatibility free-form treatment. + * + * <p>The treatment is applied to a fixed-orientation camera activity in free-form windowing + * mode. The treatment letterboxes or pillarboxes the activity to the expected orientation and + * provides changes to the camera and display orientation signals to match those expected on a + * portrait device in that orientation (for example, on a standard phone). + * + * <p>The treatment is enabled when the following conditions are met: + * <ul> + * <li>Property gating the camera compatibility free-form treatment is enabled. + * <li>Activity isn't opted out by the device manufacturer with override or by the app + * developers with the component property. + * </ul> + */ + boolean shouldApplyFreeformTreatmentForCameraCompat() { + return shouldEnableWithOptOutOverrideAndProperty( + /* gatingCondition */ ()-> Flags.cameraCompatForFreeform(), + mIsOverrideCameraCompatDisableFreeformWindowingTreatmentEnabled, + // TODO(b/328616176): add a manifest override for developers. + null); + } + private boolean isCameraCompatTreatmentActive() { DisplayContent displayContent = mActivityRecord.mDisplayContent; if (displayContent == null) { diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java index 4e4bbfe6371d..0290f0f5bd0f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP; import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_ANY_ORIENTATION_TO_USER; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION; +import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; @@ -63,6 +64,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.server.wm.LetterboxUiController.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; import static com.android.server.wm.LetterboxUiController.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS; +import static com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -81,6 +83,7 @@ import android.content.pm.PackageManager.Property; import android.content.res.Resources; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; +import android.platform.test.flag.junit.SetFlagsRule; import android.view.InsetsSource; import android.view.InsetsState; import android.view.RoundedCorner; @@ -101,11 +104,11 @@ import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; - /** +/** * Test class for {@link LetterboxUiControllerTest}. * * Build/Install/Run: - * atest WmTests:LetterboxUiControllerTest + * atest WmTests:LetterboxUiControllerTest */ @SmallTest @Presubmit @@ -122,6 +125,8 @@ public class LetterboxUiControllerTest extends WindowTestsBase { @Rule public TestRule compatChangeRule = new PlatformCompatChangeRule(); + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private ActivityRecord mActivity; private Task mTask; @@ -466,10 +471,48 @@ public class LetterboxUiControllerTest extends WindowTestsBase { assertTrue(mController.shouldForceRotateForCameraCompat()); } + // shouldApplyFreeformTreatmentForCameraCompat + + @Test + public void testShouldApplyCameraCompatFreeformTreatment_flagIsDisabled_returnsFalse() { + mSetFlagsRule.disableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM); + + assertFalse(mController.shouldApplyFreeformTreatmentForCameraCompat()); + } + + @Test + @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT}) + public void testShouldApplyCameraCompatFreeformTreatment_overrideEnabled_returnsFalse() { + mSetFlagsRule.enableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM); + + assertFalse(mController.shouldApplyFreeformTreatmentForCameraCompat()); + } + + @Test + @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_FREEFORM_WINDOWING_TREATMENT}) + public void testShouldApplyCameraCompatFreeformTreatment_disabledByOverride_returnsFalse() + throws Exception { + mSetFlagsRule.enableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM); + + mController = new LetterboxUiController(mWm, mActivity); + + assertFalse(mController.shouldApplyFreeformTreatmentForCameraCompat()); + } + + @Test + public void testShouldApplyCameraCompatFreeformTreatment_notDisabledByOverride_returnsTrue() + throws Exception { + mSetFlagsRule.enableFlags(FLAG_CAMERA_COMPAT_FOR_FREEFORM); + + mController = new LetterboxUiController(mWm, mActivity); + + assertTrue(mController.shouldApplyFreeformTreatmentForCameraCompat()); + } + @Test public void testGetCropBoundsIfNeeded_handleCropForTransparentActivityBasedOnOpaqueBounds() { final InsetsSource taskbar = new InsetsSource(/*id=*/ 0, - WindowInsets.Type.navigationBars()); + WindowInsets.Type.navigationBars()); taskbar.setFlags(FLAG_INSETS_ROUNDED_CORNER, FLAG_INSETS_ROUNDED_CORNER); final WindowState mainWindow = mockForGetCropBoundsAndRoundedCorners(taskbar); final Rect opaqueBounds = new Rect(0, 0, 500, 300); @@ -726,7 +769,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase { throws Exception { mDisplayContent.setIgnoreOrientationRequest(false); assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded( - /* candidate */ SCREEN_ORIENTATION_PORTRAIT)); + /* candidate */ SCREEN_ORIENTATION_PORTRAIT)); } @Test @@ -736,7 +779,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase { prepareActivityThatShouldApplyUserMinAspectRatioOverride(); assertEquals(SCREEN_ORIENTATION_PORTRAIT, mController.overrideOrientationIfNeeded( - /* candidate */ SCREEN_ORIENTATION_PORTRAIT)); + /* candidate */ SCREEN_ORIENTATION_PORTRAIT)); } @Test @@ -859,6 +902,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase { assertEquals(SCREEN_ORIENTATION_USER, mController.overrideOrientationIfNeeded( /* candidate */ SCREEN_ORIENTATION_UNSPECIFIED)); } + @Test public void testOverrideOrientationIfNeeded_respectOrientationRequestOverUserFullScreen() { spyOn(mController); @@ -1380,7 +1424,7 @@ public class LetterboxUiControllerTest extends WindowTestsBase { private void mockThatProperty(String propertyName, boolean value) throws Exception { Property property = new Property(propertyName, /* value */ value, /* packageName */ "", - /* className */ ""); + /* className */ ""); PackageManager pm = mWm.mContext.getPackageManager(); spyOn(pm); doReturn(property).when(pm).getProperty(eq(propertyName), anyString()); |