Loading core/java/android/view/WindowManager.java +37 −0 Original line number Diff line number Diff line Loading @@ -1198,6 +1198,43 @@ public interface WindowManager extends ViewManager { String PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE = "android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE"; /** * Application-level [PackageManager][android.content.pm.PackageManager.Property] tag that (when * set to false) informs the system the app has opted out of the camera compatibility treatment * for fixed-orientation apps, which simulates running on a portrait device, in the orientation * requested by the app. * * <p>This treatment aims to mitigate camera issues on large screens, like stretched or sideways * previews. It simulates running on a portrait device by: * <ul> * <li>Letterboxing the app window, * <li>Cropping the camera buffer to match the app's requested orientation, * <li>Setting the camera sensor orientation to portrait. * <li>Setting the display rotation to match the app's requested orientation, given portrait * natural orientation, * <li>Refreshes the activity to trigger new camera setup, with sandboxed values. * </ul> * * <p>To opt out of the camera compatibility treatment, add this property to your app manifest * and set the value to {@code false}. * * <p>Not setting this property at all, or setting this property to {@code true} has no effect. * * <p><b>Syntax:</b> * <pre> * <application> * <property * android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION" * android:value="true|false"/> * </application> * </pre> * * @hide */ //TODO(b/394590412): Make this property public. String PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION = "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION"; /** * Application level {@link android.content.pm.PackageManager.Property PackageManager.Property} * for an app to inform the system that the app should be excluded from the compatibility Loading services/core/java/com/android/server/wm/AppCompatCameraOverrides.java +33 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFR import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA; import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; Loading @@ -32,6 +33,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS import static com.android.server.wm.AppCompatUtils.isChangeEnabled; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.server.wm.utils.OptPropFactory; import com.android.window.flags.Flags; Loading Loading @@ -60,6 +62,8 @@ class AppCompatCameraOverrides { private final OptPropFactory.OptProp mCameraCompatEnableRefreshViaPauseOptProp; @NonNull private final OptPropFactory.OptProp mCameraCompatAllowForceRotationOptProp; @Nullable private final OptPropFactory.OptProp mCameraCompatAllowOrientationTreatmentOptProp; AppCompatCameraOverrides(@NonNull ActivityRecord activityRecord, @NonNull AppCompatConfiguration appCompatConfiguration, Loading @@ -80,6 +84,10 @@ class AppCompatCameraOverrides { mCameraCompatAllowForceRotationOptProp = optPropBuilder.create( PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION, isCameraCompatTreatmentEnabled); mCameraCompatAllowOrientationTreatmentOptProp = Flags.enableCameraCompatForDesktopWindowingOptOut() ? optPropBuilder.create( PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION, isCameraCompatTreatmentEnabled) : null; } /** Loading Loading @@ -168,10 +176,31 @@ class AppCompatCameraOverrides { * </ul> */ boolean shouldApplyFreeformTreatmentForCameraCompat() { return Flags.enableCameraCompatForDesktopWindowing() && (isChangeEnabled(mActivityRecord, OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT) || mActivityRecord.mWmService.mAppCompatConfiguration .isCameraCompatFreeformWindowingTreatmentEnabled()); return Flags.enableCameraCompatForDesktopWindowing() && (shouldEnableCameraCompatFreeformTreatmentForApp() || shouldEnableCameraCompatFreeformTreatmentForAllApps()); } private boolean shouldEnableCameraCompatFreeformTreatmentForApp() { if (mCameraCompatAllowOrientationTreatmentOptProp != null) { return mCameraCompatAllowOrientationTreatmentOptProp .shouldEnableWithOptOutOverrideAndProperty(isChangeEnabled(mActivityRecord, OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT)); } else { return isChangeEnabled(mActivityRecord, OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT); } } /** * Returns whether camera compat treatment should be enabled for all apps targeted for treatment * (usually fixed-orientation apps). * * <p>This can be enabled via adb only. */ private boolean shouldEnableCameraCompatFreeformTreatmentForAllApps() { return mActivityRecord.mWmService.mAppCompatConfiguration .isCameraCompatFreeformWindowingTreatmentEnabled(); } boolean isOverrideOrientationOnlyForCameraEnabled() { Loading services/tests/wmtests/src/com/android/server/wm/AppCompatCameraOverridesTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -23,12 +23,14 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFR import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA; import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT; import android.compat.testing.PlatformCompatChangeRule; import android.platform.test.annotations.DisableFlags; Loading Loading @@ -237,6 +239,34 @@ public class AppCompatCameraOverridesTest extends WindowTestsBase { }); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) @EnableFlags({FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT}) public void testShouldApplyCameraCompatFreeformTreatment_propertyFalse_returnsFalse() { runTestScenario((robot) -> { robot.activity().createActivityWithComponentInNewTask(); robot.prop().disable(PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION); robot.checkShouldApplyFreeformTreatmentForCameraCompat(false); }); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) public void testShouldApplyCameraCompatFreeformTreatment_optOutFlagNotEnabled_optOutIgnored() { runTestScenario((robot) -> { robot.activity().createActivityWithComponentInNewTask(); robot.prop().disable(PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION); robot.checkShouldApplyFreeformTreatmentForCameraCompat(true); }); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) Loading Loading
core/java/android/view/WindowManager.java +37 −0 Original line number Diff line number Diff line Loading @@ -1198,6 +1198,43 @@ public interface WindowManager extends ViewManager { String PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE = "android.window.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE"; /** * Application-level [PackageManager][android.content.pm.PackageManager.Property] tag that (when * set to false) informs the system the app has opted out of the camera compatibility treatment * for fixed-orientation apps, which simulates running on a portrait device, in the orientation * requested by the app. * * <p>This treatment aims to mitigate camera issues on large screens, like stretched or sideways * previews. It simulates running on a portrait device by: * <ul> * <li>Letterboxing the app window, * <li>Cropping the camera buffer to match the app's requested orientation, * <li>Setting the camera sensor orientation to portrait. * <li>Setting the display rotation to match the app's requested orientation, given portrait * natural orientation, * <li>Refreshes the activity to trigger new camera setup, with sandboxed values. * </ul> * * <p>To opt out of the camera compatibility treatment, add this property to your app manifest * and set the value to {@code false}. * * <p>Not setting this property at all, or setting this property to {@code true} has no effect. * * <p><b>Syntax:</b> * <pre> * <application> * <property * android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION" * android:value="true|false"/> * </application> * </pre> * * @hide */ //TODO(b/394590412): Make this property public. String PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION = "android.window.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION"; /** * Application level {@link android.content.pm.PackageManager.Property PackageManager.Property} * for an app to inform the system that the app should be excluded from the compatibility Loading
services/core/java/com/android/server/wm/AppCompatCameraOverrides.java +33 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFR import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA; import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; Loading @@ -32,6 +33,7 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLAS import static com.android.server.wm.AppCompatUtils.isChangeEnabled; import android.annotation.NonNull; import android.annotation.Nullable; import com.android.server.wm.utils.OptPropFactory; import com.android.window.flags.Flags; Loading Loading @@ -60,6 +62,8 @@ class AppCompatCameraOverrides { private final OptPropFactory.OptProp mCameraCompatEnableRefreshViaPauseOptProp; @NonNull private final OptPropFactory.OptProp mCameraCompatAllowForceRotationOptProp; @Nullable private final OptPropFactory.OptProp mCameraCompatAllowOrientationTreatmentOptProp; AppCompatCameraOverrides(@NonNull ActivityRecord activityRecord, @NonNull AppCompatConfiguration appCompatConfiguration, Loading @@ -80,6 +84,10 @@ class AppCompatCameraOverrides { mCameraCompatAllowForceRotationOptProp = optPropBuilder.create( PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION, isCameraCompatTreatmentEnabled); mCameraCompatAllowOrientationTreatmentOptProp = Flags.enableCameraCompatForDesktopWindowingOptOut() ? optPropBuilder.create( PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION, isCameraCompatTreatmentEnabled) : null; } /** Loading Loading @@ -168,10 +176,31 @@ class AppCompatCameraOverrides { * </ul> */ boolean shouldApplyFreeformTreatmentForCameraCompat() { return Flags.enableCameraCompatForDesktopWindowing() && (isChangeEnabled(mActivityRecord, OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT) || mActivityRecord.mWmService.mAppCompatConfiguration .isCameraCompatFreeformWindowingTreatmentEnabled()); return Flags.enableCameraCompatForDesktopWindowing() && (shouldEnableCameraCompatFreeformTreatmentForApp() || shouldEnableCameraCompatFreeformTreatmentForAllApps()); } private boolean shouldEnableCameraCompatFreeformTreatmentForApp() { if (mCameraCompatAllowOrientationTreatmentOptProp != null) { return mCameraCompatAllowOrientationTreatmentOptProp .shouldEnableWithOptOutOverrideAndProperty(isChangeEnabled(mActivityRecord, OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT)); } else { return isChangeEnabled(mActivityRecord, OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT); } } /** * Returns whether camera compat treatment should be enabled for all apps targeted for treatment * (usually fixed-orientation apps). * * <p>This can be enabled via adb only. */ private boolean shouldEnableCameraCompatFreeformTreatmentForAllApps() { return mActivityRecord.mWmService.mAppCompatConfiguration .isCameraCompatFreeformWindowingTreatmentEnabled(); } boolean isOverrideOrientationOnlyForCameraEnabled() { Loading
services/tests/wmtests/src/com/android/server/wm/AppCompatCameraOverridesTest.java +30 −0 Original line number Diff line number Diff line Loading @@ -23,12 +23,14 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFR import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA; import static android.content.pm.ActivityInfo.OVERRIDE_ORIENTATION_ONLY_FOR_CAMERA; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING; import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT; import android.compat.testing.PlatformCompatChangeRule; import android.platform.test.annotations.DisableFlags; Loading Loading @@ -237,6 +239,34 @@ public class AppCompatCameraOverridesTest extends WindowTestsBase { }); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) @EnableFlags({FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING, FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT}) public void testShouldApplyCameraCompatFreeformTreatment_propertyFalse_returnsFalse() { runTestScenario((robot) -> { robot.activity().createActivityWithComponentInNewTask(); robot.prop().disable(PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION); robot.checkShouldApplyFreeformTreatmentForCameraCompat(false); }); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) @DisableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT) public void testShouldApplyCameraCompatFreeformTreatment_optOutFlagNotEnabled_optOutIgnored() { runTestScenario((robot) -> { robot.activity().createActivityWithComponentInNewTask(); robot.prop().disable(PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION); robot.checkShouldApplyFreeformTreatmentForCameraCompat(true); }); } @Test @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT}) @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING) Loading