camera: Add support for logical camera

- Add physical cameraId field in stream structure.
- Override processCaptureRequest due to physicalCameraId change.
- Update 3.3 metadata with logical camera characteristics.

Test: Camera CTS on Taimen, LogicalCamera CTS test on C1
Bug: 64691172
Change-Id: I65bd1ae38381ecb89fae439ae14b813c9bcc3248
diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp
index 2523fa8..67b79b9 100644
--- a/camera/device/3.4/Android.bp
+++ b/camera/device/3.4/Android.bp
@@ -18,6 +18,9 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "HalStream",
+        "HalStreamConfiguration",
+        "Stream",
         "StreamConfiguration",
     ],
     gen_java: false,
diff --git a/camera/device/3.4/ICameraDeviceSession.hal b/camera/device/3.4/ICameraDeviceSession.hal
index e5693b2..71a4b34 100644
--- a/camera/device/3.4/ICameraDeviceSession.hal
+++ b/camera/device/3.4/ICameraDeviceSession.hal
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2017-2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,6 +19,8 @@
 import android.hardware.camera.common@1.0::Status;
 import @3.3::ICameraDeviceSession;
 import @3.3::HalStreamConfiguration;
+import @3.2::BufferCache;
+import @3.2::CaptureRequest;
 
 /**
  * Camera device active session interface.
@@ -69,6 +71,5 @@
      */
     configureStreams_3_4(@3.4::StreamConfiguration requestedConfiguration)
             generates (Status status,
-                       @3.3::HalStreamConfiguration halConfiguration);
-
+                       @3.4::HalStreamConfiguration halConfiguration);
 };
diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp
index c0ce838..a0ab167 100644
--- a/camera/device/3.4/default/Android.bp
+++ b/camera/device/3.4/default/Android.bp
@@ -28,6 +28,7 @@
     srcs: [
         "CameraDevice.cpp",
         "CameraDeviceSession.cpp",
+        "convert.cpp",
     ],
     shared_libs: [
         "libhidlbase",
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index 0ae470f..b74fd57 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2017-2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -41,8 +41,8 @@
 }
 
 Return<void> CameraDeviceSession::configureStreams_3_4(
-        const V3_4::StreamConfiguration& requestedConfiguration,
-        ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb)  {
+        const StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)  {
     Status status = initStatus();
     HalStreamConfiguration outStreams;
 
@@ -86,7 +86,7 @@
     camera3_stream_configuration_t stream_list{};
     hidl_vec<camera3_stream_t*> streams;
     stream_list.session_parameters = paramBuffer;
-    if (!preProcessConfigurationLocked(requestedConfiguration.v3_2, &stream_list, &streams)) {
+    if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
         return Void();
     }
@@ -98,7 +98,7 @@
     // In case Hal returns error most likely it was not able to release
     // the corresponding resources of the deleted streams.
     if (ret == OK) {
-        postProcessConfigurationLocked(requestedConfiguration.v3_2);
+        postProcessConfigurationLocked_3_4(requestedConfiguration);
     }
 
     if (ret == -EINVAL) {
@@ -106,7 +106,7 @@
     } else if (ret != OK) {
         status = Status::INTERNAL_ERROR;
     } else {
-        V3_3::implementation::convertToHidl(stream_list, &outStreams);
+        V3_4::implementation::convertToHidl(stream_list, &outStreams);
         mFirstRequest = true;
     }
 
@@ -114,6 +114,244 @@
     return Void();
 }
 
+bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
+        const StreamConfiguration& requestedConfiguration,
+        camera3_stream_configuration_t *stream_list /*out*/,
+        hidl_vec<camera3_stream_t*> *streams /*out*/) {
+
+    if ((stream_list == nullptr) || (streams == nullptr)) {
+        return false;
+    }
+
+    stream_list->operation_mode = (uint32_t) requestedConfiguration.operationMode;
+    stream_list->num_streams = requestedConfiguration.streams.size();
+    streams->resize(stream_list->num_streams);
+    stream_list->streams = streams->data();
+
+    for (uint32_t i = 0; i < stream_list->num_streams; i++) {
+        int id = requestedConfiguration.streams[i].v3_2.id;
+
+        if (mStreamMap.count(id) == 0) {
+            Camera3Stream stream;
+            convertFromHidl(requestedConfiguration.streams[i], &stream);
+            mStreamMap[id] = stream;
+            mPhysicalCameraIdMap[id] = requestedConfiguration.streams[i].physicalCameraId;
+            mStreamMap[id].data_space = mapToLegacyDataspace(
+                    mStreamMap[id].data_space);
+            mStreamMap[id].physical_camera_id = mPhysicalCameraIdMap[id].c_str();
+            mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
+        } else {
+            // width/height/format must not change, but usage/rotation might need to change
+            if (mStreamMap[id].stream_type !=
+                    (int) requestedConfiguration.streams[i].v3_2.streamType ||
+                    mStreamMap[id].width != requestedConfiguration.streams[i].v3_2.width ||
+                    mStreamMap[id].height != requestedConfiguration.streams[i].v3_2.height ||
+                    mStreamMap[id].format != (int) requestedConfiguration.streams[i].v3_2.format ||
+                    mStreamMap[id].data_space !=
+                            mapToLegacyDataspace( static_cast<android_dataspace_t> (
+                                    requestedConfiguration.streams[i].v3_2.dataSpace)) ||
+                    mPhysicalCameraIdMap[id] != requestedConfiguration.streams[i].physicalCameraId) {
+                ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
+                return false;
+            }
+            mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].v3_2.rotation;
+            mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].v3_2.usage;
+        }
+        (*streams)[i] = &mStreamMap[id];
+    }
+
+    return true;
+}
+
+void CameraDeviceSession::postProcessConfigurationLocked_3_4(
+        const StreamConfiguration& requestedConfiguration) {
+    // delete unused streams, note we do this after adding new streams to ensure new stream
+    // will not have the same address as deleted stream, and HAL has a chance to reference
+    // the to be deleted stream in configure_streams call
+    for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
+        int id = it->first;
+        bool found = false;
+        for (const auto& stream : requestedConfiguration.streams) {
+            if (id == stream.v3_2.id) {
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            // Unmap all buffers of deleted stream
+            // in case the configuration call succeeds and HAL
+            // is able to release the corresponding resources too.
+            cleanupBuffersLocked(id);
+            it = mStreamMap.erase(it);
+        } else {
+            ++it;
+        }
+    }
+
+    // Track video streams
+    mVideoStreamIds.clear();
+    for (const auto& stream : requestedConfiguration.streams) {
+        if (stream.v3_2.streamType == StreamType::OUTPUT &&
+            stream.v3_2.usage &
+                graphics::common::V1_0::BufferUsage::VIDEO_ENCODER) {
+            mVideoStreamIds.push_back(stream.v3_2.id);
+        }
+    }
+    mResultBatcher.setBatchedStreams(mVideoStreamIds);
+}
+
+Return<void> CameraDeviceSession::processCaptureRequest_3_4(
+        const hidl_vec<CaptureRequest>& requests,
+        const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+        ICameraDeviceSession::processCaptureRequest_cb _hidl_cb)  {
+    updateBufferCaches(cachesToRemove);
+
+    uint32_t numRequestProcessed = 0;
+    Status s = Status::OK;
+    for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
+        s = processOneCaptureRequest_3_4(requests[i]);
+        if (s != Status::OK) {
+            break;
+        }
+    }
+
+    if (s == Status::OK && requests.size() > 1) {
+        mResultBatcher.registerBatch(requests);
+    }
+
+    _hidl_cb(s, numRequestProcessed);
+    return Void();
+}
+
+Status CameraDeviceSession::processOneCaptureRequest_3_4(const CaptureRequest& request)  {
+    Status status = initStatus();
+    if (status != Status::OK) {
+        ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
+        return status;
+    }
+
+    camera3_capture_request_t halRequest;
+    halRequest.frame_number = request.frameNumber;
+
+    bool converted = true;
+    V3_2::CameraMetadata settingsFmq;  // settings from FMQ
+    if (request.fmqSettingsSize > 0) {
+        // non-blocking read; client must write metadata before calling
+        // processOneCaptureRequest
+        settingsFmq.resize(request.fmqSettingsSize);
+        bool read = mRequestMetadataQueue->read(settingsFmq.data(), request.fmqSettingsSize);
+        if (read) {
+            converted = V3_2::implementation::convertFromHidl(settingsFmq, &halRequest.settings);
+        } else {
+            ALOGE("%s: capture request settings metadata couldn't be read from fmq!", __FUNCTION__);
+            converted = false;
+        }
+    } else {
+        converted = V3_2::implementation::convertFromHidl(request.settings, &halRequest.settings);
+    }
+
+    if (!converted) {
+        ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    if (mFirstRequest && halRequest.settings == nullptr) {
+        ALOGE("%s: capture request settings must not be null for first request!",
+                __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    hidl_vec<buffer_handle_t*> allBufPtrs;
+    hidl_vec<int> allFences;
+    bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
+            request.inputBuffer.bufferId != 0);
+    size_t numOutputBufs = request.outputBuffers.size();
+    size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
+
+    if (numOutputBufs == 0) {
+        ALOGE("%s: capture request must have at least one output buffer!", __FUNCTION__);
+        return Status::ILLEGAL_ARGUMENT;
+    }
+
+    status = importRequest(request, allBufPtrs, allFences);
+    if (status != Status::OK) {
+        return status;
+    }
+
+    hidl_vec<camera3_stream_buffer_t> outHalBufs;
+    outHalBufs.resize(numOutputBufs);
+    bool aeCancelTriggerNeeded = false;
+    ::android::hardware::camera::common::V1_0::helper::CameraMetadata settingsOverride;
+    {
+        Mutex::Autolock _l(mInflightLock);
+        if (hasInputBuf) {
+            auto streamId = request.inputBuffer.streamId;
+            auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
+            auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
+            convertFromHidl(
+                    allBufPtrs[numOutputBufs], request.inputBuffer.status,
+                    &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
+                    &bufCache);
+            bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
+            halRequest.input_buffer = &bufCache;
+        } else {
+            halRequest.input_buffer = nullptr;
+        }
+
+        halRequest.num_output_buffers = numOutputBufs;
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            auto streamId = request.outputBuffers[i].streamId;
+            auto key = std::make_pair(streamId, request.frameNumber);
+            auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
+            convertFromHidl(
+                    allBufPtrs[i], request.outputBuffers[i].status,
+                    &mStreamMap[streamId], allFences[i],
+                    &bufCache);
+            bufCache.stream->physical_camera_id = mPhysicalCameraIdMap[streamId].c_str();
+            outHalBufs[i] = bufCache;
+        }
+        halRequest.output_buffers = outHalBufs.data();
+
+        AETriggerCancelOverride triggerOverride;
+        aeCancelTriggerNeeded = handleAePrecaptureCancelRequestLocked(
+                halRequest, &settingsOverride /*out*/, &triggerOverride/*out*/);
+        if (aeCancelTriggerNeeded) {
+            mInflightAETriggerOverrides[halRequest.frame_number] =
+                    triggerOverride;
+            halRequest.settings = settingsOverride.getAndLock();
+        }
+    }
+
+    ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
+    ATRACE_BEGIN("camera3->process_capture_request");
+    status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
+    ATRACE_END();
+    if (aeCancelTriggerNeeded) {
+        settingsOverride.unlock(halRequest.settings);
+    }
+    if (ret != OK) {
+        Mutex::Autolock _l(mInflightLock);
+        ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
+
+        cleanupInflightFences(allFences, numBufs);
+        if (hasInputBuf) {
+            auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
+            mInflightBuffers.erase(key);
+        }
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
+            mInflightBuffers.erase(key);
+        }
+        if (aeCancelTriggerNeeded) {
+            mInflightAETriggerOverrides.erase(request.frameNumber);
+        }
+        return Status::INTERNAL_ERROR;
+    }
+
+    mFirstRequest = false;
+    return Status::OK;
+}
+
 } // namespace implementation
 }  // namespace V3_4
 }  // namespace device
