Add support for dynamic shared output surfaces

The Camera API needs to support the dynamic attach/detach of extra
output surfaces to a given camera stream.

Bug: 63912484
Change-Id: I18809aea31f78fb9e125bd18b58951ade4fad3c5
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index f985382..a376ab4 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -530,10 +530,11 @@
     }
 
     int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
+    std::vector<int> surfaceIds;
     err = mDevice->createStream(surfaces, deferredConsumer, streamInfo.width,
             streamInfo.height, streamInfo.format, streamInfo.dataSpace,
             static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
-            &streamId, outputConfiguration.getSurfaceSetID(), isShared);
+            &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared);
 
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -545,7 +546,8 @@
         for (auto& binder : binders) {
             ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d",
                     __FUNCTION__, binder.get(), streamId, i);
-            mStreamMap.add(binder, StreamSurfaceId(streamId, i++));
+            mStreamMap.add(binder, StreamSurfaceId(streamId, surfaceIds[i]));
+            i++;
         }
 
         mStreamInfoMap[streamId] = streamInfo;
@@ -592,10 +594,12 @@
     }
     int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
     std::vector<sp<Surface>> noSurface;
+    std::vector<int> surfaceIds;
     err = mDevice->createStream(noSurface, /*hasDeferredConsumer*/true, width,
             height, format, dataSpace,
             static_cast<camera3_stream_rotation_t>(outputConfiguration.getRotation()),
-            &streamId, outputConfiguration.getSurfaceSetID(), isShared, consumerUsage);
+            &streamId, &surfaceIds, outputConfiguration.getSurfaceSetID(), isShared,
+            consumerUsage);
 
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
@@ -721,6 +725,130 @@
     return res;
 }
 
