Camera: support libhardware camera device 3.6

Add buffer management API support.

Test: VTS to be written. Need Pixel device impl to verify.
Bug: 120986771
Change-Id: Icdbc621f8cd17aa0868d3ac361867c44793a268c
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index fd785df..f2d7a47 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -44,13 +44,15 @@
 static constexpr int METADATA_SHRINK_REL_THRESHOLD = 2;
 
 HandleImporter CameraDeviceSession::sHandleImporter;
+buffer_handle_t CameraDeviceSession::sEmptyBuffer = nullptr;
+
 const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
 
 CameraDeviceSession::CameraDeviceSession(
     camera3_device_t* device,
     const camera_metadata_t* deviceInfo,
     const sp<ICameraDeviceCallback>& callback) :
-        camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
+        camera3_callback_ops({&sProcessCaptureResult, &sNotify, nullptr, nullptr}),
         mDevice(device),
         mDeviceVersion(device->common.version),
         mFreeBufEarly(shouldFreeBufEarly()),
@@ -246,10 +248,50 @@
     }
 }
 
+Status CameraDeviceSession::importBuffer(int32_t streamId,
+        uint64_t bufId, buffer_handle_t buf,
+        /*out*/buffer_handle_t** outBufPtr,
+        bool allowEmptyBuf) {
+
+    if (buf == nullptr && bufId == BUFFER_ID_NO_BUFFER) {
+        if (allowEmptyBuf) {
+            *outBufPtr = &sEmptyBuffer;
+            return Status::OK;
+        } else {
+            ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
+            return Status::ILLEGAL_ARGUMENT;
+        }
+    }
+
+    Mutex::Autolock _l(mInflightLock);
+    CirculatingBuffers& cbs = mCirculatingBuffers[streamId];
+    if (cbs.count(bufId) == 0) {
+        // Register a newly seen buffer
+        buffer_handle_t importedBuf = buf;
+        sHandleImporter.importBuffer(importedBuf);
+        if (importedBuf == nullptr) {
+            ALOGE("%s: output buffer for stream %d is invalid!", __FUNCTION__, streamId);
+            return Status::INTERNAL_ERROR;
+        } else {
+            cbs[bufId] = importedBuf;
+        }
+    }
+    *outBufPtr = &cbs[bufId];
+    return Status::OK;
+}
+
 Status CameraDeviceSession::importRequest(
         const CaptureRequest& request,
         hidl_vec<buffer_handle_t*>& allBufPtrs,
         hidl_vec<int>& allFences) {
+    return importRequestImpl(request, allBufPtrs, allFences);
+}
+
+Status CameraDeviceSession::importRequestImpl(
+        const CaptureRequest& request,
+        hidl_vec<buffer_handle_t*>& allBufPtrs,
+        hidl_vec<int>& allFences,
+        bool allowEmptyBuf) {
     bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
             request.inputBuffer.bufferId != 0);
     size_t numOutputBufs = request.outputBuffers.size();
