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

Commit 3bc4a871 authored by Mina Karadzic's avatar Mina Karadzic
Browse files

Refactor camera compat to use CameraCompatibilityInfo instead of int.

This allows more flexible data storage.

Flag: EXEMPT refactoring
Bug: 414347702
Test: atest WmTests:AppCompatCameraSimReqOrientationPolicyTests
Change-Id: Ib7db2789261f61eaa2acf5286e4808fa93863c4d
parent 86c150c5
Loading
Loading
Loading
Loading
+6 −21
Original line number Diff line number Diff line
@@ -1449,8 +1449,7 @@ public final class ActivityThread extends ClientTransactionHandler
            data.startRequestedElapsedTime = startRequestedElapsedTime;
            data.startRequestedUptime = startRequestedUptime;
            updateCompatOverrideScale(compatInfo);
            updateCompatOverrideDisplayRotation(compatInfo);
            updateCompatOverrideCameraRotation(compatInfo);
            updateCameraCompatInfo(compatInfo);
            CompatibilityInfo.applyOverrideIfNeeded(config);
            sendMessage(H.BIND_APPLICATION, data);
        }
@@ -1465,24 +1464,11 @@ public final class ActivityThread extends ClientTransactionHandler
            }
        }

        private void updateCompatOverrideDisplayRotation(@NonNull CompatibilityInfo info) {
            if (info.isOverrideDisplayRotationRequired()) {
                CompatibilityInfo.setOverrideDisplayRotation(info.applicationDisplayRotation);
        private void updateCameraCompatInfo(@NonNull CompatibilityInfo info) {
            if (info.isOverrideCameraCompatibilityInfoRequired()) {
                CompatibilityInfo.setCameraCompatibilityInfo(info.cameraCompatibilityInfo);
            } else {
                CompatibilityInfo.setOverrideDisplayRotation(
                        WindowConfiguration.ROTATION_UNDEFINED);
            }
        }

        private void updateCompatOverrideCameraRotation(@NonNull CompatibilityInfo info) {
            if (com.android.window.flags.Flags
                    .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
                if (info.isOverrideCameraRotationRequired()) {
                    CompatibilityInfo.setOverrideCameraRotation(info.applicationCameraRotation);
                } else {
                    CompatibilityInfo.setOverrideCameraRotation(
                            WindowConfiguration.ROTATION_UNDEFINED);
                }
                CompatibilityInfo.resetCameraCompatibilityInfo();
            }
        }

@@ -2188,8 +2174,7 @@ public final class ActivityThread extends ClientTransactionHandler
            ucd.pkg = pkg;
            ucd.info = info;
            updateCompatOverrideScale(info);
            updateCompatOverrideDisplayRotation(info);
            updateCompatOverrideCameraRotation(info);
            updateCameraCompatInfo(info);
            sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
        }

+9 −1
Original line number Diff line number Diff line
@@ -190,13 +190,21 @@ public final class CameraCompatibilityInfo implements Parcelable {
    }

    /** Whether any camera compat mode changes are requested via this object. */
    public static boolean isCameraCompatModeActive(CameraCompatibilityInfo cameraCompatMode) {
    public static boolean isCameraCompatModeActive(@NonNull CameraCompatibilityInfo
            cameraCompatMode) {
        return cameraCompatMode.mRotateAndCropRotation != ROTATION_UNDEFINED
                || cameraCompatMode.mShouldOverrideSensorOrientation
                || cameraCompatMode.mShouldLetterboxForCameraCompat
                || cameraCompatMode.mDisplayRotationSandbox != ROTATION_UNDEFINED;
    }

    /** Changes the WindowConfiguration display rotation for the given configuration. */
    public void applyToConfigurationIfNeeded(@NonNull Configuration inoutConfig) {
        if (mDisplayRotationSandbox != ROTATION_UNDEFINED) {
            inoutConfig.windowConfiguration.setDisplayRotation(mDisplayRotationSandbox);
        }
    }

    @Override
    public String toString() {
        return "CameraCompatibilityInfo{"
+53 −123
Original line number Diff line number Diff line
@@ -16,8 +16,8 @@

package android.content.res;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -36,10 +36,11 @@ import android.util.MergedConfiguration;
import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;

import java.util.Objects;

/**
 * CompatibilityInfo class keeps the information about the screen compatibility mode that the
 * application is running under.
@@ -48,6 +49,8 @@ import android.view.WindowManager.LayoutParams;
 */
@RavenwoodKeepWholeClass
public class CompatibilityInfo implements Parcelable {
    private static final String TAG = "CompatibilityInfo";

    /** default compatibility info object for compatible applications */
    @UnsupportedAppUsage
    public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo() {
@@ -133,38 +136,19 @@ public class CompatibilityInfo implements Parcelable {
    public final float applicationDensityInvertedScale;

    /**
     * Application's display rotation.
     *
     * <p>This field is used to sandbox fixed-orientation activities on displays or display areas
     * with ignoreOrientationRequest, where the display orientation is more likely to be different
     * from the orientation the activity requested (e.g. in desktop windowing, or letterboxed).
     * Mainly set for activities which use the display rotation to orient their content, for example
     * camera previews.
     *
     * <p>In the case of camera activities, assuming the wrong posture
     * can lead to sideways or stretched previews. As part of camera compat treatment for desktop
     * windowing, the app is sandboxed to believe that the app and the device are in the posture the
     * app requested. For example for portrait fixed-orientation apps, the app is letterboxed to
     * portrait, camera feed is cropped to portrait, and the display rotation is changed via this
     * field, for example to {@link Surface.Rotation#ROTATION_0} on devices with portrait natural
     * orientation. All of these parameters factor in common calculations for setting up the camera
     * preview.
     */
    @Surface.Rotation
    public int applicationDisplayRotation = WindowConfiguration.ROTATION_UNDEFINED;

    /**
     * Application's camera feed rotation (using rotate-and-crop).
     *
     * <p>This field is used to communicate to the camera framework by how many degrees the camera
     * feed should be rotated on the Camera HAL before it is sent to the app which uses the camera.
     * Information needed to set up camera compatibility mode.
     *
     * <p>Rotate-and-crop is a part of camera compat treatment, used to simulate an environment that
     * the current fixed-orientation app has requested. These apps often make assumptions about
     * device, camera, and window orientations, which are more decoupled on large screens.
     */
    @Surface.Rotation
    public int applicationCameraRotation = WindowConfiguration.ROTATION_UNDEFINED;
     * <p>CameraCompatibilityInfo is used to sandbox the environment for fixed-orientation camera
     * activities on displays or display areas with ignoreOrientationRequest, where the display
     * orientation is more likely to be different from the orientation the activity requested
     * (e.g. in desktop windowing, or letterboxed). This setup includes sandboxing display rotation,
     * rotating the camera preview on Camera HAL, letterboxing the activity, and changing the
     * camera sensor reported orientation. All of these parameters factor in common calculations for
     * setting up the camera preview, and assuming the wrong posture can lead to sideways or
     * stretched previews.
     */
    public CameraCompatibilityInfo cameraCompatibilityInfo = new CameraCompatibilityInfo.Builder()
            .build();

    /** The process level override inverted scale. See {@link #HAS_OVERRIDE_SCALING}. */
    private static float sOverrideInvertedScale = 1f;
@@ -172,13 +156,9 @@ public class CompatibilityInfo implements Parcelable {
    /** The process level override inverted density scale. See {@link #HAS_OVERRIDE_SCALING}. */
    private static float sOverrideDensityInvertScale = 1f;

    /** The process level override display rotation. */
    @Surface.Rotation
    private static int sOverrideDisplayRotation = WindowConfiguration.ROTATION_UNDEFINED;

    /** The process level camera rotate-and-crop rotation. */
    @Surface.Rotation
    private static int sOverrideCameraRotation = WindowConfiguration.ROTATION_UNDEFINED;
    /** The process level override for camera compat mode info. */
    private static CameraCompatibilityInfo sCameraCompatibilityInfo = new CameraCompatibilityInfo
            .Builder().build();

    @UnsupportedAppUsage
    @Deprecated
@@ -391,14 +371,11 @@ public class CompatibilityInfo implements Parcelable {
        return (mCompatibilityFlags & HAS_OVERRIDE_SCALING) != 0;
    }

    /** Returns {@code true} if {@link #sOverrideDisplayRotation} should be set. */
    public boolean isOverrideDisplayRotationRequired() {
        return applicationDisplayRotation != WindowConfiguration.ROTATION_UNDEFINED;
    }

    /** Returns {@code true} if {@link #sOverrideCameraRotation} should be set. */
    public boolean isOverrideCameraRotationRequired() {
        return applicationCameraRotation != WindowConfiguration.ROTATION_UNDEFINED;
    /**
     * Returns {@code true} if {@link #sCameraCompatibilityInfo} should be set.
     */
    public boolean isOverrideCameraCompatibilityInfoRequired() {
        return CameraCompatibilityInfo.isCameraCompatModeActive(cameraCompatibilityInfo);
    }

    @UnsupportedAppUsage
@@ -673,9 +650,7 @@ public class CompatibilityInfo implements Parcelable {
    }

    public void applyToConfiguration(int displayDensity, Configuration inoutConfig) {
        if (hasOverrideDisplayRotation()) {
            applyDisplayRotationConfiguration(sOverrideDisplayRotation, inoutConfig);
        }
        sCameraCompatibilityInfo.applyToConfigurationIfNeeded(inoutConfig);
        if (hasOverrideScale()) return;
        if (!supportsScreen()) {
            // This is a larger screen device and the app is not
@@ -708,19 +683,9 @@ public class CompatibilityInfo implements Parcelable {
        inoutConfig.windowConfiguration.scale(invertScale);
    }

    /** Changes the WindowConfiguration display rotation for the given configuration. */
    public static void applyDisplayRotationConfiguration(@Surface.Rotation int displayRotation,
            Configuration inoutConfig) {
        if (displayRotation != WindowConfiguration.ROTATION_UNDEFINED) {
            inoutConfig.windowConfiguration.setDisplayRotation(displayRotation);
        }
    }

    /** @see #sOverrideInvertedScale and #sOverrideDisplayRotation. */
    public static void applyOverrideIfNeeded(Configuration config) {
        if (hasOverrideDisplayRotation()) {
            applyDisplayRotationConfiguration(sOverrideDisplayRotation, config);
        }
        sCameraCompatibilityInfo.applyToConfigurationIfNeeded(config);
        if (hasOverrideScale()) {
            scaleConfiguration(sOverrideInvertedScale, sOverrideDensityInvertScale, config);
        }
@@ -728,14 +693,13 @@ public class CompatibilityInfo implements Parcelable {

    /** @see #sOverrideInvertedScale and #sOverrideDisplayRotation. */
    public static void applyOverrideIfNeeded(MergedConfiguration mergedConfig) {
        if (hasOverrideDisplayRotation()) {
            applyDisplayRotationConfiguration(sOverrideDisplayRotation,
                    mergedConfig.getGlobalConfiguration());
            applyDisplayRotationConfiguration(sOverrideDisplayRotation,
                    mergedConfig.getOverrideConfiguration());
            applyDisplayRotationConfiguration(sOverrideDisplayRotation,
                    mergedConfig.getMergedConfiguration());
        }
        sCameraCompatibilityInfo.applyToConfigurationIfNeeded(mergedConfig
                .getGlobalConfiguration());
        sCameraCompatibilityInfo.applyToConfigurationIfNeeded(mergedConfig
                .getOverrideConfiguration());
        sCameraCompatibilityInfo.applyToConfigurationIfNeeded(mergedConfig
                .getMergedConfiguration());

        if (hasOverrideScale()) {
            scaleConfiguration(sOverrideInvertedScale, sOverrideDensityInvertScale,
                    mergedConfig.getGlobalConfiguration());
@@ -772,29 +736,20 @@ public class CompatibilityInfo implements Parcelable {
        return sOverrideDensityInvertScale;
    }

    /** Returns {@code true} if this process is in a environment with override display rotation. */
    private static boolean hasOverrideDisplayRotation() {
        return sOverrideDisplayRotation != WindowConfiguration.ROTATION_UNDEFINED;
    }

    /** @see #sOverrideDisplayRotation */
    public static void setOverrideDisplayRotation(@Surface.Rotation int displayRotation) {
        sOverrideDisplayRotation = displayRotation;
    }

    /** @see #sOverrideDisplayRotation */
    public static int getOverrideDisplayRotation() {
        return sOverrideDisplayRotation;
    /** @see #sCameraCompatibilityInfo */
    public static void setCameraCompatibilityInfo(@NonNull CameraCompatibilityInfo
            cameraCompatibilityInfo) {
        sCameraCompatibilityInfo = cameraCompatibilityInfo;
    }

    /** @see #sOverrideCameraRotation */
    public static void setOverrideCameraRotation(@Surface.Rotation int cameraRotation) {
        sOverrideCameraRotation = cameraRotation;
    /** @see #sCameraCompatibilityInfo */
    public static void resetCameraCompatibilityInfo() {
        sCameraCompatibilityInfo = new CameraCompatibilityInfo.Builder().build();
    }

    /** @see #sOverrideCameraRotation */
    public static int getOverrideCameraRotation() {
        return sOverrideCameraRotation;
    /** @see #sCameraCompatibilityInfo */
    public static CameraCompatibilityInfo getCameraCompatibilityInfo() {
        return sCameraCompatibilityInfo;
    }

    /**
@@ -858,8 +813,7 @@ public class CompatibilityInfo implements Parcelable {

        if (!isCompatibilityFlagsEqual(oc)) return false;
        if (!isScaleEqual(oc)) return false;
        if (!isDisplayRotationEqual(oc)) return false;
        if (!isCameraRotationEqual(oc)) return false;
        if (!isCameraCompatibilityInfoEqual(oc)) return false;
        return true;
    }

@@ -869,10 +823,7 @@ public class CompatibilityInfo implements Parcelable {
     */
    public int getCompatibilityChangesForConfig(@Nullable CompatibilityInfo o) {
        int changes = 0;
        if (!isDisplayRotationEqual(o)) {
            changes |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
        }
        if (!isCameraRotationEqual(o)) {
        if (!isCameraCompatibilityInfoEqual(o)) {
            changes |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
        }
        if (!isScaleEqual(o) || !isCompatibilityFlagsEqual(o)) {
@@ -893,12 +844,8 @@ public class CompatibilityInfo implements Parcelable {
        return true;
    }

    private boolean isDisplayRotationEqual(@Nullable CompatibilityInfo oc) {
        return oc != null && oc.applicationDisplayRotation == applicationDisplayRotation;
    }

    private boolean isCameraRotationEqual(@Nullable CompatibilityInfo oc) {
        return oc != null && oc.applicationCameraRotation == applicationCameraRotation;
    private boolean isCameraCompatibilityInfoEqual(@Nullable CompatibilityInfo oc) {
        return oc != null && Objects.equals(oc.cameraCompatibilityInfo, cameraCompatibilityInfo);
    }

    private boolean isCompatibilityFlagsEqual(@Nullable CompatibilityInfo oc) {
@@ -922,14 +869,9 @@ public class CompatibilityInfo implements Parcelable {
            sb.append(" overrideDensityInvScale=");
            sb.append(applicationDensityInvertedScale);
        }
        if (isOverrideDisplayRotationRequired()) {
            sb.append(" overrideDisplayRotation=");
            sb.append(applicationDisplayRotation);
        }
        if (com.android.window.flags.Flags.enableCameraCompatCompatibilityInfoRotateAndCropBugfix()
                && isOverrideCameraRotationRequired()) {
            sb.append(" overrideCameraRotation=");
            sb.append(applicationCameraRotation);
        if (isOverrideCameraCompatibilityInfoRequired()) {
            sb.append(" cameraCompatibilityInfo=");
            sb.append(cameraCompatibilityInfo);
        }
        if (!supportsScreen()) {
            sb.append(" resizing");
@@ -953,11 +895,7 @@ public class CompatibilityInfo implements Parcelable {
        result = 31 * result + Float.floatToIntBits(applicationInvertedScale);
        result = 31 * result + Float.floatToIntBits(applicationDensityScale);
        result = 31 * result + Float.floatToIntBits(applicationDensityInvertedScale);
        result = 31 * result + applicationDisplayRotation;
        if (com.android.window.flags.Flags
                .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            result = 31 * result + applicationCameraRotation;
        }
        result = 31 * result + cameraCompatibilityInfo.hashCode();
        return result;
    }

@@ -974,11 +912,7 @@ public class CompatibilityInfo implements Parcelable {
        dest.writeFloat(applicationInvertedScale);
        dest.writeFloat(applicationDensityScale);
        dest.writeFloat(applicationDensityInvertedScale);
        dest.writeInt(applicationDisplayRotation);
        if (com.android.window.flags.Flags
                .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            dest.writeInt(applicationCameraRotation);
        }
        dest.writeTypedObject(cameraCompatibilityInfo, 0);
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -1002,11 +936,7 @@ public class CompatibilityInfo implements Parcelable {
        applicationInvertedScale = source.readFloat();
        applicationDensityScale = source.readFloat();
        applicationDensityInvertedScale = source.readFloat();
        applicationDisplayRotation = source.readInt();
        if (com.android.window.flags.Flags
                .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            applicationCameraRotation = source.readInt();
        }
        cameraCompatibilityInfo = source.readTypedObject(CameraCompatibilityInfo.CREATOR);
    }

    /**
+24 −18
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.hardware.camera2;

import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_INVALID;
@@ -45,6 +46,7 @@ import android.content.AttributionSource;
import android.content.AttributionSourceState;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.CameraCompatibilityInfo;
import android.content.res.CompatibilityInfo;
import android.graphics.Point;
import android.hardware.CameraExtensionSessionStats;
@@ -774,9 +776,7 @@ public final class CameraManager {
    public CameraCharacteristics getCameraCharacteristics(@NonNull String cameraId,
            boolean overrideToPortrait) throws CameraAccessException {
        return getCameraCharacteristics(cameraId,
                overrideToPortrait
                        ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                        : ICameraService.ROTATION_OVERRIDE_NONE);
                getLandscapeToPortraitOverride(overrideToPortrait));
    }

    @NonNull
@@ -1314,9 +1314,8 @@ public final class CameraManager {
            @NonNull final CameraDevice.StateCallback callback) throws CameraAccessException {
        openCameraImpl(cameraId, callback, CameraDeviceImpl.checkAndWrapHandler(handler),
                         /*oomScoreOffset*/ 0,
                         overrideToPortrait
                                 ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                                 : ICameraService.ROTATION_OVERRIDE_NONE, /*sharedMode*/false);
                         getLandscapeToPortraitOverride(overrideToPortrait),
                         /*sharedMode*/ false);
    }

    /**
@@ -1705,10 +1704,9 @@ public final class CameraManager {

        if (com.android.window.flags.Flags
                .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            final int simulateReqOrientationOverride = getRotationOverrideForCompatFreeform(
                    CompatibilityInfo.getOverrideCameraRotation());
            if (simulateReqOrientationOverride != ICameraService.ROTATION_OVERRIDE_NONE) {
                return simulateReqOrientationOverride;
            if (isCameraCompatModeRequested()) {
                return getRotationOverrideForCompatFreeform(CompatibilityInfo
                        .getCameraCompatibilityInfo().getRotateAndCropRotation());
            }
        } else {
            // Isolated process does not have access to ActivityTaskManager service, which is used
@@ -1736,21 +1734,29 @@ public final class CameraManager {

        if (packageManager != null && packageName != null) {
            try {
                return packageManager.getProperty(
                        PackageManager.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT,
                        packageName).getBoolean()
                        ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                        : ICameraService.ROTATION_OVERRIDE_NONE;
                return getLandscapeToPortraitOverride(packageManager.getProperty(
                        PackageManager.PROPERTY_COMPAT_OVERRIDE_LANDSCAPE_TO_PORTRAIT, packageName)
                        .getBoolean());
            } catch (PackageManager.NameNotFoundException e) {
                // No such property
            }
        }

        return CompatChanges.isChangeEnabled(OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT)
                ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
        return getLandscapeToPortraitOverride(CompatChanges.isChangeEnabled(
                OVERRIDE_CAMERA_LANDSCAPE_TO_PORTRAIT));
    }

    private static int getLandscapeToPortraitOverride(boolean shouldOverride) {
        return shouldOverride ? ICameraService.ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT
                : ICameraService.ROTATION_OVERRIDE_NONE;
    }

    private static boolean isCameraCompatModeRequested() {
        final CameraCompatibilityInfo compatInfo = CompatibilityInfo.getCameraCompatibilityInfo();
        return compatInfo.getRotateAndCropRotation() != ROTATION_UNDEFINED
                || compatInfo.shouldOverrideSensorOrientation();
    }

    private static boolean isInCameraCompatMode(@CameraCompatTaskInfo.CameraCompatMode int
            cameraCompatMode) {
        return (cameraCompatMode != CameraCompatTaskInfo.CAMERA_COMPAT_UNSPECIFIED)
+4 −2
Original line number Diff line number Diff line
@@ -172,10 +172,12 @@ public abstract class OrientationEventListener {
            // camera open and it is in camera compat mode for desktop windowing (freeform mode).
            // Values of this override is Surface.ROTATION_0/90/180/270, or
            // WindowConfiguration.ROTATION_UNDEFINED when not set.
            if (CompatibilityInfo.getOverrideDisplayRotation() != ROTATION_UNDEFINED) {
            final int sandboxedDisplayRotation = CompatibilityInfo.getCameraCompatibilityInfo()
                    .getDisplayRotationSandbox();
            if (sandboxedDisplayRotation != ROTATION_UNDEFINED) {
                // SensorEventListener reports the rotation in the opposite direction from the
                // display rotation.
                int orientation = (360 - CompatibilityInfo.getOverrideDisplayRotation() * 90) % 360;
                int orientation = (360 - sandboxedDisplayRotation * 90) % 360;
                if (orientation != mOrientation) {
                    mOrientation = orientation;
                    onOrientationChanged(orientation);
Loading