Merge "Camera: fix per stream error code for HAL buffer manager"
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index d9c6eef..873ddd0 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -186,111 +186,118 @@
     }
     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;
+            break; // Other status Handled by following code
     }
+
+    if (status != BufferRequestStatus::OK && status != BufferRequestStatus::FAILED_PARTIAL &&
+            status != BufferRequestStatus::FAILED_UNKNOWN) {
+        ALOGE("%s: unknown buffer request error code %d", __FUNCTION__, status);
+        return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+    }
+
+    // Only OK, FAILED_PARTIAL and FAILED_UNKNOWN reaches here
+    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;
+    }
+
+    *num_returned_buf_reqs = num_buffer_reqs;
+    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;
+    }
+
+    // Handle failed streams
+    for (size_t i = 0; i < num_buffer_reqs; i++) {
+        if (bufRets[i].val.getDiscriminator() == 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());
+                    return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+            }
+        }
+    }
+
+    if (status == BufferRequestStatus::FAILED_UNKNOWN) {
+        return CAMERA3_BUF_REQ_FAILED_UNKNOWN;
+    }
+
+    // Only BufferRequestStatus::OK and BufferRequestStatus::FAILED_PARTIAL reaches here
+    std::vector<int> importedFences;
+    std::vector<std::pair<buffer_handle_t, int>> importedBuffers;
+    for (size_t i = 0; i < num_buffer_reqs; i++) {
+        if (bufRets[i].val.getDiscriminator() !=
+                StreamBuffersVal::hidl_discriminator::buffers) {
+            continue;
+        }
+        int streamId = bufRets[i].streamId;
+        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;
+    }
+
+    return (status == BufferRequestStatus::OK) ?
+            CAMERA3_BUF_REQ_OK : CAMERA3_BUF_REQ_FAILED_PARTIAL;
 }
 
 void CameraDeviceSession::returnStreamBuffers(
diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal
index 7cb9727..e3c2350 100644
--- a/camera/device/3.5/types.hal
+++ b/camera/device/3.5/types.hal
@@ -120,7 +120,9 @@
 
     /**
      * Method call failed for all streams and no buffers are returned at all.
-     * Failure due to unknown reason.
+     * Failure due to unknown reason, or all streams has individual failing
+     * reason. For the latter case, check per stream status for each returned
+     * StreamBufferRet.
      */
     FAILED_UNKNOWN = 4,
 };
diff --git a/current.txt b/current.txt
index fd55d7c..f37a8e2 100644
--- a/current.txt
+++ b/current.txt
@@ -444,7 +444,7 @@
 09ab9b24994429d9bb32a3fb420b6f6be3e47eb655139a2c08c4e80d3f33ff95 android.hardware.camera.device@3.5::ICameraDevice
 06237de53c42890029e3f8fe7d1480d078469c0d07608e51c37b4d485d342992 android.hardware.camera.device@3.5::ICameraDeviceCallback
 08c68b196e2fc4e5ba67ba0d0917bde828a87cbe2cffec19d04733972da9eb49 android.hardware.camera.device@3.5::ICameraDeviceSession
-d487ab209944df8987eeca70cf09307fc1429cedf64b0ea9e77c61d8caeb8c15 android.hardware.camera.device@3.5::types
+acaba39216973e58949f50978762bcda1c29f5f7e0bca3e08db21f0767356130 android.hardware.camera.device@3.5::types
 74ec7732fdacb22292c907b49f8f933510851ea1b3ed195c4dcdff35a20387f5 android.hardware.camera.metadata@3.4::types
 0fb39a7809ad1c52b3efbbed5ef4749b06c2a4f1f19cdc3efa2e3d9b28f1205c android.hardware.camera.provider@2.5::ICameraProvider
 f5777403d65135a5407723671bc7a864cdca83aea13ee3ce2894b95e6588ca3a android.hardware.camera.provider@2.5::types