@@ -277,25 +319,15 @@
     }
 
     for (size_t i = 0; i < numBufs; i++) {
-        buffer_handle_t buf = allBufs[i];
-        uint64_t bufId = allBufIds[i];
-        CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
-        if (cbs.count(bufId) == 0) {
-            if (buf == nullptr) {
-                ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
-                return Status::ILLEGAL_ARGUMENT;
-            }
-            // Register a newly seen buffer
-            buffer_handle_t importedBuf = buf;
-            sHandleImporter.importBuffer(importedBuf);
-            if (importedBuf == nullptr) {
-                ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
-                return Status::INTERNAL_ERROR;
-            } else {
-                cbs[bufId] = importedBuf;
-            }
+        Status st = importBuffer(
+                streamIds[i], allBufIds[i], allBufs[i], &allBufPtrs[i],
+                // Disallow empty buf for input stream, otherwise follow
+                // the allowEmptyBuf argument.
+                (hasInputBuf && i == numOutputBufs) ? false : allowEmptyBuf);
+        if (st != Status::OK) {
+            // Detailed error logs printed in importBuffer
+            return st;
         }
-        allBufPtrs[i] = &cbs[bufId];
     }
 
     // All buffers are imported. Now validate output buffer acquire fences
@@ -1271,18 +1303,26 @@
         ATRACE_END();
 
         // free all imported buffers
+        Mutex::Autolock _l(mInflightLock);
         for(auto& pair : mCirculatingBuffers) {
             CirculatingBuffers& buffers = pair.second;
             for (auto& p2 : buffers) {
                 sHandleImporter.freeBuffer(p2.second);
             }
+            buffers.clear();
         }
+        mCirculatingBuffers.clear();
 
         mClosed = true;
     }
     return Void();
 }
 
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t&, int) {
+    // No need to fill in bufferId by default
+    return BUFFER_ID_NO_BUFFER;
+}
+
 status_t CameraDeviceSession::constructCaptureResult(CaptureResult& result,
                                                  const camera3_capture_result *hal_result) {
     uint32_t frameNumber = hal_result->frame_number;
@@ -1396,6 +1436,14 @@
         result.outputBuffers[i].streamId =
                 static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
         result.outputBuffers[i].buffer = nullptr;
+        if (hal_result->output_buffers[i].buffer != nullptr) {
+            result.outputBuffers[i].bufferId = getCapResultBufferId(
+                    *(hal_result->output_buffers[i].buffer),
+                    result.outputBuffers[i].streamId);
+        } else {
+            result.outputBuffers[i].bufferId = 0;
+        }
+
         result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
         // skip acquire fence since it's of no use to camera service
         if (hal_result->output_buffers[i].release_fence != -1) {
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index bcee259..a96c245 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -161,6 +161,7 @@
     std::map<uint32_t, bool> mInflightRawBoostPresent;
     ::android::hardware::camera::common::V1_0::helper::CameraMetadata mOverridenRequest;
 
+    static const uint64_t BUFFER_ID_NO_BUFFER = 0;
     // buffers currently ciculating between HAL and camera service
     // key: bufferId sent via HIDL interface
     // value: imported buffer_handle_t
@@ -171,6 +172,7 @@
     std::map<int, CirculatingBuffers> mCirculatingBuffers;
 
     static HandleImporter sHandleImporter;
+    static buffer_handle_t sEmptyBuffer;
 
     bool mInitFail;
     bool mFirstRequest = false;
@@ -301,11 +303,23 @@
     Status initStatus() const;
 
     // Validate and import request's input buffer and acquire fence
-    Status importRequest(
+    virtual Status importRequest(
             const CaptureRequest& request,
             hidl_vec<buffer_handle_t*>& allBufPtrs,
             hidl_vec<int>& allFences);
 
+    Status importRequestImpl(
+            const CaptureRequest& request,
+            hidl_vec<buffer_handle_t*>& allBufPtrs,
+            hidl_vec<int>& allFences,
+            // Optional argument for ICameraDeviceSession@3.5 impl
+            bool allowEmptyBuf = false);
+
+    Status importBuffer(int32_t streamId,
+            uint64_t bufId, buffer_handle_t buf,
+            /*out*/buffer_handle_t** outBufPtr,
+            bool allowEmptyBuf);
+
     static void cleanupInflightFences(
             hidl_vec<int>& allFences, size_t numFences);
 
@@ -332,6 +346,11 @@
     static callbacks_process_capture_result_t sProcessCaptureResult;
     static callbacks_notify_t sNotify;
 
+    // By default camera service uses frameNumber/streamId pair to retrieve the buffer that
+    // was sent to HAL. Override this implementation if HAL is using buffers from buffer management
+    // APIs to send output buffer.
+    virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId);
+
     status_t constructCaptureResult(CaptureResult& result,
                                 const camera3_capture_result *hal_result);
 
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index f2e031c..e52577c 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -87,6 +87,14 @@
 Return<void> CameraDeviceSession::configureStreams_3_4(
         const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb)  {
+    configureStreams_3_4_Impl(requestedConfiguration, _hidl_cb);
+    return Void();
+}
+
+void CameraDeviceSession::configureStreams_3_4_Impl(
+        const StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+        uint32_t streamConfigCounter)  {
     Status status = initStatus();
     HalStreamConfiguration outStreams;
 
@@ -97,7 +105,7 @@
                 ALOGE("%s: trying to configureStreams with physical camera id with V3.2 callback",
                         __FUNCTION__);
                 _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-                return Void();
+                return;
             }
         }
     }