diff --git a/camera/device/3.4/default/convert.cpp b/camera/device/3.4/default/convert.cpp
new file mode 100644
index 0000000..f12230c
--- /dev/null
+++ b/camera/device/3.4/default/convert.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.camera.device@3.4-convert-impl"
+#include <log/log.h>
+
+#include <cstring>
+#include "include/convert.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::hardware::camera::device::V3_2::BufferUsageFlags;
+
+void convertToHidl(const Camera3Stream* src, HalStream* dst) {
+    V3_3::implementation::convertToHidl(src, &dst->v3_3);
+    dst->physicalCameraId = src->physical_camera_id;
+}
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
+    dst->streams.resize(src.num_streams);
+    for (uint32_t i = 0; i < src.num_streams; i++) {
+        convertToHidl(static_cast<Camera3Stream*>(src.streams[i]), &dst->streams[i]);
+    }
+    return;
+}
+
+void convertFromHidl(const Stream &src, Camera3Stream* dst) {
+    V3_2::implementation::convertFromHidl(src.v3_2, dst);
+    // Initialize physical_camera_id
+    dst->physical_camera_id = nullptr;
+    return;
+}
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.4/default/include/convert.h b/camera/device/3.4/default/include/convert.h
new file mode 100644
index 0000000..e8e3951
--- /dev/null
+++ b/camera/device/3.4/default/include/convert.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HARDWARE_INTERFACES_CAMERA_DEVICE_V3_4_DEFAULT_INCLUDE_CONVERT_H_
+#define HARDWARE_INTERFACES_CAMERA_DEVICE_V3_4_DEFAULT_INCLUDE_CONVERT_H_
+
+#include <android/hardware/camera/device/3.4/types.h>
+#include "hardware/camera3.h"
+#include "../../3.3/default/include/convert.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_4 {
+namespace implementation {
+
+using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream;
+
+void convertToHidl(const Camera3Stream* src, HalStream* dst);
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst);
+
+void convertFromHidl(const Stream &src, Camera3Stream* dst);
+
+}  // namespace implementation
+}  // namespace V3_4
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_CAMERA_DEVICE_V3_4_DEFAULT_INCLUDE_CONVERT_H_
diff --git a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
index bff1734..83b3afe 100644
--- a/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
+++ b/camera/device/3.4/default/include/device_v3_4_impl/CameraDeviceSession.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2017-2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -18,7 +18,6 @@
 #define ANDROID_HARDWARE_CAMERA_DEVICE_V3_4_CAMERADEVICE3SESSION_H
 
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
-#include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 #include <../../3.3/default/CameraDeviceSession.h>
 #include <../../3.3/default/include/convert.h>
