Camera: Add per-surface mirroring mode

Add the support to do per output surface mirror mode. Previously
mirroring mode is set per OutputConfiguration, which could contain
multiple shared surfaces.

Flag: com.android.internal.camera.flags.mirror_mode_shared_surfaces
Test: atest MultiViewTest
Bug: 298899993
Change-Id: I3654cb585d243365b62a10131c21a869af754e73
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index 2d1af32..48a7338 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -22,12 +22,14 @@
 
 #include <camera/camera2/OutputConfiguration.h>
 #include <camera/StringUtils.h>
+#include <com_android_internal_camera_flags.h>
 #include <binder/Parcel.h>
 #include <gui/view/Surface.h>
 #include <system/camera_metadata.h>
 #include <system/graphics.h>
 #include <utils/String8.h>
 
+namespace flags = com::android::internal::camera::flags;
 
 namespace android {
 
@@ -95,7 +97,21 @@
     return mTimestampBase;
 }
 
-int OutputConfiguration::getMirrorMode() const {
+int OutputConfiguration::getMirrorMode(sp<IGraphicBufferProducer> surface) const {
+    if (!flags::mirror_mode_shared_surfaces()) {
+        return mMirrorMode;
+    }
+
+    // Use per-producer mirror mode if available.
+    for (size_t i = 0; i < mGbps.size(); i++) {
+        if (mGbps[i] == surface) {
+            return mMirrorModeForProducers[i];
+        }
+    }
+
+    // For surface that doesn't belong to this output configuration, use
+    // mMirrorMode as default.
+    ALOGW("%s: Surface doesn't belong to this OutputConfiguration!", __FUNCTION__);
     return mMirrorMode;
 }
 
@@ -251,6 +267,12 @@
         return err;
     }
 
+    std::vector<int> mirrorModeForProducers;
+    if ((err = parcel->readInt32Vector(&mirrorModeForProducers)) != OK) {
+        ALOGE("%s: Failed to read mirroring mode for surfaces from parcel", __FUNCTION__);
+        return err;
+    }
+
     int useReadoutTimestamp = 0;
     if ((err = parcel->readInt32(&useReadoutTimestamp)) != OK) {
         ALOGE("%s: Failed to read useReadoutTimestamp flag from parcel", __FUNCTION__);
@@ -286,6 +308,7 @@
     mStreamUseCase = streamUseCase;
     mTimestampBase = timestampBase;
     mMirrorMode = mirrorMode;
+    mMirrorModeForProducers = std::move(mirrorModeForProducers);
     mUseReadoutTimestamp = useReadoutTimestamp != 0;
     for (auto& surface : surfaceShims) {
         ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
@@ -409,6 +432,9 @@
     err = parcel->writeInt32(mMirrorMode);
     if (err != OK) return err;
 
+    err = parcel->writeInt32Vector(mMirrorModeForProducers);
+    if (err != OK) return err;
+
     err = parcel->writeInt32(mUseReadoutTimestamp ? 1 : 0);
     if (err != OK) return err;
 
@@ -438,6 +464,20 @@
     return true;
 }
 
+template <typename T>
+static bool simpleVectorsLessThan(T first, T second) {
+    if (first.size() != second.size()) {
+        return first.size() < second.size();
+    }
+
+    for (size_t i = 0; i < first.size(); i++) {
+        if (first[i] != second[i]) {
+            return first[i] < second[i];
+        }
+    }
+    return false;
+}
+
 bool OutputConfiguration::gbpsEqual(const OutputConfiguration& other) const {
     const std::vector<sp<IGraphicBufferProducer> >& otherGbps =
             other.getGraphicBufferProducers();
@@ -449,20 +489,20 @@
     return simpleVectorsEqual(othersensorPixelModesUsed, mSensorPixelModesUsed);
 }
 
+bool OutputConfiguration::mirrorModesEqual(const OutputConfiguration& other) const {
+    const std::vector<int>& otherMirrorModes = other.getMirrorModes();
+    return simpleVectorsEqual(otherMirrorModes, mMirrorModeForProducers);
+
+}
+
 bool OutputConfiguration::sensorPixelModesUsedLessThan(const OutputConfiguration& other) const {
     const std::vector<int32_t>& spms = other.getSensorPixelModesUsed();
+    return simpleVectorsLessThan(mSensorPixelModesUsed, spms);
+}
 
-    if (mSensorPixelModesUsed.size() !=  spms.size()) {
-        return mSensorPixelModesUsed.size() < spms.size();
-    }
-
-    for (size_t i = 0; i < spms.size(); i++) {
-        if (mSensorPixelModesUsed[i] != spms[i]) {
-            return mSensorPixelModesUsed[i] < spms[i];
-        }
-    }
-
-    return false;
+bool OutputConfiguration::mirrorModesLessThan(const OutputConfiguration& other) const {
+    const std::vector<int>& otherMirrorModes = other.getMirrorModes();
+    return simpleVectorsLessThan(mMirrorModeForProducers, otherMirrorModes);
 }
 
 bool OutputConfiguration::gbpsLessThan(const OutputConfiguration& other) const {