@@ -109,7 +117,7 @@
         ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
                 __FUNCTION__, mInflightBuffers.size());
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     if (!mInflightAETriggerOverrides.empty()) {
@@ -117,7 +125,7 @@
                 " trigger overrides!", __FUNCTION__,
                 mInflightAETriggerOverrides.size());
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     if (!mInflightRawBoostPresent.empty()) {
@@ -125,12 +133,12 @@
                 " boost overrides!", __FUNCTION__,
                 mInflightRawBoostPresent.size());
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     if (status != Status::OK) {
         _hidl_cb(status, outStreams);
-        return Void();
+        return;
     }
 
     const camera_metadata_t *paramBuffer = nullptr;
@@ -139,11 +147,12 @@
     }
 
     camera3_stream_configuration_t stream_list{};
+    stream_list.stream_configuration_counter = streamConfigCounter;
     hidl_vec<camera3_stream_t*> streams;
     stream_list.session_parameters = paramBuffer;
     if (!preProcessConfigurationLocked_3_4(requestedConfiguration, &stream_list, &streams)) {
         _hidl_cb(Status::INTERNAL_ERROR, outStreams);
-        return Void();
+        return;
     }
 
     ATRACE_BEGIN("camera3->configure_streams");
@@ -168,7 +177,7 @@
     }
 
     _hidl_cb(status, outStreams);
-    return Void();
+    return;
 }
 
 bool CameraDeviceSession::preProcessConfigurationLocked_3_4(
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 fdc8a5a..00500b1 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
@@ -87,6 +87,12 @@
     void postProcessConfigurationFailureLocked_3_4(
             const StreamConfiguration& requestedConfiguration);
 
+    void configureStreams_3_4_Impl(
+            const StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_3_4_cb _hidl_cb,
+            // Optional argument for ICameraDeviceSession@3.5 impl
+            uint32_t streamConfigCounter = 0);
+
     Return<void> processCaptureRequest_3_4(
             const hidl_vec<V3_4::CaptureRequest>& requests,
             const hidl_vec<V3_2::BufferCache>& cachesToRemove,
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index 963893a..0770f04 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -15,8 +15,10 @@
  */
 
 #define LOG_TAG "CamDevSession@3.5-impl"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
 #include <android/log.h>
 
+#include <vector>
 #include <utils/Trace.h>
 #include "CameraDeviceSession.h"
 
@@ -33,13 +35,26 @@
     const sp<V3_2::ICameraDeviceCallback>& callback) :
         V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) {
 
-    mHasCallback_3_5 = false;
+    mCallback_3_5 = nullptr;
 
     auto castResult = ICameraDeviceCallback::castFrom(callback);
     if (castResult.isOk()) {
         sp<ICameraDeviceCallback> callback3_5 = castResult;
         if (callback3_5 != nullptr) {
-            mHasCallback_3_5 = true;
+            mCallback_3_5 = callback3_5;
+        }
+    }
+
+    if (mCallback_3_5 != nullptr) {
+        camera_metadata_entry bufMgrVersion = mDeviceInfo.find(
+                ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION);
+        if (bufMgrVersion.count > 0) {
+            mSupportBufMgr = (bufMgrVersion.data.u8[0] ==
+                    ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5);
+            if (mSupportBufMgr) {
+                request_stream_buffers = sRequestStreamBuffers;
+                return_stream_buffers = sReturnStreamBuffers;
+            }
         }
     }
 }
@@ -50,14 +65,297 @@
 Return<void> CameraDeviceSession::configureStreams_3_5(
         const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb)  {
-    return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
+    configureStreams_3_4_Impl(requestedConfiguration.v3_4, _hidl_cb,
+            requestedConfiguration.streamConfigCounter);
+    return Void();
 }
 
 Return<void> CameraDeviceSession::signalStreamFlush(
-        const hidl_vec<int32_t>& /*requests*/, uint32_t /*streamConfigCounter*/) {
+        const hidl_vec<int32_t>& streamIds, uint32_t streamConfigCounter) {
+    std::vector<camera3_stream_t*> streams(streamIds.size());
+    {
+        Mutex::Autolock _l(mInflightLock);
+        for (size_t i = 0; i < streamIds.size(); i++) {
+            int32_t id = streamIds[i];
+            if (mStreamMap.count(id) == 0) {
+                ALOGE("%s: unknown streamId %d", __FUNCTION__, id);
+                return Void();
+            }
+            streams[i] = &mStreamMap[id];
+        }
+    }
+    if (mDevice->ops->signal_stream_flush != nullptr) {
+        mDevice->ops->signal_stream_flush(mDevice,
+                streamConfigCounter, streams.size(), streams.data());
+    }
     return Void();
 }
 