@@ -43,8 +42,9 @@
 
 using namespace ::android::hardware::camera::device;
 using ::android::hardware::camera::device::V3_2::CaptureRequest;
-using ::android::hardware::camera::device::V3_2::StreamConfiguration;
-using ::android::hardware::camera::device::V3_3::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamType;
+using ::android::hardware::camera::device::V3_4::StreamConfiguration;
+using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
 using ::android::hardware::camera::device::V3_4::ICameraDeviceSession;
 using ::android::hardware::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
@@ -75,8 +75,22 @@
     // New methods for v3.4
 
     Return<void> configureStreams_3_4(
-            const V3_4::StreamConfiguration& requestedConfiguration,
-            ICameraDeviceSession::configureStreams_3_3_cb _hidl_cb);
+            const StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb);
+
+    bool preProcessConfigurationLocked_3_4(
+            const StreamConfiguration& requestedConfiguration,
+            camera3_stream_configuration_t *stream_list /*out*/,
+            hidl_vec<camera3_stream_t*> *streams /*out*/);
+    void postProcessConfigurationLocked_3_4(const StreamConfiguration& requestedConfiguration);
+
+    Return<void> processCaptureRequest_3_4(
+            const hidl_vec<CaptureRequest>& requests,
+            const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+            ICameraDeviceSession::processCaptureRequest_cb _hidl_cb);
+    Status processOneCaptureRequest_3_4(const CaptureRequest& request);
+
+    std::map<int, std::string> mPhysicalCameraIdMap;
 private:
 
     struct TrampolineSessionInterface_3_4 : public ICameraDeviceSession {
@@ -90,7 +104,7 @@
         }
 
         virtual Return<void> configureStreams(
-                const StreamConfiguration& requestedConfiguration,
+                const V3_2::StreamConfiguration& requestedConfiguration,
                 V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
             return mParent->configureStreams(requestedConfiguration, _hidl_cb);
         }
@@ -98,7 +112,7 @@
         virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
                 const hidl_vec<V3_2::BufferCache>& cachesToRemove,
                 V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
