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

Commit 97f8a2ab authored by Mina Granic's avatar Mina Granic
Browse files

Use CompatibilityInfo to pass camera rotateAndCrop degrees.

The benefits of this approach are:
- Execution time of this check reduced from 18ms to 5 micros (3000x).
- Consolidates data in an already used data source (CompatibilityInfo).
- Removes the need for the CameraCompatTaskInfo object, thus slightly speeding up recomputing TaskInfo#getTaskInfo() every time.
- Improved testability for CameraManager, as there is no need for task/activity setup.

Flag: com.android.window.flags.enable_camera_compat_compatibility_info_rotate_and_crop_bugfix
Test: atest WmTests:AppCompatUtilsTest
Test: atest WmTests:CameraCompatFreeformPolicyTests
Test: manual
Bug: 430274604
Bug: 429295361
Change-Id: Ib1337312caabb43896822a0e71ecd5ed8e7f19ce
parent 425d7d4b
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -1447,6 +1447,7 @@ public final class ActivityThread extends ClientTransactionHandler
            data.startRequestedUptime = startRequestedUptime;
            updateCompatOverrideScale(compatInfo);
            updateCompatOverrideDisplayRotation(compatInfo);
            updateCompatOverrideCameraRotation(compatInfo);
            CompatibilityInfo.applyOverrideIfNeeded(config);
            sendMessage(H.BIND_APPLICATION, data);
        }
@@ -1470,6 +1471,18 @@ public final class ActivityThread extends ClientTransactionHandler
            }
        }

        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);
                }
            }
        }

        @Override
        public final void runIsolatedEntryPoint(String entryPoint, String[] entryPointArgs) {
            SomeArgs args = SomeArgs.obtain();
@@ -2173,6 +2186,7 @@ public final class ActivityThread extends ClientTransactionHandler
            ucd.info = info;
            updateCompatOverrideScale(info);
            updateCompatOverrideDisplayRotation(info);
            updateCompatOverrideCameraRotation(info);
            sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
        }

+4 −2
Original line number Diff line number Diff line
@@ -32,6 +32,8 @@ import android.view.Surface;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