+Status CameraDeviceSession::importRequest(
+        const CaptureRequest& request,
+        hidl_vec<buffer_handle_t*>& allBufPtrs,
+        hidl_vec<int>& allFences) {
+    if (mSupportBufMgr) {
+        return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ true);
+    }
+    return importRequestImpl(request, allBufPtrs, allFences, /*allowEmptyBuf*/ false);
+}
+
+void CameraDeviceSession::pushBufferId(
+        const buffer_handle_t& buf, uint64_t bufferId, int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+    // emplace will return existing entry if there is one.
+    auto pair = mBufferIdMaps.emplace(streamId, BufferIdMap{});
+    BufferIdMap& bIdMap = pair.first->second;
+    bIdMap[buf] = bufferId;
+}
+
+uint64_t CameraDeviceSession::popBufferId(
+        const buffer_handle_t& buf, int streamId) {
+    std::lock_guard<std::mutex> lock(mBufferIdMapLock);
+
+    auto streamIt = mBufferIdMaps.find(streamId);
+    if (streamIt == mBufferIdMaps.end()) {
+        return BUFFER_ID_NO_BUFFER;
+    }
+    BufferIdMap& bIdMap = streamIt->second;
+    auto it = bIdMap.find(buf);
+    if (it == bIdMap.end()) {
+        return BUFFER_ID_NO_BUFFER;
+    }
+    uint64_t bufId = it->second;
+    bIdMap.erase(it);
+    if (bIdMap.empty()) {
+        mBufferIdMaps.erase(streamIt);
+    }
+    return bufId;
+}
+
+uint64_t CameraDeviceSession::getCapResultBufferId(const buffer_handle_t& buf, int streamId) {
+    if (mSupportBufMgr) {
+        return popBufferId(buf, streamId);
+    }
+    return BUFFER_ID_NO_BUFFER;
+}
+
+Camera3Stream* CameraDeviceSession::getStreamPointer(int32_t streamId) {
+    Mutex::Autolock _l(mInflightLock);
+    if (mStreamMap.count(streamId) == 0) {
+        ALOGE("%s: unknown streamId %d", __FUNCTION__, streamId);
+        return nullptr;
+    }
+    return &mStreamMap[streamId];
+}
+
+void CameraDeviceSession::cleanupInflightBufferFences(
+        std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs) {
+    hidl_vec<int> hFences = fences;
+    cleanupInflightFences(hFences, fences.size());
+    for (auto& p : bufs) {
+        popBufferId(p.first, p.second);
+    }
+}
+
+camera3_buffer_request_status_t CameraDeviceSession::requestStreamBuffers(
+        uint32_t num_buffer_reqs,
+        const camera3_buffer_request_t *buffer_reqs,
+        /*out*/uint32_t *num_returned_buf_reqs,
+        /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+    ATRACE_CALL();
+    *num_returned_buf_reqs = 0;
+    hidl_vec<BufferRequest> hBufReqs(num_buffer_reqs);
+    for (size_t i = 0; i < num_buffer_reqs; i++) {
+        hBufReqs[i].streamId =
+                static_cast<Camera3Stream*>(buffer_reqs[i].stream)->mId;
+        hBufReqs[i].numBuffersRequested = buffer_reqs[i].num_buffers_requested;
+    }
+
+    ATRACE_BEGIN("HIDL requestStreamBuffers");
+    BufferRequestStatus status;
+    hidl_vec<StreamBufferRet> bufRets;
+    auto err = mCallback_3_5->requestStreamBuffers(hBufReqs,
+            [&status, &bufRets]
+            (BufferRequestStatus s, const hidl_vec<StreamBufferRet>& rets) {
+                status = s;
+                bufRets = std::move(rets);
+            });
+    if (!err.isOk()) {
+        ALOGE("%s: Transaction error: %s", __FUNCTION__, err.description().c_str());
+        return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+    }
+    ATRACE_END();
+
+    if (status == BufferRequestStatus::OK || status == BufferRequestStatus::FAILED_PARTIAL) {
+        if (bufRets.size() != num_buffer_reqs) {
+            ALOGE("%s: expect %d buffer requests returned, only got %zu",
+                    __FUNCTION__, num_buffer_reqs, bufRets.size());
+            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+        }
+
+        for (size_t i = 0; i < num_buffer_reqs; i++) {
+            // maybe we can query all streams in one call to avoid frequent locking device here?
+            Camera3Stream* stream = getStreamPointer(bufRets[i].streamId);
+            if (stream == nullptr) {
+                ALOGE("%s: unknown streamId %d", __FUNCTION__, bufRets[i].streamId);
+                return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+            }
+            returned_buf_reqs[i].stream = stream;
+        }
+
+        std::vector<int> importedFences;
+        std::vector<std::pair<buffer_handle_t, int>> importedBuffers;
+        for (size_t i = 0; i < num_buffer_reqs; i++) {
+            int streamId = bufRets[i].streamId;
+            switch (bufRets[i].val.getDiscriminator()) {
+                case StreamBuffersVal::hidl_discriminator::error:
+                    returned_buf_reqs[i].num_output_buffers = 0;
+                    switch (bufRets[i].val.error()) {
+                        case StreamBufferRequestError::NO_BUFFER_AVAILABLE:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_NO_BUFFER_AVAILABLE;
+                            break;
+                        case StreamBufferRequestError::MAX_BUFFER_EXCEEDED:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_MAX_BUFFER_EXCEEDED;
+                            break;
+                        case StreamBufferRequestError::STREAM_DISCONNECTED:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_STREAM_DISCONNECTED;
+                            break;
+                        case StreamBufferRequestError::UNKNOWN_ERROR:
+                            returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_UNKNOWN_ERROR;
+                            break;
+                        default:
+                            ALOGE("%s: Unknown StreamBufferRequestError %d",
+                                    __FUNCTION__, bufRets[i].val.error());
+                            cleanupInflightBufferFences(importedFences, importedBuffers);
+                            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+                    }
+                    break;
+                case StreamBuffersVal::hidl_discriminator::buffers: {
+                    const hidl_vec<StreamBuffer>& hBufs = bufRets[i].val.buffers();
+                    camera3_stream_buffer_t* outBufs = returned_buf_reqs[i].output_buffers;
+                    for (size_t b = 0; b < hBufs.size(); b++) {
+                        const StreamBuffer& hBuf = hBufs[b];
+                        camera3_stream_buffer_t& outBuf = outBufs[b];
+                        // maybe add importBuffers API to avoid frequent locking device?
+                        Status s = importBuffer(streamId,
+                                hBuf.bufferId, hBuf.buffer.getNativeHandle(),
+                                /*out*/&(outBuf.buffer),
+                                /*allowEmptyBuf*/false);
+                        if (s != Status::OK) {
+                            ALOGE("%s: import stream %d bufferId %" PRIu64 " failed!",
+                                    __FUNCTION__, streamId, hBuf.bufferId);
+                            cleanupInflightBufferFences(importedFences, importedBuffers);
+                            // Buffer import should never fail - restart HAL since something is very
+                            // wrong.
+                            assert(false);
+                            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+                        }
+
+                        pushBufferId(*(outBuf.buffer), hBuf.bufferId, streamId);
+                        importedBuffers.push_back(std::make_pair(*(outBuf.buffer), streamId));
+
+                        if (!sHandleImporter.importFence(
+                                hBuf.acquireFence,
+                                outBuf.acquire_fence)) {
+                            ALOGE("%s: stream %d bufferId %" PRIu64 "acquire fence is invalid",
+                                    __FUNCTION__, streamId, hBuf.bufferId);
+                            cleanupInflightBufferFences(importedFences, importedBuffers);
+                            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+                        }
+                        importedFences.push_back(outBuf.acquire_fence);
+                        outBuf.stream = returned_buf_reqs[i].stream;
+                        outBuf.status = CAMERA3_BUFFER_STATUS_OK;
+                        outBuf.release_fence = -1;
+                    }
+                    returned_buf_reqs[i].status = CAMERA3_PS_BUF_REQ_OK;
+                } break;
+                default:
+                    ALOGE("%s: unknown StreamBuffersVal discrimator!", __FUNCTION__);
+                    cleanupInflightBufferFences(importedFences, importedBuffers);
+                    return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+            }
+        }
+
+        *num_returned_buf_reqs = num_buffer_reqs;
+
+        return (status == BufferRequestStatus::OK) ?
+                CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL;
+    }
+
+    switch (status) {
+        case BufferRequestStatus::FAILED_CONFIGURING:
+            return CAMERA3_BUF_REQ_FAILED_CONFIGURING;
+        case BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS:
+            return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+        case BufferRequestStatus::FAILED_UNKNOWN:
+        default:
+            return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+    }
+}
+
+void CameraDeviceSession::returnStreamBuffers(
+        uint32_t num_buffers,
+        const camera3_stream_buffer_t* const* buffers) {
+    ATRACE_CALL();
+    hidl_vec<StreamBuffer> hBufs(num_buffers);
+
+    for (size_t i = 0; i < num_buffers; i++) {
+        hBufs[i].streamId =
+                static_cast<Camera3Stream*>(buffers[i]->stream)->mId;
+        hBufs[i].buffer = nullptr; // use bufferId
+        hBufs[i].bufferId = popBufferId(*(buffers[i]->buffer), hBufs[i].streamId);
+        if (hBufs[i].bufferId == BUFFER_ID_NO_BUFFER) {
+            ALOGE("%s: unknown buffer is returned to stream %d",
+                    __FUNCTION__, hBufs[i].streamId);
+        }
+        // ERROR since the buffer is not for application to consume
+        hBufs[i].status = BufferStatus::ERROR;
+        // skip acquire fence since it's of no use to camera service
+        if (buffers[i]->release_fence != -1) {
+            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+            handle->data[0] = buffers[i]->release_fence;
+            hBufs[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+        }
+    }
+
+    mCallback_3_5->returnStreamBuffers(hBufs);
+    return;
+}
+
+/**
+ * Static callback forwarding methods from HAL to instance
+ */
+camera3_buffer_request_status_t CameraDeviceSession::sRequestStreamBuffers(
+        const struct camera3_callback_ops *cb,
+        uint32_t num_buffer_reqs,
+        const camera3_buffer_request_t *buffer_reqs,
+        /*out*/uint32_t *num_returned_buf_reqs,
+        /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs) {
+    CameraDeviceSession *d =
+            const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+    if (num_buffer_reqs == 0 || buffer_reqs == nullptr || num_returned_buf_reqs == nullptr ||
+            returned_buf_reqs == nullptr) {
+        ALOGE("%s: bad argument: numBufReq %d, bufReqs %p, numRetBufReq %p, retBufReqs %p",
+                __FUNCTION__, num_buffer_reqs, buffer_reqs,
+                num_returned_buf_reqs, returned_buf_reqs);
+        return CAMERA3_BUF_REQ_FAILED_ILLEGAL_ARGUMENTS;
+    }
+
+    return d->requestStreamBuffers(num_buffer_reqs, buffer_reqs,
+            num_returned_buf_reqs, returned_buf_reqs);
+}
+
+void CameraDeviceSession::sReturnStreamBuffers(
+        const struct camera3_callback_ops *cb,
+        uint32_t num_buffers,
+        const camera3_stream_buffer_t* const* buffers) {
+    CameraDeviceSession *d =
+            const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+    d->returnStreamBuffers(num_buffers, buffers);
+}
+
 } // namespace implementation
 }  // namespace V3_5
 }  // namespace device
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
index ec34769..4f7284c 100644
--- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
@@ -21,6 +21,7 @@
 #include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
 #include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h>