-            return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
+            return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
         }
 
         virtual Return<void> getCaptureRequestMetadataQueue(
@@ -120,14 +134,14 @@
         }
 
         virtual Return<void> configureStreams_3_3(
-                const StreamConfiguration& requestedConfiguration,
+                const V3_2::StreamConfiguration& requestedConfiguration,
                 configureStreams_3_3_cb _hidl_cb) override {
             return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
         }
 
         virtual Return<void> configureStreams_3_4(
-                const V3_4::StreamConfiguration& requestedConfiguration,
-                configureStreams_3_3_cb _hidl_cb) override {
+                const StreamConfiguration& requestedConfiguration,
+                configureStreams_3_4_cb _hidl_cb) override {
             return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb);
         }
 
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index c822717..acad093 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -16,19 +16,68 @@
 
 package android.hardware.camera.device@3.4;
 
-import @3.2::StreamConfiguration;
 import @3.2::types;
+import @3.2::StreamConfigurationMode;
+import @3.2::Stream;
+import @3.3::HalStream;
+import @3.2::CameraMetadata;
+
+/**
+ * Stream:
+ *
+ * A descriptor for a single camera input or output stream. A stream is defined
+ * by the framework by its buffer resolution and format, and additionally by the
+ * HAL with the gralloc usage flags and the maximum in-flight buffer count.
+ *
+ * This version extends the @3.2 Stream with the physicalCameraId field.
+ */
+struct Stream {
+    /**
+     * The definition of Stream from the prior version
+     */
+    @3.2::Stream v3_2;
+
+    /**
+     * The physical camera id this stream belongs to.
+     *
+     * If the camera device is not a logical multi camera, or if the camera is a logical
+     * multi camera but the stream is not a physical output stream, this field will point to a
+     * 0-length string.
+     *
+     * A logical multi camera is a camera device backed by multiple physical cameras that
+     * are also exposed to the application. And for a logical multi camera, a physical output
+     * stream is an output stream specifically requested on an underlying physical camera.
+     *
+     * A logical camera is a camera device backed by multiple physical camera
+     * devices. And a physical stream is a stream specifically requested on a
+     * underlying physical camera device.
+     *
+     * For an input stream, this field is guaranteed to be a 0-length string.
+     *
+     * When not empty, this field is the <id> field of one of the full-qualified device
+     * instance names returned by getCameraIdList().
+     */
+    string physicalCameraId;
+};
 
 /**
  * StreamConfiguration:
  *
- * Identical to @3.2::StreamConfiguration, except that it contains session parameters.
+ * Identical to @3.2::StreamConfiguration, except that it contains session
+ * parameters, and the streams vector contains @3.4::Stream.
  */
 struct StreamConfiguration {
     /**
-     * The definition of StreamConfiguration from the prior version.
+     * An array of camera stream pointers, defining the input/output
+     * configuration for the camera HAL device.
      */
-    @3.2::StreamConfiguration v3_2;
+    vec<Stream> streams;
+
+    /**
+     * The definition of operation mode from prior version.
+     *
+     */
+    StreamConfigurationMode operationMode;
 
     /**
      * Session wide camera parameters.
@@ -44,3 +93,43 @@
      */
     CameraMetadata sessionParams;
 };
+
+/**
+ * HalStream:
+ *
+ * The camera HAL's response to each requested stream configuration.
+ *
+ * This version extends the @3.3 HalStream with the physicalCameraId
+ * field
+ */
+struct HalStream {
+    /**
+     * The definition of HalStream from the prior version.
+     */
+    @3.3::HalStream v3_3;
+
+    /**
+     * The physical camera id the current Hal stream belongs to.
+     *
+     * If current camera device isn't a logical camera, or the Hal stream isn't
+     * from a physical camera of the logical camera, this must be an empty
+     * string.
+     *
+     * A logical camera is a camera device backed by multiple physical camera
+     * devices.
+     *
+     * When not empty, this field is the <id> field of one of the full-qualified device
+     * instance names returned by getCameraIdList().
+     */
+    string physicalCameraId;
+};
+
+/**
+ * HalStreamConfiguration:
+ *
+ * Identical to @3.3::HalStreamConfiguration, except that it contains @3.4::HalStream entries.
+ *
+ */
+struct HalStreamConfiguration {
+    vec<HalStream> streams;
+};