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

Commit 11a268ad authored by Mina Karadzic's avatar Mina Karadzic
Browse files

Clearly signal to Camera FW whether to apply inverse display transform.

Inverse display transform rotates the preview based on the display rotation, so the app doesn't need to apply the display rotation offset.

However, when display rotation is sandboxed, this transform doesn't work well. This flag is already disabled for camera compat, but this data is extracted from other parameters of camera compat mode - this change is making it explicit.

What's more, when display rotation is sandboxed for external displays, neither of camera-related CameraCompatiblityInfo fields are changed (rotate-and-crop and sensor orientation) - Camera FW could check that display rotation has been sandboxed via this object, but ideally Camera FW should not hold this kind of logic.

Flag: com.android.window.flags.enable_camera_compat_sandbox_display_rotation_on_external_displays_bugfix
Bug: 395063101
Test: atest WmTests:AppCompatCameraSimReqOrientationPolicyTests
Test: atest CameraCompatibilityInfoTest
Change-Id: Ib7df281c1b8b902b6de191fb6cde280e0f3ca06e
parent 96f6c51e
Loading
Loading
Loading
Loading
+8 −6
Original line number Original line Diff line number Diff line
@@ -1329,19 +1329,21 @@ package android.content.res {
    method public int getDisplayRotationSandbox();
    method public int getDisplayRotationSandbox();
    method public int getRotateAndCropRotation();
    method public int getRotateAndCropRotation();
    method public static boolean isCameraCompatModeActive(@NonNull android.content.res.CameraCompatibilityInfo);
    method public static boolean isCameraCompatModeActive(@NonNull android.content.res.CameraCompatibilityInfo);
    method public boolean shouldAllowTransformInverseDisplay();
    method public boolean shouldLetterboxForCameraCompat();
    method public boolean shouldLetterboxForCameraCompat();
    method public boolean shouldOverrideSensorOrientation();
    method public boolean shouldOverrideSensorOrientation();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.content.res.CameraCompatibilityInfo> CREATOR;
    field @NonNull public static final android.os.Parcelable.Creator<android.content.res.CameraCompatibilityInfo> CREATOR;
  }
  }


  public static final class CameraCompatibilityInfo.Builder {
  public static final class CameraCompatibilityInfo.Builder {
    ctor public CameraCompatibilityInfo.Builder();
    ctor public CameraCompatibilityInfo.Builder();
    method public android.content.res.CameraCompatibilityInfo build();
    method @NonNull public android.content.res.CameraCompatibilityInfo build();
    method public android.content.res.CameraCompatibilityInfo.Builder setDisplayRotationSandbox(int);
    method @NonNull public android.content.res.CameraCompatibilityInfo.Builder setDisplayRotationSandbox(int);
    method public android.content.res.CameraCompatibilityInfo.Builder setRotateAndCropRotation(int);
    method @NonNull public android.content.res.CameraCompatibilityInfo.Builder setRotateAndCropRotation(int);
    method public android.content.res.CameraCompatibilityInfo.Builder setShouldLetterboxForCameraCompat(boolean);
    method @NonNull public android.content.res.CameraCompatibilityInfo.Builder setShouldAllowTransformInverseDisplay(boolean);
    method public android.content.res.CameraCompatibilityInfo.Builder setShouldOverrideSensorOrientation(boolean);
    method @NonNull public android.content.res.CameraCompatibilityInfo.Builder setShouldLetterboxForCameraCompat(boolean);
    method @NonNull public android.content.res.CameraCompatibilityInfo.Builder setShouldOverrideSensorOrientation(boolean);
  }
  }


  public final class Configuration implements java.lang.Comparable<android.content.res.Configuration> android.os.Parcelable {
  public final class Configuration implements java.lang.Comparable<android.content.res.Configuration> android.os.Parcelable {
+4 −12
Original line number Original line Diff line number Diff line
@@ -541,18 +541,6 @@ KotlinKeyword: android.app.Notification#when:


MissingNullability: android.app.AppDetailsActivity#onCreate(android.os.Bundle) parameter #0:
MissingNullability: android.app.AppDetailsActivity#onCreate(android.os.Bundle) parameter #0:
    Missing nullability on parameter `savedInstanceState` in method `onCreate`
    Missing nullability on parameter `savedInstanceState` in method `onCreate`
MissingNullability: android.content.res.CameraCompatibilityInfo#CREATOR:
    Missing nullability on field `CREATOR` in class `class android.content.res.CameraCompatibilityInfo`
MissingNullability: android.content.res.CameraCompatibilityInfo.Builder#build():
    Missing nullability on method `build` return
MissingNullability: android.content.res.CameraCompatibilityInfo.Builder#setDisplayRotationSandbox(int):
    Missing nullability on method `setDisplayRotationSandbox` return
MissingNullability: android.content.res.CameraCompatibilityInfo.Builder#setRotateAndCropRotation(int):
    Missing nullability on method `setRotateAndCropRotation` return
MissingNullability: android.content.res.CameraCompatibilityInfo.Builder#setShouldLetterboxForCameraCompat(boolean):
    Missing nullability on method `setShouldLetterboxForCameraCompat` return
MissingNullability: android.content.res.CameraCompatibilityInfo.Builder#setShouldOverrideSensorOrientation(boolean):
    Missing nullability on method `setShouldOverrideSensorOrientation` return
MissingNullability: android.hardware.camera2.CameraManager#getRotationOverride(android.content.Context, android.content.pm.PackageManager, String):
MissingNullability: android.hardware.camera2.CameraManager#getRotationOverride(android.content.Context, android.content.pm.PackageManager, String):
    Missing nullability on method `getRotationOverride` return
    Missing nullability on method `getRotationOverride` return
MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHintIdEntry(String) parameter #0:
MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHintIdEntry(String) parameter #0:
@@ -2131,6 +2119,8 @@ UnflaggedApi: android.content.res.CameraCompatibilityInfo#getRotateAndCropRotati
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.getRotateAndCropRotation()
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.getRotateAndCropRotation()
UnflaggedApi: android.content.res.CameraCompatibilityInfo#isCameraCompatModeActive(android.content.res.CameraCompatibilityInfo):
UnflaggedApi: android.content.res.CameraCompatibilityInfo#isCameraCompatModeActive(android.content.res.CameraCompatibilityInfo):
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.isCameraCompatModeActive(android.content.res.CameraCompatibilityInfo)
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.isCameraCompatModeActive(android.content.res.CameraCompatibilityInfo)
UnflaggedApi: android.content.res.CameraCompatibilityInfo#shouldAllowTransformInverseDisplay():
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.shouldAllowTransformInverseDisplay()
UnflaggedApi: android.content.res.CameraCompatibilityInfo#shouldLetterboxForCameraCompat():
UnflaggedApi: android.content.res.CameraCompatibilityInfo#shouldLetterboxForCameraCompat():
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.shouldLetterboxForCameraCompat()
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.shouldLetterboxForCameraCompat()
UnflaggedApi: android.content.res.CameraCompatibilityInfo#shouldOverrideSensorOrientation():
UnflaggedApi: android.content.res.CameraCompatibilityInfo#shouldOverrideSensorOrientation():
@@ -2147,6 +2137,8 @@ UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setDisplayRota
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.Builder.setDisplayRotationSandbox(int)
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.Builder.setDisplayRotationSandbox(int)
UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setRotateAndCropRotation(int):
UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setRotateAndCropRotation(int):
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.Builder.setRotateAndCropRotation(int)
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.Builder.setRotateAndCropRotation(int)
UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setShouldAllowTransformInverseDisplay(boolean):
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.Builder.setShouldAllowTransformInverseDisplay(boolean)
UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setShouldLetterboxForCameraCompat(boolean):
UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setShouldLetterboxForCameraCompat(boolean):
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.Builder.setShouldLetterboxForCameraCompat(boolean)
    New API must be flagged with @FlaggedApi: method android.content.res.CameraCompatibilityInfo.Builder.setShouldLetterboxForCameraCompat(boolean)
UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setShouldOverrideSensorOrientation(boolean):
UnflaggedApi: android.content.res.CameraCompatibilityInfo.Builder#setShouldOverrideSensorOrientation(boolean):
+45 −3
Original line number Original line Diff line number Diff line
@@ -51,12 +51,14 @@ public final class CameraCompatibilityInfo implements Parcelable {
    private final boolean mShouldOverrideSensorOrientation;
    private final boolean mShouldOverrideSensorOrientation;
    private final boolean mShouldLetterboxForCameraCompat;
    private final boolean mShouldLetterboxForCameraCompat;
    private final int mDisplayRotationSandbox;
    private final int mDisplayRotationSandbox;
    private final boolean mShouldAllowTransformInverseDisplay;


    private CameraCompatibilityInfo(Builder builder) {
    private CameraCompatibilityInfo(Builder builder) {
        mRotateAndCropRotation = builder.mRotateAndCropRotation;
        mRotateAndCropRotation = builder.mRotateAndCropRotation;
        mShouldOverrideSensorOrientation = builder.mShouldOverrideSensorOrientation;
        mShouldOverrideSensorOrientation = builder.mShouldOverrideSensorOrientation;
        mShouldLetterboxForCameraCompat = builder.mShouldLetterboxForCameraCompat;
        mShouldLetterboxForCameraCompat = builder.mShouldLetterboxForCameraCompat;
        mDisplayRotationSandbox = builder.mDisplayRotationSandbox;
        mDisplayRotationSandbox = builder.mDisplayRotationSandbox;
        mShouldAllowTransformInverseDisplay = builder.mShouldAllowTransformInverseDisplay;
    }
    }


    private CameraCompatibilityInfo(Parcel in) {
    private CameraCompatibilityInfo(Parcel in) {
@@ -64,6 +66,7 @@ public final class CameraCompatibilityInfo implements Parcelable {
        mShouldOverrideSensorOrientation = in.readByte() != 0;
        mShouldOverrideSensorOrientation = in.readByte() != 0;
        mShouldLetterboxForCameraCompat = in.readByte() != 0;
        mShouldLetterboxForCameraCompat = in.readByte() != 0;
        mDisplayRotationSandbox = in.readInt();
        mDisplayRotationSandbox = in.readInt();
        mShouldAllowTransformInverseDisplay = in.readByte() != 0;
    }
    }


    /**
    /**
@@ -93,12 +96,25 @@ public final class CameraCompatibilityInfo implements Parcelable {
        return mDisplayRotationSandbox;
        return mDisplayRotationSandbox;
    }
    }


    /**
     * Whether rotating the camera buffers to counter the display rotation is allowed.
     *
     * <p> This value is often set to false when display rotation is sandboxed for compatibility.
     * Since this rotation is not real for the display, native transform can rotate the buffers
     * incorrectly. Additionally, for camera compat, display sandboxing and rotate-and-crop are
     * often applied together so the apps do not have to apply any display-based transformations.
     */
    public boolean shouldAllowTransformInverseDisplay() {
        return mShouldAllowTransformInverseDisplay;
    }

    /** Builder for {@link CameraCompatibilityInfo} */
    /** Builder for {@link CameraCompatibilityInfo} */
    public static final class Builder {
    public static final class Builder {
        private int mRotateAndCropRotation = ROTATION_UNDEFINED;
        private int mRotateAndCropRotation = ROTATION_UNDEFINED;
        private boolean mShouldOverrideSensorOrientation = false;
        private boolean mShouldOverrideSensorOrientation = false;
        private boolean mShouldLetterboxForCameraCompat = false;
        private boolean mShouldLetterboxForCameraCompat = false;
        private int mDisplayRotationSandbox = ROTATION_UNDEFINED;
        private int mDisplayRotationSandbox = ROTATION_UNDEFINED;
        private boolean mShouldAllowTransformInverseDisplay = true;


        public Builder() {}
        public Builder() {}


@@ -107,12 +123,14 @@ public final class CameraCompatibilityInfo implements Parcelable {
         * `android.view.Surface.Rotation` enum. If none, the value is
         * `android.view.Surface.Rotation` enum. If none, the value is
         * `android.app.WindowConfiguration.ROTATION_UNDEFINED`.
         * `android.app.WindowConfiguration.ROTATION_UNDEFINED`.
         */
         */
        @NonNull
        public Builder setRotateAndCropRotation(int rotateAndCropRotation) {
        public Builder setRotateAndCropRotation(int rotateAndCropRotation) {
            mRotateAndCropRotation = rotateAndCropRotation;
            mRotateAndCropRotation = rotateAndCropRotation;
            return this;
            return this;
        }
        }


        /** Sets whether camera sensor orientation should be sandboxed (usually to portrait). */
        /** Sets whether camera sensor orientation should be sandboxed (usually to portrait). */
        @NonNull
        public Builder setShouldOverrideSensorOrientation(boolean shouldOverrideSensorOrientation) {
        public Builder setShouldOverrideSensorOrientation(boolean shouldOverrideSensorOrientation) {
            mShouldOverrideSensorOrientation = shouldOverrideSensorOrientation;
            mShouldOverrideSensorOrientation = shouldOverrideSensorOrientation;
            return this;
            return this;
@@ -122,6 +140,7 @@ public final class CameraCompatibilityInfo implements Parcelable {
         * Sets whether camera activity should be letterboxed, i.e. whether app bounds should be
         * Sets whether camera activity should be letterboxed, i.e. whether app bounds should be
         * changed.
         * changed.
         */
         */
        @NonNull
        public Builder setShouldLetterboxForCameraCompat(boolean shouldLetterboxForCameraCompat) {
        public Builder setShouldLetterboxForCameraCompat(boolean shouldLetterboxForCameraCompat) {
            mShouldLetterboxForCameraCompat = shouldLetterboxForCameraCompat;
            mShouldLetterboxForCameraCompat = shouldLetterboxForCameraCompat;
            return this;
            return this;
@@ -132,17 +151,36 @@ public final class CameraCompatibilityInfo implements Parcelable {
         *  should not be applied, the value should be
         *  should not be applied, the value should be
         *  `android.app.WindowConfiguration.ROTATION_UNDEFINED`.
         *  `android.app.WindowConfiguration.ROTATION_UNDEFINED`.
         */
         */
        @NonNull
        public Builder setDisplayRotationSandbox(int displayRotationSandbox) {
        public Builder setDisplayRotationSandbox(int displayRotationSandbox) {
            mDisplayRotationSandbox = displayRotationSandbox;
            mDisplayRotationSandbox = displayRotationSandbox;
            return this;
            return this;
        }
        }


        /**
         * Whether rotating the camera buffers to counter the display rotation is allowed.
         *
         * <p> This value is often set to {@code false} when display rotation is sandboxed for
         * compatibility. Since this rotation is not real for the display, native transform can
         * rotate the buffers incorrectly. Additionally, for camera compat, display sandboxing and
         * rotate-and-crop are often applied together so the apps do not have to apply any
         * display-based transformations.
         */
        @NonNull
        public Builder setShouldAllowTransformInverseDisplay(boolean
                shouldAllowTransformInverseDisplay) {
            mShouldAllowTransformInverseDisplay = shouldAllowTransformInverseDisplay;
            return this;
        }

        /** Builds a {@link CameraCompatibilityInfo} object. */
        /** Builds a {@link CameraCompatibilityInfo} object. */
        @NonNull
        public CameraCompatibilityInfo build() {
        public CameraCompatibilityInfo build() {
            return new CameraCompatibilityInfo(this);
            return new CameraCompatibilityInfo(this);
        }
        }
    }
    }


    @NonNull
    public static final Creator<CameraCompatibilityInfo> CREATOR =
    public static final Creator<CameraCompatibilityInfo> CREATOR =
            new Creator<CameraCompatibilityInfo>() {
            new Creator<CameraCompatibilityInfo>() {
                @Override
                @Override
@@ -167,13 +205,14 @@ public final class CameraCompatibilityInfo implements Parcelable {
        dest.writeBoolean(mShouldOverrideSensorOrientation);
        dest.writeBoolean(mShouldOverrideSensorOrientation);
        dest.writeBoolean(mShouldLetterboxForCameraCompat);
        dest.writeBoolean(mShouldLetterboxForCameraCompat);
        dest.writeInt(mDisplayRotationSandbox);
        dest.writeInt(mDisplayRotationSandbox);
        dest.writeBoolean(mShouldAllowTransformInverseDisplay);
    }
    }


    @Override
    @Override
    public int hashCode() {
    public int hashCode() {
        return Objects.hash(mRotateAndCropRotation,
        return Objects.hash(mRotateAndCropRotation,
                mShouldOverrideSensorOrientation, mShouldLetterboxForCameraCompat,
                mShouldOverrideSensorOrientation, mShouldLetterboxForCameraCompat,
                mDisplayRotationSandbox);
                mDisplayRotationSandbox, mShouldAllowTransformInverseDisplay);
    }
    }


    @Override
    @Override
@@ -187,7 +226,8 @@ public final class CameraCompatibilityInfo implements Parcelable {
        return mRotateAndCropRotation == that.mRotateAndCropRotation
        return mRotateAndCropRotation == that.mRotateAndCropRotation
                && mShouldOverrideSensorOrientation == that.mShouldOverrideSensorOrientation
                && mShouldOverrideSensorOrientation == that.mShouldOverrideSensorOrientation
                && mShouldLetterboxForCameraCompat == that.mShouldLetterboxForCameraCompat
                && mShouldLetterboxForCameraCompat == that.mShouldLetterboxForCameraCompat
                && mDisplayRotationSandbox == that.mDisplayRotationSandbox;
                && mDisplayRotationSandbox == that.mDisplayRotationSandbox
                && mShouldAllowTransformInverseDisplay == that.mShouldAllowTransformInverseDisplay;
    }
    }


    /** Whether any camera compat mode changes are requested via this object. */
    /** Whether any camera compat mode changes are requested via this object. */
@@ -196,7 +236,8 @@ public final class CameraCompatibilityInfo implements Parcelable {
        return cameraCompatMode.mRotateAndCropRotation != ROTATION_UNDEFINED
        return cameraCompatMode.mRotateAndCropRotation != ROTATION_UNDEFINED
                || cameraCompatMode.mShouldOverrideSensorOrientation
                || cameraCompatMode.mShouldOverrideSensorOrientation
                || cameraCompatMode.mShouldLetterboxForCameraCompat
                || cameraCompatMode.mShouldLetterboxForCameraCompat
                || cameraCompatMode.mDisplayRotationSandbox != ROTATION_UNDEFINED;
                || cameraCompatMode.mDisplayRotationSandbox != ROTATION_UNDEFINED
                || !cameraCompatMode.mShouldAllowTransformInverseDisplay;
    }
    }


    /** Changes the WindowConfiguration display rotation for the given configuration. */
    /** Changes the WindowConfiguration display rotation for the given configuration. */
@@ -213,6 +254,7 @@ public final class CameraCompatibilityInfo implements Parcelable {
                + ", mShouldOverrideSensorOrientation=" + mShouldOverrideSensorOrientation
                + ", mShouldOverrideSensorOrientation=" + mShouldOverrideSensorOrientation
                + ", mShouldLetterboxForCameraCompat=" + mShouldLetterboxForCameraCompat
                + ", mShouldLetterboxForCameraCompat=" + mShouldLetterboxForCameraCompat
                + ", mDisplayRotationSandbox=" + mDisplayRotationSandbox
                + ", mDisplayRotationSandbox=" + mDisplayRotationSandbox
                + ", mShouldAllowTransformInverseDisplay=" + mShouldAllowTransformInverseDisplay
                + '}';
                + '}';
    }
    }
}
}
+12 −0
Original line number Original line Diff line number Diff line
@@ -34,6 +34,8 @@ namespace res {
        parcel->writeBool(mShouldOverrideSensorOrientation);
        parcel->writeBool(mShouldOverrideSensorOrientation);
        parcel->writeBool(mShouldLetterboxForCameraCompat);
        parcel->writeBool(mShouldLetterboxForCameraCompat);
        parcel->writeInt32(mDisplayRotationSandbox.transform(ui::toRotationInt).value_or(-1));
        parcel->writeInt32(mDisplayRotationSandbox.transform(ui::toRotationInt).value_or(-1));
        parcel->writeBool(mShouldAllowTransformInverseDisplay);

        return OK;
        return OK;
    }
    }


@@ -56,6 +58,7 @@ namespace res {
        } else {
        } else {
            mDisplayRotationSandbox = ui::toRotation(tmpInt);
            mDisplayRotationSandbox = ui::toRotation(tmpInt);
        }
        }
        parcel->readBool(&mShouldAllowTransformInverseDisplay);
        return OK;
        return OK;
    }
    }


@@ -100,6 +103,15 @@ namespace res {
        mDisplayRotationSandbox = displayRotationSandbox;
        mDisplayRotationSandbox = displayRotationSandbox;
    }
    }


    bool CameraCompatibilityInfo::shouldAllowTransformInverseDisplay() const {
        return mShouldAllowTransformInverseDisplay;
    }

    void CameraCompatibilityInfo::setShouldAllowTransformInverseDisplay(bool
            shouldAllowTransformInverseDisplay) {
        mShouldAllowTransformInverseDisplay = shouldAllowTransformInverseDisplay;
    }

} // namespace res
} // namespace res
} // namespace content
} // namespace content
} // namespace android
} // namespace android
+5 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ private:
    bool mShouldOverrideSensorOrientation = false;
    bool mShouldOverrideSensorOrientation = false;
    bool mShouldLetterboxForCameraCompat = false;
    bool mShouldLetterboxForCameraCompat = false;
    std::optional<ui::Rotation> mDisplayRotationSandbox = std::nullopt;
    std::optional<ui::Rotation> mDisplayRotationSandbox = std::nullopt;
    bool mShouldAllowTransformInverseDisplay = true;


public:
public:
    virtual status_t writeToParcel(Parcel* parcel) const;
    virtual status_t writeToParcel(Parcel* parcel) const;
@@ -57,6 +58,10 @@ public:
    std::optional<ui::Rotation> getDisplayRotationSandbox() const;
    std::optional<ui::Rotation> getDisplayRotationSandbox() const;


    void setDisplayRotationSandbox(std::optional<ui::Rotation> displayRotationSandbox);
    void setDisplayRotationSandbox(std::optional<ui::Rotation> displayRotationSandbox);

    bool shouldAllowTransformInverseDisplay() const;

    void setShouldAllowTransformInverseDisplay(bool shouldAllowTransformInverseDisplay);
};
};


} // namespace res
} // namespace res
Loading