+binder::Status CameraDeviceClient::updateOutputConfiguration(int streamId,
+        const hardware::camera2::params::OutputConfiguration &outputConfiguration) {
+    ATRACE_CALL();
+
+    binder::Status res;
+    if (!(res = checkPidStatus(__FUNCTION__)).isOk()) return res;
+
+    Mutex::Autolock icl(mBinderSerializationLock);
+
+    if (!mDevice.get()) {
+        return STATUS_ERROR(CameraService::ERROR_DISCONNECTED, "Camera device no longer alive");
+    }
+
+    const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
+            outputConfiguration.getGraphicBufferProducers();
+    auto producerCount = bufferProducers.size();
+    if (producerCount == 0) {
+        ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "bufferProducers must not be empty");
+    }
+
+    // The first output is the one associated with the output configuration.
+    // It should always be present, valid and the corresponding stream id should match.
+    sp<IBinder> binder = IInterface::asBinder(bufferProducers[0]);
+    ssize_t index = mStreamMap.indexOfKey(binder);
+    if (index == NAME_NOT_FOUND) {
+        ALOGE("%s: Outputconfiguration is invalid", __FUNCTION__);
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "OutputConfiguration is invalid");
+    }
+    if (mStreamMap.valueFor(binder).streamId() != streamId) {
+        ALOGE("%s: Stream Id: %d provided doesn't match the id: %d in the stream map",
+                __FUNCTION__, streamId, mStreamMap.valueFor(binder).streamId());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                "Stream id is invalid");
+    }
+
+    std::vector<size_t> removedSurfaceIds;
+    std::vector<sp<IBinder>> removedOutputs;
+    std::vector<sp<Surface>> newOutputs;
+    std::vector<OutputStreamInfo> streamInfos;
+    KeyedVector<sp<IBinder>, sp<IGraphicBufferProducer>> newOutputsMap;
+    for (auto &it : bufferProducers) {
+        newOutputsMap.add(IInterface::asBinder(it), it);
+    }
+
+    for (size_t i = 0; i < mStreamMap.size(); i++) {
+        ssize_t idx = newOutputsMap.indexOfKey(mStreamMap.keyAt(i));
+        if (idx == NAME_NOT_FOUND) {
+            if (mStreamMap[i].streamId() == streamId) {
+                removedSurfaceIds.push_back(mStreamMap[i].surfaceId());
+                removedOutputs.push_back(mStreamMap.keyAt(i));
+            }
+        } else {
+            if (mStreamMap[i].streamId() != streamId) {
+                ALOGE("%s: Output surface already part of a different stream", __FUNCTION__);
+                return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Target Surface is invalid");
+            }
+            newOutputsMap.removeItemsAt(idx);
+        }
+    }
+
+    for (size_t i = 0; i < newOutputsMap.size(); i++) {
+        OutputStreamInfo outInfo;
+        sp<Surface> surface;
+        res = createSurfaceFromGbp(outInfo, /*isStreamInfoValid*/ false, surface,
+                newOutputsMap.valueAt(i));
+        if (!res.isOk())
+            return res;
+
+        // Stream sharing is only supported for IMPLEMENTATION_DEFINED
+        // formats.
+        if (outInfo.format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) {
+            String8 msg = String8::format("Camera %s: Stream sharing is only supported for "
+                    "IMPLEMENTATION_DEFINED format", mCameraIdStr.string());
+            ALOGW("%s: %s", __FUNCTION__, msg.string());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        }
+        streamInfos.push_back(outInfo);
+        newOutputs.push_back(surface);
+    }
+
+    //Trivial case no changes required
+    if (removedSurfaceIds.empty() && newOutputs.empty()) {
+        return binder::Status::ok();
+    }
+
+    KeyedVector<sp<Surface>, size_t> outputMap;
+    auto ret = mDevice->updateStream(streamId, newOutputs, streamInfos, removedSurfaceIds,
+            &outputMap);
+    if (ret != OK) {
+        switch (ret) {
+            case NAME_NOT_FOUND:
+            case BAD_VALUE:
+            case -EBUSY:
+                res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
+                        "Camera %s: Error updating stream: %s (%d)",
+                        mCameraIdStr.string(), strerror(ret), ret);
+                break;
+            default:
+                res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
+                        "Camera %s: Error updating stream: %s (%d)",
+                        mCameraIdStr.string(), strerror(ret), ret);
+                break;
+        }
+    } else {
+        for (const auto &it : removedOutputs) {
+            mStreamMap.removeItem(it);
+        }
+
+        for (size_t i = 0; i < outputMap.size(); i++) {
+            mStreamMap.add(IInterface::asBinder(outputMap.keyAt(i)->getIGraphicBufferProducer()),
+                    StreamSurfaceId(streamId, outputMap.valueAt(i)));
+        }
+
+        ALOGV("%s: Camera %s: Successful stream ID %d update",
+                  __FUNCTION__, mCameraIdStr.string(), streamId);
+    }
+
+    return res;
+}
+
 bool CameraDeviceClient::isPublicFormat(int32_t format)
 {
     switch(format) {
@@ -1242,15 +1370,12 @@
     }
 
     std::vector<sp<Surface>> consumerSurfaces;
-    std::vector<size_t> consumerSurfaceIds;
-    size_t surfaceId = 0;
     for (auto& bufferProducer : bufferProducers) {
         // Don't create multiple streams for the same target surface
         ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
         if (index != NAME_NOT_FOUND) {
             ALOGV("Camera %s: Surface already has a stream created "
                     " for it (ID %zd)", mCameraIdStr.string(), index);
-            surfaceId++;
             continue;
         }
 
@@ -1262,8 +1387,6 @@
             return res;
 
         consumerSurfaces.push_back(surface);
-        consumerSurfaceIds.push_back(surfaceId);
-        surfaceId++;
     }
 
     // Gracefully handle case where finalizeOutputConfigurations is called
@@ -1275,12 +1398,13 @@
 
     // Finish the deferred stream configuration with the surface.
     status_t err;
-    err = mDevice->setConsumerSurfaces(streamId, consumerSurfaces);
+    std::vector<int> consumerSurfaceIds;
+    err = mDevice->setConsumerSurfaces(streamId, consumerSurfaces, &consumerSurfaceIds);
     if (err == OK) {
         for (size_t i = 0; i < consumerSurfaces.size(); i++) {
             sp<IBinder> binder = IInterface::asBinder(
                     consumerSurfaces[i]->getIGraphicBufferProducer());
-            ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %zu", __FUNCTION__,
+            ALOGV("%s: mStreamMap add binder %p streamId %d, surfaceId %d", __FUNCTION__,
                     binder.get(), streamId, consumerSurfaceIds[i]);
             mStreamMap.add(binder, StreamSurfaceId(streamId, consumerSurfaceIds[i]));
         }