Camera: Plumb through stream mirroring mode

The stream mirroring mode is used to override the default flip for front
facing camera.

Test: Camera CTS
Bug: 200309079
Change-Id: I161875ccf33267686d54ba3c1c94b597032bd4e8
diff --git a/camera/CameraUtils.cpp b/camera/CameraUtils.cpp
index af3c492..3473780 100644
--- a/camera/CameraUtils.cpp
+++ b/camera/CameraUtils.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include <camera/CameraUtils.h>
+#include <camera/camera2/OutputConfiguration.h>
 #include <media/hardware/HardwareAPI.h>
 
 #include <android-base/properties.h>
@@ -31,7 +32,7 @@
 const char *kCameraServiceDisabledProperty = "config.disable_cameraservice";
 
 status_t CameraUtils::getRotationTransform(const CameraMetadata& staticInfo,
-                /*out*/int32_t* transform) {
+        int mirrorMode, /*out*/int32_t* transform) {
     ALOGV("%s", __FUNCTION__);
 
     if (transform == NULL) {
@@ -55,9 +56,18 @@
 
     int32_t& flags = *transform;
 
-    bool mirror = (entryFacing.data.u8[0] == ANDROID_LENS_FACING_FRONT);
+    int32_t mirror = 0;
+    if (mirrorMode == OutputConfiguration::MIRROR_MODE_AUTO &&
+            entryFacing.data.u8[0] == ANDROID_LENS_FACING_FRONT) {
+        mirror = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+    } else if (mirrorMode == OutputConfiguration::MIRROR_MODE_H) {
+        mirror = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+    } else if (mirrorMode == OutputConfiguration::MIRROR_MODE_V) {
+        mirror = NATIVE_WINDOW_TRANSFORM_FLIP_V;
+    }
+
     int orientation = entry.data.i32[0];
-    if (!mirror) {
+    if (mirror == 0) {
         switch (orientation) {
             case 0:
                 flags = 0;
@@ -77,25 +87,25 @@
                 return INVALID_OPERATION;
         }
     } else {
-        // Front camera needs to be horizontally flipped for mirror-like behavior.
+        // - Front camera needs to be horizontally flipped for mirror-like behavior.
+        // - Application-specified mirroring needs to be applied.
         // Note: Flips are applied before rotates; using XOR here as some of these flags are
         // composed in terms of other flip/rotation flags, and are not bitwise-ORable.
         switch (orientation) {
             case 0:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H;
+                flags = mirror;
                 break;
             case 90:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+                flags = mirror ^
                         NATIVE_WINDOW_TRANSFORM_ROT_270;
                 break;
             case 180:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+                flags = mirror ^
                         NATIVE_WINDOW_TRANSFORM_ROT_180;
                 break;
             case 270:
-                flags = NATIVE_WINDOW_TRANSFORM_FLIP_H ^
+                flags = mirror ^
                         NATIVE_WINDOW_TRANSFORM_ROT_90;
-
                 break;
             default:
                 ALOGE("%s: Invalid HAL android.sensor.orientation value: %d",
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index a16e747..4300f9a 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -89,6 +89,10 @@
     return mTimestampBase;
 }
 
+int OutputConfiguration::getMirrorMode() const {
+    return mMirrorMode;
+}
+
 OutputConfiguration::OutputConfiguration() :
         mRotation(INVALID_ROTATION),
         mSurfaceSetID(INVALID_SET_ID),
@@ -100,7 +104,8 @@
         mIsMultiResolution(false),
         mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
         mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
-        mTimestampBase(TIMESTAMP_BASE_DEFAULT) {
+        mTimestampBase(TIMESTAMP_BASE_DEFAULT),
+        mMirrorMode(MIRROR_MODE_AUTO) {
 }
 
 OutputConfiguration::OutputConfiguration(const android::Parcel& parcel) :
@@ -199,6 +204,12 @@
         return err;
     }
 
+    int mirrorMode = MIRROR_MODE_AUTO;
+    if ((err = parcel->readInt32(&mirrorMode)) != OK) {
+        ALOGE("%s: Failed to read mirroring mode from parcel", __FUNCTION__);
+        return err;
+    }
+
     mRotation = rotation;
     mSurfaceSetID = setID;
     mSurfaceType = surfaceType;
@@ -209,6 +220,7 @@
     mIsMultiResolution = isMultiResolution != 0;
     mStreamUseCase = streamUseCase;
     mTimestampBase = timestampBase;
+    mMirrorMode = mirrorMode;
     for (auto& surface : surfaceShims) {
         ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
                 surface.graphicBufferProducer.get(),
@@ -220,9 +232,11 @@
     mDynamicRangeProfile = dynamicProfile;
 
     ALOGV("%s: OutputConfiguration: rotation = %d, setId = %d, surfaceType = %d,"
-          " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d, timestampBase = %d",
+          " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %d, timestampBase = %d,"
+          " mirrorMode = %d",
           __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType,
-          String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase);
+          String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase,
+          mMirrorMode);
 
     return err;
 }
@@ -240,6 +254,7 @@
     mDynamicRangeProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD;
     mStreamUseCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
     mTimestampBase = TIMESTAMP_BASE_DEFAULT;
+    mMirrorMode = MIRROR_MODE_AUTO;
 }
 
 OutputConfiguration::OutputConfiguration(
@@ -251,7 +266,8 @@
     mPhysicalCameraId(physicalCameraId), mIsMultiResolution(false),
     mDynamicRangeProfile(ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD),
     mStreamUseCase(ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT),
-    mTimestampBase(TIMESTAMP_BASE_DEFAULT) { }
+    mTimestampBase(TIMESTAMP_BASE_DEFAULT),
+    mMirrorMode(MIRROR_MODE_AUTO) { }
 
 status_t OutputConfiguration::writeToParcel(android::Parcel* parcel) const {
 
@@ -307,6 +323,9 @@
     err = parcel->writeInt32(mTimestampBase);
     if (err != OK) return err;
 
+    err = parcel->writeInt32(mMirrorMode);
+    if (err != OK) return err;
+
     return OK;
 }
 
diff --git a/camera/include/camera/CameraUtils.h b/camera/include/camera/CameraUtils.h
index a397ccd..31d25e7 100644
--- a/camera/include/camera/CameraUtils.h
+++ b/camera/include/camera/CameraUtils.h
@@ -37,10 +37,13 @@
          * metadata.  This is based on the sensor orientation and lens facing
          * attributes of the camera device.
          *
+         * If mirrorMode is not AUTO, it will be used to override the lens
+         * facing based mirror.
+         *
          * Returns OK on success, or a negative error code.
          */
         static status_t getRotationTransform(const CameraMetadata& staticInfo,
-                /*out*/int32_t* transform);
+                int mirrorMode, /*out*/int32_t* transform);
 
         /**
          * Check if the image data is VideoNativeHandleMetadata, that contains a native handle.
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 9a91cc0..d7abfba 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -38,13 +38,19 @@
         SURFACE_TYPE_SURFACE_VIEW = 0,
         SURFACE_TYPE_SURFACE_TEXTURE = 1
     };
-    enum TimestampBaseByte {
+    enum TimestampBaseType {
         TIMESTAMP_BASE_DEFAULT = 0,
         TIMESTAMP_BASE_SENSOR = 1,
         TIMESTAMP_BASE_MONOTONIC = 2,
         TIMESTAMP_BASE_REALTIME = 3,
         TIMESTAMP_BASE_CHOREOGRAPHER_SYNCED = 4
     };
+    enum MirrorModeType {
+        MIRROR_MODE_AUTO = 0,
+        MIRROR_MODE_NONE = 1,
+        MIRROR_MODE_H = 2,
+        MIRROR_MODE_V = 3,
+    };
 
     const std::vector<sp<IGraphicBufferProducer>>& getGraphicBufferProducers() const;
     int                        getRotation() const;
@@ -59,6 +65,7 @@
     bool                       isMultiResolution() const;
     int                        getStreamUseCase() const;
     int                        getTimestampBase() const;
+    int                        getMirrorMode() const;
 
     // set of sensor pixel mode resolutions allowed {MAX_RESOLUTION, DEFAULT_MODE};
     const std::vector<int32_t>&            getSensorPixelModesUsed() const;
@@ -103,7 +110,8 @@
                 sensorPixelModesUsedEqual(other) &&
                 mDynamicRangeProfile == other.mDynamicRangeProfile &&
                 mStreamUseCase == other.mStreamUseCase &&
-                mTimestampBase == other.mTimestampBase);
+                mTimestampBase == other.mTimestampBase &&
+                mMirrorMode == other.mMirrorMode);
     }
     bool operator != (const OutputConfiguration& other) const {
         return !(*this == other);
@@ -149,6 +157,9 @@
         if (mTimestampBase != other.mTimestampBase) {
             return mTimestampBase < other.mTimestampBase;
         }
+        if (mMirrorMode != other.mMirrorMode) {
+            return mMirrorMode < other.mMirrorMode;
+        }
         return gbpsLessThan(other);
     }
 
@@ -176,6 +187,7 @@
     int                        mDynamicRangeProfile;
     int                        mStreamUseCase;
     int                        mTimestampBase;
+    int                        mMirrorMode;
 };
 } // namespace params
 } // namespace camera2