+#include <unordered_map>
 
 namespace android {
 namespace hardware {
@@ -30,11 +31,14 @@
 namespace implementation {
 
 using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::BufferStatus;
 using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::StreamBuffer;
 using ::android::hardware::camera::device::V3_5::StreamConfiguration;
 using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
 using ::android::hardware::camera::device::V3_5::ICameraDeviceSession;
 using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::implementation::Camera3Stream;
 using ::android::hardware::camera::common::V1_0::Status;
 using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
 using ::android::hardware::Return;
@@ -44,6 +48,25 @@
 using ::android::sp;
 using ::android::Mutex;
 
+
+/**
+ * Function pointer types with C calling convention to
+ * use for HAL callback functions.
+ */
+extern "C" {
+    typedef camera3_buffer_request_status_t (callbacks_request_stream_buffer_t)(
+            const struct camera3_callback_ops *,
+            uint32_t num_buffer_reqs,
+            const camera3_buffer_request_t *buffer_reqs,
+            /*out*/uint32_t *num_returned_buf_reqs,
+            /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+    typedef void (callbacks_return_stream_buffer_t)(
+            const struct camera3_callback_ops *,
+            uint32_t num_buffers,
+            const camera3_stream_buffer_t* const* buffers);
+}
+
 struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession {
 
     CameraDeviceSession(camera3_device_t*,
@@ -62,12 +85,85 @@
             ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb);
 
     Return<void> signalStreamFlush(
-            const hidl_vec<int32_t>& requests,
+            const hidl_vec<int32_t>& streamIds,
             uint32_t streamConfigCounter);
 
+    virtual Status importRequest(
+            const CaptureRequest& request,
+            hidl_vec<buffer_handle_t*>& allBufPtrs,
+            hidl_vec<int>& allFences) override;
 
-    // Whether this camera device session is created with version 3.5 callback.
-    bool mHasCallback_3_5;
+    /**
+     * Static callback forwarding methods from HAL to instance
+     */
+    static callbacks_request_stream_buffer_t sRequestStreamBuffers;
+    static callbacks_return_stream_buffer_t sReturnStreamBuffers;
+
+    camera3_buffer_request_status_t requestStreamBuffers(
+            uint32_t num_buffer_reqs,
+            const camera3_buffer_request_t *buffer_reqs,
+            /*out*/uint32_t *num_returned_buf_reqs,
+            /*out*/camera3_stream_buffer_ret_t *returned_buf_reqs);
+
+    void returnStreamBuffers(
+            uint32_t num_buffers,
+            const camera3_stream_buffer_t* const* buffers);
+
+    struct BufferHasher {
+        size_t operator()(const buffer_handle_t& buf) const {
+            if (buf == nullptr)
+                return 0;
+
+            size_t result = 1;
+            result = 31 * result + buf->numFds;
+            for (int i = 0; i < buf->numFds; i++) {
+                result = 31 * result + buf->data[i];
+            }
+            return result;
+        }
+    };
+
+    struct BufferComparator {
+        bool operator()(const buffer_handle_t& buf1, const buffer_handle_t& buf2) const {
+            if (buf1->numFds == buf2->numFds) {
+                for (int i = 0; i < buf1->numFds; i++) {
+                    if (buf1->data[i] != buf2->data[i]) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+    };
+
+    Camera3Stream* getStreamPointer(int32_t streamId);
+
+    // Register buffer to mBufferIdMaps so we can find corresponding bufferId
+    // when the buffer is returned to camera service
+    void pushBufferId(const buffer_handle_t& buf, uint64_t bufferId, int streamId);
+
+    // Method to pop buffer's bufferId from mBufferIdMaps
+    // BUFFER_ID_NO_BUFFER is returned if no matching buffer is found
+    uint64_t popBufferId(const buffer_handle_t& buf, int streamId);
+
+    // Method to cleanup imported buffer/fences if requestStreamBuffers fails half way
+    void cleanupInflightBufferFences(
+            std::vector<int>& fences, std::vector<std::pair<buffer_handle_t, int>>& bufs);
+
+    // Overrides the default constructCaptureResult behavior for buffer management APIs
+    virtual uint64_t getCapResultBufferId(const buffer_handle_t& buf, int streamId) override;
+
+    std::mutex mBufferIdMapLock; // protecting mBufferIdMaps and mNextBufferId
+    typedef std::unordered_map<const buffer_handle_t, uint64_t,
+            BufferHasher, BufferComparator> BufferIdMap;
+    // stream ID -> per stream buffer ID map for buffers coming from requestStreamBuffers API
+    // Entries are created during requestStreamBuffers when a stream first request a buffer, and
+    // deleted in returnStreamBuffers/processCaptureResult* when all buffers are returned
+    std::unordered_map<int, BufferIdMap> mBufferIdMaps;
+
+    sp<ICameraDeviceCallback> mCallback_3_5;
+    bool mSupportBufMgr;
 
 private: