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/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index 187bd93..b436d2e 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -18,6 +18,8 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <utils/Trace.h>
+
 #include "Flags.h"
 
 #include "Camera3SharedOutputStream.h"
@@ -29,7 +31,7 @@
 const size_t Camera3SharedOutputStream::kMaxOutputs;
 
 Camera3SharedOutputStream::Camera3SharedOutputStream(int id,
-        const std::vector<sp<Surface>>& surfaces,
+        const std::vector<SurfaceHolder>& surfaces,
         uint32_t width, uint32_t height, int format,
         uint64_t consumerUsage, android_dataspace dataSpace,
         camera_stream_rotation_t rotation,
@@ -37,12 +39,12 @@
         const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
         int setId, bool useHalBufManager, int64_t dynamicProfile,
         int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
-        int mirrorMode, int32_t colorSpace, bool useReadoutTimestamp) :
+        int32_t colorSpace, bool useReadoutTimestamp) :
         Camera3OutputStream(id, CAMERA_STREAM_OUTPUT, width, height,
                             format, dataSpace, rotation, physicalCameraId, sensorPixelModesUsed,
                             transport, consumerUsage, timestampOffset, setId,
                             /*isMultiResolution*/false, dynamicProfile, streamUseCase,
-                            deviceTimeBaseIsRealtime, timestampBase, mirrorMode, colorSpace,
+                            deviceTimeBaseIsRealtime, timestampBase, colorSpace,
                             useReadoutTimestamp),
         mUseHalBufManager(useHalBufManager) {
     size_t consumerCount = std::min(surfaces.size(), kMaxOutputs);
@@ -50,7 +52,7 @@
         ALOGE("%s: Trying to add more consumers than the maximum ", __func__);
     }
     for (size_t i = 0; i < consumerCount; i++) {
-        mSurfaceUniqueIds[i] = std::make_pair(surfaces[i], mNextUniqueSurfaceId++);
+        mSurfaceUniqueIds[i] = SurfaceHolderUniqueId{surfaces[i], mNextUniqueSurfaceId++};
     }
 }
 
@@ -72,8 +74,8 @@
 
     std::unordered_map<size_t, sp<Surface>> initialSurfaces;
     for (size_t i = 0; i < kMaxOutputs; i++) {
-        if (mSurfaceUniqueIds[i].first != nullptr) {
-            initialSurfaces.emplace(i, mSurfaceUniqueIds[i].first);
+        if (mSurfaceUniqueIds[i].mSurfaceHolder.mSurface != nullptr) {
+            initialSurfaces.emplace(i, mSurfaceUniqueIds[i].mSurfaceHolder.mSurface);
         }
     }
 
@@ -142,19 +144,19 @@
         return true;
     }
 
-    return (mSurfaceUniqueIds[surface_id].first == nullptr);
+    return (mSurfaceUniqueIds[surface_id].mSurfaceHolder.mSurface == nullptr);
 }
 