// TODO(b/430274604): Remove after WindowManager -> Camera Framework communication for camera compat
// moves to CompatibilityInfo.
/**
 * Stores Camera Compat information about a particular Task.
 * @hide
@@ -91,7 +93,7 @@ public class CameraCompatTaskInfo implements Parcelable {
     */
    // TODO(b/414347702): Revisit data structure.
    @FreeformCameraCompatMode
    public int freeformCameraCompatMode;
    public int freeformCameraCompatMode = CAMERA_COMPAT_FREEFORM_UNSPECIFIED;

    /**
     * Real display rotation, never affected by camera compat sandboxing.
@@ -100,7 +102,7 @@ public class CameraCompatTaskInfo implements Parcelable {
     */
    // TODO(b/414347702): Revisit data structure.
    @Surface.Rotation
    public int displayRotation;
    public int displayRotation = ROTATION_UNDEFINED;

    private CameraCompatTaskInfo() {
        // Do nothing
+58 −1
Original line number Diff line number Diff line
@@ -153,6 +153,19 @@ public class CompatibilityInfo implements Parcelable {
    @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.
     *
     * <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;

    /** The process level override inverted scale. See {@link #HAS_OVERRIDE_SCALING}. */
    private static float sOverrideInvertedScale = 1f;

@@ -163,6 +176,10 @@ public class CompatibilityInfo implements Parcelable {
    @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;

    @UnsupportedAppUsage
    @Deprecated
    public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
@@ -379,6 +396,11 @@ public class CompatibilityInfo implements Parcelable {
        return applicationDisplayRotation != WindowConfiguration.ROTATION_UNDEFINED;
    }

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

    @UnsupportedAppUsage
    public boolean supportsScreen() {
        return (mCompatibilityFlags&NEEDS_SCREEN_COMPAT) == 0;
@@ -755,7 +777,7 @@ public class CompatibilityInfo implements Parcelable {
        return sOverrideDisplayRotation != WindowConfiguration.ROTATION_UNDEFINED;
    }

    /** @see #sOverrideInvertedScale */
    /** @see #sOverrideDisplayRotation */
    public static void setOverrideDisplayRotation(@Surface.Rotation int displayRotation) {
        sOverrideDisplayRotation = displayRotation;
    }
@@ -765,6 +787,16 @@ public class CompatibilityInfo implements Parcelable {
        return sOverrideDisplayRotation;
    }

    /** @see #sOverrideCameraRotation */
    public static void setOverrideCameraRotation(@Surface.Rotation int cameraRotation) {
        sOverrideCameraRotation = cameraRotation;
    }

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

    /**
     * Compute the frame Rect for applications runs under compatibility mode.
     *
@@ -827,6 +859,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;
        return true;
    }

@@ -839,6 +872,9 @@ public class CompatibilityInfo implements Parcelable {
        if (!isDisplayRotationEqual(o)) {
            changes |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
        }
        if (!isCameraRotationEqual(o)) {
            changes |= ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
        }
        if (!isScaleEqual(o) || !isCompatibilityFlagsEqual(o)) {
            changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
                    | ActivityInfo.CONFIG_SCREEN_SIZE
@@ -861,6 +897,10 @@ public class CompatibilityInfo implements Parcelable {
        return oc != null && oc.applicationDisplayRotation == applicationDisplayRotation;
    }

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

    private boolean isCompatibilityFlagsEqual(@Nullable CompatibilityInfo oc) {
        return oc != null && oc.mCompatibilityFlags == mCompatibilityFlags;
    }
@@ -886,6 +926,11 @@ public class CompatibilityInfo implements Parcelable {
            sb.append(" overrideDisplayRotation=");
            sb.append(applicationDisplayRotation);
        }
        if (com.android.window.flags.Flags.enableCameraCompatCompatibilityInfoRotateAndCropBugfix()
                && isOverrideCameraRotationRequired()) {
            sb.append(" overrideCameraRotation=");
            sb.append(applicationCameraRotation);
        }
        if (!supportsScreen()) {
            sb.append(" resizing");
        }
@@ -909,6 +954,10 @@ public class CompatibilityInfo implements Parcelable {
        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;
        }
        return result;
    }

@@ -926,6 +975,10 @@ public class CompatibilityInfo implements Parcelable {
        dest.writeFloat(applicationDensityScale);
        dest.writeFloat(applicationDensityInvertedScale);
        dest.writeInt(applicationDisplayRotation);
        if (com.android.window.flags.Flags
                .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            dest.writeInt(applicationCameraRotation);
        }
    }

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -950,6 +1003,10 @@ public class CompatibilityInfo implements Parcelable {
        applicationDensityScale = source.readFloat();
        applicationDensityInvertedScale = source.readFloat();
        applicationDisplayRotation = source.readInt();
        if (com.android.window.flags.Flags
                .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            applicationCameraRotation = source.readInt();
        }
    }

    /**
+38 −15
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import android.content.AttributionSource;
import android.content.AttributionSourceState;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.graphics.Point;
import android.hardware.CameraExtensionSessionStats;
import android.hardware.CameraStatus;
@@ -1721,10 +1722,19 @@ public final class CameraManager {
            return ICameraService.ROTATION_OVERRIDE_NONE;
        }

        if (com.android.window.flags.Flags
                .enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            final int simulateReqOrientationOverride = getRotationOverrideForCompatFreeform(
                    CompatibilityInfo.getOverrideCameraRotation());
            if (simulateReqOrientationOverride != ICameraService.ROTATION_OVERRIDE_NONE) {
                return simulateReqOrientationOverride;
            }
        } else {
            // Isolated process does not have access to ActivityTaskManager service, which is used
            // indirectly in `ActivityManager.getAppTasks()`.
            if (context != null && !Process.isIsolated()) {
            final ActivityManager activityManager = context.getSystemService(ActivityManager.class);
                final ActivityManager activityManager = context.getSystemService(
                        ActivityManager.class);
                if (activityManager != null) {
                    for (ActivityManager.AppTask appTask : activityManager.getAppTasks()) {
                        final TaskInfo taskInfo = appTask.getTaskInfo();
@@ -1735,7 +1745,9 @@ public final class CameraManager {
                                && taskInfo.topActivity.getPackageName().equals(packageName)) {
                            // WindowManager has requested rotation override.
                            return getRotationOverrideForCompatFreeform(freeformCameraCompatMode,
                                taskInfo.appCompatTaskInfo.cameraCompatTaskInfo.displayRotation);
                                    taskInfo.appCompatTaskInfo.cameraCompatTaskInfo
                                            .displayRotation);
                        }
                    }
                }
            }
@@ -1764,6 +1776,17 @@ public final class CameraManager {
                && (freeformCameraCompatMode != CameraCompatTaskInfo.CAMERA_COMPAT_FREEFORM_NONE);
    }

    private static int getRotationOverrideForCompatFreeform(
            @Surface.Rotation int requestedRotation) {
        if (requestedRotation == ROTATION_90) {
            return ICameraService.ROTATION_OVERRIDE_ROTATION_ONLY;
        } else if (requestedRotation == ROTATION_270) {
            return ICameraService.ROTATION_OVERRIDE_ROTATION_ONLY_REVERSE;
        } else {
            return ICameraService.ROTATION_OVERRIDE_NONE;
        }
    }

    private static int getRotationOverrideForCompatFreeform(
            @CameraCompatTaskInfo.FreeformCameraCompatMode int freeformCameraCompatMode,
            @Surface.Rotation int displayRotation) {
+9 −5
Original line number Diff line number Diff line
@@ -229,11 +229,15 @@ final class AppCompatUtils {
                !info.isTopActivityTransparent && !appCompatTaskInfo.isTopActivityInSizeCompat()
                        && aspectRatioOverrides.shouldEnableUserAspectRatioSettings();
        appCompatTaskInfo.setEligibleForUserAspectRatioButton(eligibleForAspectRatioButton);
        // Obsolete way of sending camera compat mode data to CameraManager.
        if (!Flags.enableCameraCompatCompatibilityInfoRotateAndCropBugfix()) {
            appCompatTaskInfo.cameraCompatTaskInfo.freeformCameraCompatMode =
                    AppCompatCameraPolicy.getCameraCompatFreeformMode(top);
            appCompatTaskInfo.cameraCompatTaskInfo.displayRotation =
                    Flags.enableCameraCompatCheckDeviceRotationBugfix()
                        ? AppCompatCameraPolicy.getCameraDeviceRotation(top) : ROTATION_UNDEFINED;
                            ? AppCompatCameraPolicy.getCameraDeviceRotation(top)
                            : ROTATION_UNDEFINED;
        }
        appCompatTaskInfo.setHasMinAspectRatioOverride(top.mAppCompatController
                .getDesktopAspectRatioPolicy().hasMinAspectRatioOverride(task));
        appCompatTaskInfo.setOptOutEdgeToEdge(top.mOptOutEdgeToEdge);
Loading