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

Commit 7e110400 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "CameraCompat: use simReqOrientation instead of force-rotate in fullscreen." into main

parents 1d3f26bb 05c7eda6
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -120,6 +120,12 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState
        return mIsRunning;
    }

    static boolean isPolicyEnabled(@NonNull DisplayContent displayContent) {
        return !Flags.cameraCompatUnifyCameraPolicies()
                && displayContent.mWmService.mAppCompatConfiguration
                        .isCameraCompatForceRotateTreatmentEnabledAtBuildTime();
    }

    /**
     * Determines orientation for Camera compatibility.
     *
@@ -161,7 +167,7 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState
        boolean isPortraitActivity =
                topActivity.getRequestedConfigurationOrientation() == ORIENTATION_PORTRAIT;
        boolean isNaturalDisplayOrientationPortrait =
                mDisplayContent.getNaturalOrientation() == ORIENTATION_PORTRAIT;
                topActivity.getDisplayContent().getNaturalOrientation() == ORIENTATION_PORTRAIT;
        // Rotate portrait-only activity in the natural orientation of the displays (and in the
        // opposite to natural orientation for landscape-only) since many apps assume that those
        // are aligned when they compute orientation of the preview.
@@ -180,7 +186,7 @@ final class AppCompatCameraDisplayRotationPolicy implements AppCompatCameraState
                "Display id=%d is ignoring all orientation requests, camera is active "
                        + "and the top activity is eligible for force rotation, return %s,"
                        + "portrait activity: %b, is natural orientation portrait: %b.",
                mDisplayContent.mDisplayId, screenOrientationToString(orientation),
                topActivity.getDisplayContent().mDisplayId, screenOrientationToString(orientation),
                isPortraitActivity, isNaturalDisplayOrientationPortrait);
        return orientation;
    }
+7 −11
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.res.Configuration;
import android.view.Surface;
import android.widget.Toast;
import android.window.DesktopModeFlags;

import com.android.internal.annotations.VisibleForTesting;

@@ -52,24 +51,21 @@ class AppCompatCameraPolicy {
            @NonNull DisplayContent displayContent) {
        // Not checking DeviceConfig value here to allow enabling via DeviceConfig
        // without the need to restart the device.
        final boolean needsDisplayRotationPolicy = wmService.mAppCompatConfiguration
                .isCameraCompatForceRotateTreatmentEnabledAtBuildTime();
        final boolean needsSimReqOrientationPolicy =
                DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue()
                        && DesktopModeHelper.canEnterDesktopMode(wmService.mContext)
                        && wmService.mAppCompatConfiguration
                        .isCameraCompatSimulateRequestedOrientationTreatmentEnabled();
        if (needsDisplayRotationPolicy || needsSimReqOrientationPolicy) {
        final boolean isDisplayRotationPolicyEnabled = AppCompatCameraDisplayRotationPolicy
                .isPolicyEnabled(displayContent);
        final boolean isSimReqOrientationPolicyEnabled = AppCompatCameraSimReqOrientationPolicy
                .isPolicyEnabled(displayContent);
        if (isDisplayRotationPolicyEnabled || isSimReqOrientationPolicyEnabled) {
            final AppCompatCameraStateSource cameraStateListenerDelegate =
                    new AppCompatCameraStateSource();
            mCameraStateMonitor = new CameraStateMonitor(displayContent, wmService.mH,
                    cameraStateListenerDelegate);
            mActivityRefresher = new ActivityRefresher(wmService, wmService.mH);
            mDisplayRotationPolicy = needsDisplayRotationPolicy
            mDisplayRotationPolicy = isDisplayRotationPolicyEnabled
                    ? new AppCompatCameraDisplayRotationPolicy(displayContent, mCameraStateMonitor,
                            cameraStateListenerDelegate, mActivityRefresher)
                    : null;
            mSimReqOrientationPolicy = needsSimReqOrientationPolicy
            mSimReqOrientationPolicy = isSimReqOrientationPolicyEnabled
                    ? new AppCompatCameraSimReqOrientationPolicy(displayContent,
                            mCameraStateMonitor, cameraStateListenerDelegate, mActivityRefresher)
                    : null;
+34 −11
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_PORTRAIT_DEVICE_IN_
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_PORTRAIT_DEVICE_IN_PORTRAIT;
import static android.app.CameraCompatTaskInfo.CAMERA_COMPAT_UNSPECIFIED;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOW_CONFIG_APP_BOUNDS;
import static android.app.WindowConfiguration.WINDOW_CONFIG_DISPLAY_ROTATION;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
@@ -43,6 +44,7 @@ import android.content.res.Configuration;
import android.os.RemoteException;
import android.util.Slog;
import android.view.Surface;
import android.window.DesktopModeFlags;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
@@ -62,7 +64,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta
    private static final String TAG = TAG_WITH_CLASS_NAME ? "AppCompatCameraSROPolicy" : TAG_WM;

    @NonNull
    private final DisplayContent mDisplayContent;
    private final ActivityTaskManagerService mAtmService;
    @NonNull
    private final ActivityRefresher mActivityRefresher;
    @NonNull
@@ -85,7 +87,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta
            @NonNull CameraStateMonitor cameraStateMonitor,
            @NonNull AppCompatCameraStateSource cameraStateNotifier,
            @NonNull ActivityRefresher activityRefresher) {
        mDisplayContent = displayContent;
        mAtmService = displayContent.mAtmService;
        mCameraStateMonitor = cameraStateMonitor;
        mCameraStateNotifier = cameraStateNotifier;
        mActivityRefresher = activityRefresher;
@@ -117,6 +119,14 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta
        return mCameraDisplayRotationProvider.getCameraDeviceRotation();
    }

    static boolean isPolicyEnabled(@NonNull DisplayContent displayContent) {
        return DesktopModeFlags.ENABLE_CAMERA_COMPAT_SIMULATE_REQUESTED_ORIENTATION.isTrue()
                && (DesktopModeHelper.canEnterDesktopMode(displayContent.mWmService.mContext)
                        || Flags.cameraCompatUnifyCameraPolicies())
                && displayContent.mWmService.mAppCompatConfiguration
                        .isCameraCompatSimulateRequestedOrientationTreatmentEnabled();
    }

    // Refreshing only when configuration changes after applying camera compat treatment.
    @Override
    public boolean shouldRefreshActivity(@NonNull ActivityRecord activity,
@@ -174,7 +184,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta
            ProtoLog.v(WmProtoLogGroups.WM_DEBUG_STATES,
                    "Display id=%d is notified that Camera %s is closed but activity is"
                            + " still refreshing. Rescheduling an update.",
                    mDisplayContent.mDisplayId, cameraId);
                    topActivity.getDisplayContent().mDisplayId, cameraId);
            return false;
        }
        return true;
@@ -234,7 +244,7 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta
            Slog.w(TAG, "Insufficient app information. Cannot revert display rotation sandboxing.");
            return;
        }
        final CompatibilityInfo compatibilityInfo = mDisplayContent.mAtmService
        final CompatibilityInfo compatibilityInfo = mAtmService
                .compatibilityInfoForPackageLocked(app.mInfo);
        // CompatibilityInfo fields are static, so even if task or activity has been closed, this
        // state should be updated.
@@ -341,13 +351,18 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta
    boolean isCameraRunningAndWindowingModeEligible(@NonNull ActivityRecord activity) {
        return  activity.mAppCompatController.getCameraOverrides()
                .shouldApplyCameraCompatSimReqOrientationTreatment()
                // Do not apply camera compat treatment when an app is running on a candybar
                // display.
                && activity.getDisplayContent().getIgnoreOrientationRequest()
                && isWindowingModeEligible(activity)
                && mCameraStateMonitor.isCameraRunningForActivity(activity);
    }

    private boolean isWindowingModeEligible(@NonNull ActivityRecord activity) {
        // TODO(b/432218134): consider all windowing modes, e.g. WINDOWING_MODE_PINNED.
        return activity.inFreeformWindowingMode()
                || (Flags.cameraCompatUnifyCameraPolicies() && activity.inMultiWindowMode());
                || (Flags.cameraCompatUnifyCameraPolicies() && (activity.inMultiWindowMode()
                        || activity.getWindowingMode() == WINDOWING_MODE_FULLSCREEN));
    }

    boolean shouldCameraCompatControlAspectRatio(@NonNull ActivityRecord activity) {
@@ -426,18 +441,26 @@ final class AppCompatCameraSimReqOrientationPolicy implements AppCompatCameraSta
    @VisibleForTesting
    boolean isTreatmentEnabledForActivity(@NonNull ActivityRecord activity,
            boolean checkOrientation) {
        int orientation = activity.getRequestedConfigurationOrientation();
        return activity.mAppCompatController.getCameraOverrides()
                .shouldApplyCameraCompatSimReqOrientationTreatment()
                // Do not apply camera compat treatment when an app is running on a candybar
                // display.
                && activity.getDisplayContent().getIgnoreOrientationRequest()
                && mCameraStateMonitor.isCameraRunningForActivity(activity)
                && (!checkOrientation || orientation != ORIENTATION_UNDEFINED)
                && activity.inFreeformWindowingMode()
                && isOrientationEligibleForTreatment(activity, checkOrientation)
                && isWindowingModeEligible(activity)
                // TODO(b/332665280): investigate whether we can support activity embedding.
                && !activity.isEmbedded();
    }

    private boolean isOrientationEligibleForTreatment(@NonNull ActivityRecord activity,
            boolean checkOrientation) {
        final int orientation = activity.getRequestedConfigurationOrientation();
        return  (!checkOrientation || orientation != ORIENTATION_UNDEFINED)
                // "locked" and "nosensor" values are often used by camera apps that can't
                // handle dynamic changes so we shouldn't force-letterbox them.
                && activity.getRequestedOrientation() != SCREEN_ORIENTATION_NOSENSOR
                && activity.getRequestedOrientation() != SCREEN_ORIENTATION_LOCKED
                // TODO(b/332665280): investigate whether we can support activity embedding.
                && !activity.isEmbedded();
                && activity.getRequestedOrientation() != SCREEN_ORIENTATION_LOCKED;
    }

    @Nullable
+20 −15
Original line number Diff line number Diff line
@@ -732,6 +732,24 @@ public class ActivityRecordTests extends WindowTestsBase {
    @DisableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT)
    @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT})
    public void testOrientation_allowFixedOrientationForCameraCompatInFreeformWindowing() {
        doReturn(true).when(() -> DesktopModeHelper.canEnterDesktopMode(any()));
        final ActivityRecord activity = setupDisplayAndActivityForCameraCompat(
                /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM);

        // Task in landscape.
        assertEquals(ORIENTATION_LANDSCAPE, activity.getTask().getConfiguration().orientation);
        // The app should be letterboxed.
        assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation);
        assertTrue(activity.mAppCompatController.getAspectRatioPolicy()
                .isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    @EnableFlags({Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING,
            Flags.FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES,
            Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING_OPT_OUT})
    @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT})
    public void testOrientation_allowFixedOrientationForCameraCompatWhenEnabledForAll() {
        final ActivityRecord activity = setupDisplayAndActivityForCameraCompat(
                /* isCameraRunning= */ true, WINDOWING_MODE_FREEFORM);

@@ -789,21 +807,6 @@ public class ActivityRecordTests extends WindowTestsBase {
                .isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING)
    @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_ENABLE_FREEFORM_WINDOWING_TREATMENT})
    public void testOrientation_dontAllowFixedOrientationForCameraCompatFreeformIfInPip() {
        final ActivityRecord activity = setupDisplayAndActivityForCameraCompat(
                /* isCameraRunning= */ true, WINDOWING_MODE_PINNED);

        // Task in landscape.
        assertEquals(ORIENTATION_LANDSCAPE, activity.getTask().getConfiguration().orientation);
        // Activity is not letterboxed.
        assertEquals(ORIENTATION_LANDSCAPE, activity.getConfiguration().orientation);
        assertFalse(activity.mAppCompatController.getAspectRatioPolicy()
                .isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    public void testShouldMakeActive_deferredResume() {
        final ActivityRecord activity = createActivityWithTask();
@@ -3631,6 +3634,7 @@ public class ActivityRecordTests extends WindowTestsBase {
        // Create a new DisplayContent so that the flag values create the camera freeform policy.
        mDisplayContent = new TestDisplayContent.Builder(mAtm, mDisplayContent.getSurfaceWidth(),
                mDisplayContent.getSurfaceHeight()).build();
        mDisplayContent.setIgnoreOrientationRequest(true);
        final CameraStateMonitor cameraStateMonitor = mDisplayContent.mAppCompatCameraPolicy
                .mCameraStateMonitor;
        spyOn(cameraStateMonitor);
@@ -3646,6 +3650,7 @@ public class ActivityRecordTests extends WindowTestsBase {
        final ActivityRecord activity = new ActivityBuilder(mAtm)
                .setComponent(ComponentName.createRelative(mContext,
                        com.android.server.wm.ActivityRecordTests.class.getName()))
                .setTask(rootTask)
                .setParentTask(rootTask)
                .setCreateTask(true)
                .setOnTop(true)
+14 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.AppCompatCameraPolicy.isTreatmentEnabledForActivity;
import static com.android.server.wm.AppCompatCameraPolicy.shouldOverrideMinAspectRatioForCamera;
import static com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES;
import static com.android.window.flags.Flags.FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING;

import static org.junit.Assert.assertEquals;
@@ -124,6 +125,19 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase {
        });
    }

    @Test
    @EnableFlags({FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING,
            FLAG_CAMERA_COMPAT_UNIFY_CAMERA_POLICIES})
    public void testSimReqOrientationPolicy_unifyCameraPoliciesAndAllowedViaConfig_present() {
        runTestScenario((robot) -> {
            robot.dw().allowEnterDesktopMode(/* isAllowed= */ false);
            robot.conf().enableCameraCompatSimulateRequestedOrientationTreatment(
                    /* enabled= */ true);
            robot.activity().createActivityWithComponentInNewTaskAndDisplay();
            robot.checkTopActivityHasSimReqOrientationPolicy(/* exists= */ true);
        });
    }

    @Test
    @EnableFlags(FLAG_ENABLE_CAMERA_COMPAT_FOR_DESKTOP_WINDOWING)
    public void testSimReqOrientationPolicy_startedWhenEnabledAndDW() {
Loading