-status_t Camera3SharedOutputStream::setConsumers(const std::vector<sp<Surface>>& surfaces) {
+status_t Camera3SharedOutputStream::setConsumers(const std::vector<SurfaceHolder>& surfaceHolders) {
     Mutex::Autolock l(mLock);
-    if (surfaces.size() == 0) {
+    if (surfaceHolders.size() == 0) {
         ALOGE("%s: it's illegal to set zero consumer surfaces!", __FUNCTION__);
         return INVALID_OPERATION;
     }
 
     status_t ret = OK;
-    for (auto& surface : surfaces) {
-        if (surface == nullptr) {
+    for (auto& surfaceHolder : surfaceHolders) {
+        if (surfaceHolder.mSurface == nullptr) {
             ALOGE("%s: it's illegal to set a null consumer surface!", __FUNCTION__);
             return INVALID_OPERATION;
         }
@@ -165,11 +167,11 @@
             return NO_MEMORY;
         }
 
-        mSurfaceUniqueIds[id] = std::make_pair(surface, mNextUniqueSurfaceId++);
+        mSurfaceUniqueIds[id] = SurfaceHolderUniqueId{surfaceHolder, mNextUniqueSurfaceId++};
 
         // Only call addOutput if the splitter has been connected.
         if (mStreamSplitter != nullptr) {
-            ret = mStreamSplitter->addOutput(id, surface);
+            ret = mStreamSplitter->addOutput(id, surfaceHolder.mSurface);
             if (ret != OK) {
                 ALOGE("%s: addOutput failed with error code %d", __FUNCTION__, ret);
                 return ret;
@@ -222,7 +224,7 @@
         for (const auto& uniqueId : uniqueSurfaceIds) {
             bool uniqueIdFound = false;
             for (size_t i = 0; i < kMaxOutputs; i++) {
-                if (mSurfaceUniqueIds[i].second == uniqueId) {
+                if (mSurfaceUniqueIds[i].mId == uniqueId) {
                     surfaceIds.push_back(i);
                     uniqueIdFound = true;
                     break;
@@ -275,6 +277,23 @@
         return res;
     }
 
+    // Set buffer transform for all configured surfaces
+    for (const auto& surfaceUniqueId : mSurfaceUniqueIds) {
+        const sp<Surface>& surface = surfaceUniqueId.mSurfaceHolder.mSurface;
+        int surfaceId = surfaceUniqueId.mId;
+        int32_t transform = surfaceUniqueId.mTransform;
+        if (transform == -1 || surface == nullptr) {
+            continue;
+        }
+
+        res = mStreamSplitter->setTransform(surfaceId, transform);
+        if (res != OK) {
+            ALOGE("%s: StreamSplitter failed to setTransform: %s(%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+    }
+
     return OK;
 }
 
@@ -299,8 +318,9 @@
         *usage = getPresetConsumerUsage();
 
         for (size_t id = 0; id < kMaxOutputs; id++) {
-            if (mSurfaceUniqueIds[id].first != nullptr) {
-                res = getEndpointUsageForSurface(&u, mSurfaceUniqueIds[id].first);
+            const auto& surface = mSurfaceUniqueIds[id].mSurfaceHolder.mSurface;
+            if (surface != nullptr) {
+                res = getEndpointUsageForSurface(&u, surface);
                 *usage |= u;
             }
         }
@@ -316,7 +336,7 @@
 ssize_t Camera3SharedOutputStream::getNextSurfaceIdLocked() {
     ssize_t id = -1;
     for (size_t i = 0; i < kMaxOutputs; i++) {
-        if (mSurfaceUniqueIds[i].first == nullptr) {
+        if (mSurfaceUniqueIds[i].mSurfaceHolder.mSurface == nullptr) {
             id = i;
             break;
         }
@@ -329,7 +349,7 @@
     Mutex::Autolock l(mLock);
     ssize_t id = -1;
     for (size_t i = 0; i < kMaxOutputs; i++) {
-        if (mSurfaceUniqueIds[i].first == surface) {
+        if (mSurfaceUniqueIds[i].mSurfaceHolder.mSurface == surface) {
             id = i;
             break;
         }
@@ -353,13 +373,13 @@
         if (surfaceId >= kMaxOutputs) {
             return BAD_VALUE;
         }
-        outUniqueIds->push_back(mSurfaceUniqueIds[surfaceId].second);
+        outUniqueIds->push_back(mSurfaceUniqueIds[surfaceId].mId);
     }
     return OK;
 }
 
 status_t Camera3SharedOutputStream::revertPartialUpdateLocked(
-        const KeyedVector<sp<Surface>, size_t> &removedSurfaces,
+        const KeyedVector<size_t, SurfaceHolder> &removedSurfaces,
         const KeyedVector<sp<Surface>, size_t> &attachedSurfaces) {
     status_t ret = OK;
 
@@ -371,25 +391,25 @@
                 return UNKNOWN_ERROR;
             }
         }
-        mSurfaceUniqueIds[index] = std::make_pair(nullptr, mNextUniqueSurfaceId++);
+        mSurfaceUniqueIds[index] = SurfaceHolderUniqueId{mNextUniqueSurfaceId++};
     }
 
     for (size_t i = 0; i < removedSurfaces.size(); i++) {
-        size_t index = removedSurfaces.valueAt(i);
+        size_t index = removedSurfaces.keyAt(i);
         if (mStreamSplitter != nullptr) {
-            ret = mStreamSplitter->addOutput(index, removedSurfaces.keyAt(i));
+            ret = mStreamSplitter->addOutput(index, removedSurfaces.valueAt(i).mSurface);
             if (ret != OK) {
                 return UNKNOWN_ERROR;
             }
         }
-        mSurfaceUniqueIds[index] = std::make_pair(
-                removedSurfaces.keyAt(i), mNextUniqueSurfaceId++);
+        mSurfaceUniqueIds[index] = SurfaceHolderUniqueId{removedSurfaces.valueAt(i),
+                mNextUniqueSurfaceId++};
     }
 
     return ret;
 }
 
-status_t Camera3SharedOutputStream::updateStream(const std::vector<sp<Surface>> &outputSurfaces,
+status_t Camera3SharedOutputStream::updateStream(const std::vector<SurfaceHolder> &outputSurfaces,
         const std::vector<OutputStreamInfo> &outputInfo,
         const std::vector<size_t> &removedSurfaceIds,
         KeyedVector<sp<Surface>, size_t> *outputMap) {
@@ -403,7 +423,7 @@
 
     uint64_t usage;
     getEndpointUsage(&usage);
-    KeyedVector<sp<Surface>, size_t> removedSurfaces;
+    KeyedVector<size_t, SurfaceHolder> removedSurfaces;
     //Check whether the new surfaces are compatible.
     for (const auto &infoIt : outputInfo) {
         bool imgReaderUsage = (infoIt.consumerUsage & GRALLOC_USAGE_SW_READ_OFTEN) ? true : false;
@@ -437,8 +457,8 @@
 
             }
         }
-        removedSurfaces.add(mSurfaceUniqueIds[it].first, it);
-        mSurfaceUniqueIds[it] = std::make_pair(nullptr, mNextUniqueSurfaceId++);
+        removedSurfaces.add(it, mSurfaceUniqueIds[it].mSurfaceHolder);
+        mSurfaceUniqueIds[it] = SurfaceHolderUniqueId{mNextUniqueSurfaceId++};
     }
 
     //Next add the new outputs
@@ -453,7 +473,7 @@
             return NO_MEMORY;
         }
         if (mStreamSplitter != nullptr) {
-            ret = mStreamSplitter->addOutput(surfaceId, it);
+            ret = mStreamSplitter->addOutput(surfaceId, it.mSurface);
             if (ret != OK) {
                 ALOGE("%s: failed with error code %d", __FUNCTION__, ret);
                 status_t res = revertPartialUpdateLocked(removedSurfaces, *outputMap);
@@ -463,13 +483,54 @@
                 return ret;
             }
         }
-        mSurfaceUniqueIds[surfaceId] = std::make_pair(it, mNextUniqueSurfaceId++);
-        outputMap->add(it, surfaceId);
+        mSurfaceUniqueIds[surfaceId] = SurfaceHolderUniqueId{it, mNextUniqueSurfaceId++};
+        outputMap->add(it.mSurface, surfaceId);
     }
 
     return ret;
 }
 
+status_t Camera3SharedOutputStream::setTransform(
+        int transform, bool mayChangeMirror, int surfaceId) {
+    ATRACE_CALL();
+    Mutex::Autolock l(mLock);
+
+    status_t res = OK;
+
+    if (surfaceId < 0 || (size_t)surfaceId >= mSurfaceUniqueIds.size()) {
+        ALOGE("%s: Invalid surfaceId %d", __FUNCTION__, surfaceId);
+        return BAD_VALUE;
+    }
+    if (transform == -1) return res;
+
+    if (mState == STATE_ERROR) {
+        ALOGE("%s: Stream in error state", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    auto& surfaceHolderForId = mSurfaceUniqueIds[surfaceId];
+    if (surfaceHolderForId.mSurfaceHolder.mMirrorMode != OutputConfiguration::MIRROR_MODE_AUTO &&
+            mayChangeMirror) {
+        // If the mirroring mode is not AUTO, do not allow transform update
+        // which may change mirror.
+        return OK;
+    }
+
+    surfaceHolderForId.mTransform = transform;
+    if (mState == STATE_CONFIGURED) {
+        sp<Surface> surface = surfaceHolderForId.mSurfaceHolder.mSurface;
+        if (surface != nullptr) {
+            res = mStreamSplitter->setTransform(surfaceId, transform);
+            if (res != OK) {
+                ALOGE("%s: StreamSplitter fails to setTransform: %s(%d)",
+                        __FUNCTION__, strerror(-res), res);
+                return res;
+            }
+        }
+    }
+    return res;
+}
+
 } // namespace camera3
 
 } // namespace android