Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 94fba95e authored by Mina Granic's avatar Mina Granic Committed by Android (Google) Code Review
Browse files

Merge "Add an opt-out property for camera compat freeform treatment." into main

parents 973f0b16 5e050679
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -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>
     * &lt;application&gt;
     *   &lt;property
     *     android:name="android.window.PROPERTY_CAMERA_COMPAT_ALLOW_SIMULATE_REQUESTED_ORIENTATION"
     *     android:value="true|false"/&gt;
     * &lt;/application&gt;
     * </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
+33 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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,
@@ -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;
    }

    /**
@@ -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() {
+30 −0
Original line number Diff line number Diff line
@@ -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;
@@ -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)