Camera3: Unblock capture_request in correct condition

Previously we were only checking max buffer dequeued when
metadata callback happens. HAL needs to do the same check
in buffer callback.

This change also breaks down the captureResultCb() function
which is long overdue.

This should help improve latency and performance because
we are unblocking capture_request early.

Bug: 11011342
Change-Id: I37a37e78a3534f780b4a92e46ab21f5ae78b5329
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index 5e2b0ac..ccb2593 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -922,6 +922,341 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : handleMetadataWithLock
+ *
+ * DESCRIPTION: Handles metadata buffer callback with mMutex lock held.
+ *
+ * PARAMETERS : @metadata_buf: metadata buffer
+ *
+ * RETURN     :
+ *
+ *==========================================================================*/
+void QCamera3HardwareInterface::handleMetadataWithLock(
+    mm_camera_super_buf_t *metadata_buf)
+{
+    metadata_buffer_t *metadata = (metadata_buffer_t *)metadata_buf->bufs[0]->buffer;
+    int32_t frame_number_valid = *(int32_t *)
+        POINTER_OF(CAM_INTF_META_FRAME_NUMBER_VALID, metadata);
+    uint32_t pending_requests = *(uint32_t *)POINTER_OF(
+        CAM_INTF_META_PENDING_REQUESTS, metadata);
+    uint32_t frame_number = *(uint32_t *)
+        POINTER_OF(CAM_INTF_META_FRAME_NUMBER, metadata);
+    const struct timeval *tv = (const struct timeval *)
+        POINTER_OF(CAM_INTF_META_SENSOR_TIMESTAMP, metadata);
+    nsecs_t capture_time = (nsecs_t)tv->tv_sec * NSEC_PER_SEC +
+        tv->tv_usec * NSEC_PER_USEC;
+    cam_frame_dropped_t cam_frame_drop = *(cam_frame_dropped_t *)
+        POINTER_OF(CAM_INTF_META_FRAME_DROPPED, metadata);
+
+    if (!frame_number_valid) {
+        ALOGV("%s: Not a valid frame number, used as SOF only", __func__);
+        mMetadataChannel->bufDone(metadata_buf);
+        free(metadata_buf);
+        goto done_metadata;
+    }
+    ALOGV("%s: valid frame_number = %d, capture_time = %lld", __func__,
+            frame_number, capture_time);
+
+    // Go through the pending requests info and send shutter/results to frameworks
+    for (List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin();
+        i != mPendingRequestsList.end() && i->frame_number <= frame_number;) {
+        camera3_capture_result_t result;
+        camera3_notify_msg_t notify_msg;
+        ALOGV("%s: frame_number in the list is %d", __func__, i->frame_number);
+
+        // Flush out all entries with less or equal frame numbers.
+
+        //TODO: Make sure shutter timestamp really reflects shutter timestamp.
+        //Right now it's the same as metadata timestamp
+
+        //TODO: When there is metadata drop, how do we derive the timestamp of
+        //dropped frames? For now, we fake the dropped timestamp by substracting
+        //from the reported timestamp
+        nsecs_t current_capture_time = capture_time -
+            (frame_number - i->frame_number) * NSEC_PER_33MSEC;
+
+        // Send shutter notify to frameworks
+        notify_msg.type = CAMERA3_MSG_SHUTTER;
+        notify_msg.message.shutter.frame_number = i->frame_number;
+        notify_msg.message.shutter.timestamp = current_capture_time;
+        mCallbackOps->notify(mCallbackOps, &notify_msg);
+        ALOGV("%s: notify frame_number = %d, capture_time = %lld", __func__,
+                i->frame_number, capture_time);
+
+        // Check whether any stream buffer corresponding to this is dropped or not
+        // If dropped, then send the ERROR_BUFFER for the corresponding stream
+        if (cam_frame_drop.frame_dropped) {
+            camera3_notify_msg_t notify_msg;
+            for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
+                    j != i->buffers.end(); j++) {
+                QCamera3Channel *channel = (QCamera3Channel *)j->stream->priv;
+                uint32_t streamTypeMask = channel->getStreamTypeMask();
+                if (streamTypeMask & cam_frame_drop.stream_type_mask) {
+                    // Send Error notify to frameworks with CAMERA3_MSG_ERROR_BUFFER
+                    ALOGV("%s: Start of reporting error frame#=%d, streamMask=%d",
+                           __func__, i->frame_number, streamTypeMask);
+                    notify_msg.type = CAMERA3_MSG_ERROR;
+                    notify_msg.message.error.frame_number = i->frame_number;
+                    notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER ;
+                    notify_msg.message.error.error_stream = j->stream;
+                    mCallbackOps->notify(mCallbackOps, &notify_msg);
+                    ALOGV("%s: End of reporting error frame#=%d, streamMask=%d",
+                           __func__, i->frame_number, streamTypeMask);
+                    PendingFrameDropInfo PendingFrameDrop;
+                    PendingFrameDrop.frame_number=i->frame_number;
+                    PendingFrameDrop.stream_type_mask = cam_frame_drop.stream_type_mask;
+                    // Add the Frame drop info to mPendingFrameDropList
+                    mPendingFrameDropList.push_back(PendingFrameDrop);
+                }
+            }
+        }
+
+        // Send empty metadata with already filled buffers for dropped metadata
+        // and send valid metadata with already filled buffers for current metadata
+        if (i->frame_number < frame_number) {
+            CameraMetadata dummyMetadata;
+            dummyMetadata.update(ANDROID_SENSOR_TIMESTAMP,
+                    &current_capture_time, 1);
+            dummyMetadata.update(ANDROID_REQUEST_ID,
+                    &(i->request_id), 1);
+            result.result = dummyMetadata.release();
+        } else {
+            result.result = translateCbMetadataToResultMetadata(metadata,
+                    current_capture_time, i->request_id, i->blob_request,
+                    &(i->input_jpeg_settings));
+            if (mIsZslMode) {
+                int found_metadata = 0;
+                //for ZSL case store the metadata buffer and corresp. ZSL handle ptr
+                for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
+                    j != i->buffers.end(); j++) {
+                    if (j->stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
+                        //check if corresp. zsl already exists in the stored metadata list
+                        for (List<MetadataBufferInfo>::iterator m = mStoredMetadataList.begin();
+                                m != mStoredMetadataList.begin(); m++) {
+                            if (m->frame_number == frame_number) {
+                                m->meta_buf = metadata_buf;
+                                found_metadata = 1;
+                                break;
+                            }
+                        }
+                        if (!found_metadata) {
+                            MetadataBufferInfo store_meta_info;
+                            store_meta_info.meta_buf = metadata_buf;
+                            store_meta_info.frame_number = frame_number;
+                            mStoredMetadataList.push_back(store_meta_info);
+                            found_metadata = 1;
+                        }
+                    }
+                }
+                if (!found_metadata) {
+                    if (!i->input_buffer_present && i->blob_request) {
+                        //livesnapshot or fallback non-zsl snapshot case
+                        for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
+                                j != i->buffers.end(); j++){
+                            if (j->stream->stream_type == CAMERA3_STREAM_OUTPUT &&
+                                j->stream->format == HAL_PIXEL_FORMAT_BLOB) {
+                                mPictureChannel->queueMetadata(metadata_buf,mMetadataChannel,true);
+                                break;
+                            }
+                        }
+                    } else {
+                        //return the metadata immediately
+                        mMetadataChannel->bufDone(metadata_buf);
+                        free(metadata_buf);
+                    }
+                }
+            } else if (!mIsZslMode && i->blob_request) {
+                //If it is a blob request then send the metadata to the picture channel
+                mPictureChannel->queueMetadata(metadata_buf,mMetadataChannel,true);
+            } else {
+                // Return metadata buffer
+                mMetadataChannel->bufDone(metadata_buf);
+                free(metadata_buf);
+            }
+        }
+        if (!result.result) {
+            ALOGE("%s: metadata is NULL", __func__);
+        }
+        result.frame_number = i->frame_number;
+        result.num_output_buffers = 0;
+        result.output_buffers = NULL;
+        for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
+                    j != i->buffers.end(); j++) {
+            if (j->buffer) {
+                result.num_output_buffers++;
+            }
+        }
+
+        if (result.num_output_buffers > 0) {
+            camera3_stream_buffer_t *result_buffers =
+                new camera3_stream_buffer_t[result.num_output_buffers];
+            if (!result_buffers) {
+                ALOGE("%s: Fatal error: out of memory", __func__);
+            }
+            size_t result_buffers_idx = 0;
+            for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
+                    j != i->buffers.end(); j++) {
+                if (j->buffer) {
+                    for (List<PendingFrameDropInfo>::iterator m = mPendingFrameDropList.begin();
+                            m != mPendingFrameDropList.end(); m++) {
+                        QCamera3Channel *channel = (QCamera3Channel *)j->buffer->stream->priv;
+                        uint32_t streamTypeMask = channel->getStreamTypeMask();
+                        if((m->stream_type_mask & streamTypeMask) &&
+                                (m->frame_number==frame_number)) {
+                            j->buffer->status=CAMERA3_BUFFER_STATUS_ERROR;
+                            ALOGV("%s: Stream STATUS_ERROR frame_number=%d, streamTypeMask=%d",
+                                  __func__, frame_number, streamTypeMask);
+                            m = mPendingFrameDropList.erase(m);
+                            break;
+                        }
+                    }
+                    result_buffers[result_buffers_idx++] = *(j->buffer);
+                    free(j->buffer);
+                    j->buffer = NULL;
+                    mPendingBuffersMap.editValueFor(j->stream)--;
+                }
+            }
+            result.output_buffers = result_buffers;
+
+            mCallbackOps->process_capture_result(mCallbackOps, &result);
+            ALOGV("%s: meta frame_number = %d, capture_time = %lld",
+                    __func__, result.frame_number, current_capture_time);
+            free_camera_metadata((camera_metadata_t *)result.result);
+            delete[] result_buffers;
+        } else {
+            mCallbackOps->process_capture_result(mCallbackOps, &result);
+            ALOGV("%s: meta frame_number = %d, capture_time = %lld",
+                        __func__, result.frame_number, current_capture_time);
+            free_camera_metadata((camera_metadata_t *)result.result);
+        }
+        // erase the element from the list
+        i = mPendingRequestsList.erase(i);
+    }
+
+done_metadata:
+    if (!pending_requests)
+        unblockRequestIfNecessary();
+
+}
+
+/*===========================================================================
+ * FUNCTION   : handleBufferWithLock
+ *
+ * DESCRIPTION: Handles image buffer callback with mMutex lock held.
+ *
+ * PARAMETERS : @buffer: image buffer for the callback
+ *              @frame_number: frame number of the image buffer
+ *
+ * RETURN     :
+ *
+ *==========================================================================*/
+void QCamera3HardwareInterface::handleBufferWithLock(
+    camera3_stream_buffer_t *buffer, uint32_t frame_number)
+{
+    // If the frame number doesn't exist in the pending request list,
+    // directly send the buffer to the frameworks, and update pending buffers map
+    // Otherwise, book-keep the buffer.
+    List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin();
+    while (i != mPendingRequestsList.end() && i->frame_number != frame_number){
+        i++;
+    }
+    if (i == mPendingRequestsList.end()) {
+        // Verify all pending requests frame_numbers are greater
+        for (List<PendingRequestInfo>::iterator j = mPendingRequestsList.begin();
+                j != mPendingRequestsList.end(); j++) {
+            if (j->frame_number < frame_number) {
+                ALOGE("%s: Error: pending frame number %d is smaller than %d",
+                        __func__, j->frame_number, frame_number);
+            }
+        }
+        camera3_capture_result_t result;
+        result.result = NULL;
+        result.frame_number = frame_number;
+        result.num_output_buffers = 1;
+        for (List<PendingFrameDropInfo>::iterator m = mPendingFrameDropList.begin();
+                m != mPendingFrameDropList.end(); m++) {
+            QCamera3Channel *channel = (QCamera3Channel *)buffer->stream->priv;
+            uint32_t streamTypeMask = channel->getStreamTypeMask();
+            if((m->stream_type_mask & streamTypeMask) &&
+                (m->frame_number==frame_number) ) {
+                buffer->status=CAMERA3_BUFFER_STATUS_ERROR;
+                ALOGV("%s: Stream STATUS_ERROR frame_number=%d, streamTypeMask=%d",
+                        __func__, frame_number, streamTypeMask);
+                m = mPendingFrameDropList.erase(m);
+                break;
+            }
+        }
+        result.output_buffers = buffer;
+        ALOGV("%s: result frame_number = %d, buffer = %p",
+                __func__, frame_number, buffer);
+        mPendingBuffersMap.editValueFor(buffer->stream)--;
+        if (buffer->stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
+            int found = 0;
+            for (List<MetadataBufferInfo>::iterator k = mStoredMetadataList.begin();
+                k != mStoredMetadataList.end(); k++) {
+                if (k->frame_number == frame_number) {
+                    k->zsl_buf_hdl = buffer->buffer;
+                    found = 1;
+                    break;
+                }
+            }
+            if (!found) {
+                MetadataBufferInfo meta_info;
+                meta_info.frame_number = frame_number;
+                meta_info.zsl_buf_hdl = buffer->buffer;
+                mStoredMetadataList.push_back(meta_info);
+            }
+        }
+        mCallbackOps->process_capture_result(mCallbackOps, &result);
+        unblockRequestIfNecessary();
+    } else {
+        for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
+                j != i->buffers.end(); j++) {
+            if (j->stream == buffer->stream) {
+                if (j->buffer != NULL) {
+                    ALOGE("%s: Error: buffer is already set", __func__);
+                } else {
+                    j->buffer = (camera3_stream_buffer_t *)malloc(
+                            sizeof(camera3_stream_buffer_t));
+                    *(j->buffer) = *buffer;
+                    ALOGV("%s: cache buffer %p at result frame_number %d",
+                            __func__, buffer, frame_number);
+                }
+            }
+        }
+    }
+}
+
+/*===========================================================================
+ * FUNCTION   : unblockRequestIfNecessary
+ *
+ * DESCRIPTION: Unblock capture_request if max_buffer hasn't been reached. Note
+ *              that mMutex is held when this function is called.
+ *
+ * PARAMETERS :
+ *
+ * RETURN     :
+ *
+ *==========================================================================*/
+void QCamera3HardwareInterface::unblockRequestIfNecessary()
+{
+    bool max_buffers_dequeued = false;
+    for (size_t i = 0; i < mPendingBuffersMap.size(); i++) {
+        const camera3_stream_t *stream = mPendingBuffersMap.keyAt(i);
+        uint32_t queued_buffers = mPendingBuffersMap.valueAt(i);
+        if (queued_buffers == stream->max_buffers) {
+            max_buffers_dequeued = true;
+            break;
+        }
+    }
+    if (!max_buffers_dequeued) {
+        // Unblock process_capture_request
+        mPendingRequest = 0;
+        pthread_cond_signal(&mRequestCond);
+    }
+}
+
+/*===========================================================================
  * FUNCTION   : registerStreamBuffers
  *
  * DESCRIPTION: Register buffers for a given stream with the HAL device.
@@ -1314,296 +1649,11 @@
 {
     pthread_mutex_lock(&mMutex);
 
-    if (metadata_buf) {
-        metadata_buffer_t *metadata = (metadata_buffer_t *)metadata_buf->bufs[0]->buffer;
-        int32_t frame_number_valid = *(int32_t *)
-            POINTER_OF(CAM_INTF_META_FRAME_NUMBER_VALID, metadata);
-        uint32_t pending_requests = *(uint32_t *)POINTER_OF(
-            CAM_INTF_META_PENDING_REQUESTS, metadata);
-        uint32_t frame_number = *(uint32_t *)
-            POINTER_OF(CAM_INTF_META_FRAME_NUMBER, metadata);
-        const struct timeval *tv = (const struct timeval *)
-            POINTER_OF(CAM_INTF_META_SENSOR_TIMESTAMP, metadata);
-        nsecs_t capture_time = (nsecs_t)tv->tv_sec * NSEC_PER_SEC +
-            tv->tv_usec * NSEC_PER_USEC;
-        cam_frame_dropped_t cam_frame_drop = *(cam_frame_dropped_t *)
-            POINTER_OF(CAM_INTF_META_FRAME_DROPPED, metadata);
+    if (metadata_buf)
+        handleMetadataWithLock(metadata_buf);
+    else
+        handleBufferWithLock(buffer, frame_number);
 
-        if (!frame_number_valid) {
-            ALOGV("%s: Not a valid frame number, used as SOF only", __func__);
-            mMetadataChannel->bufDone(metadata_buf);
-            free(metadata_buf);
-            goto done_metadata;
-        }
-        ALOGV("%s: valid frame_number = %d, capture_time = %lld", __func__,
-                frame_number, capture_time);
-
-        // Go through the pending requests info and send shutter/results to frameworks
-        for (List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin();
-                i != mPendingRequestsList.end() && i->frame_number <= frame_number;) {
-            camera3_capture_result_t result;
-            camera3_notify_msg_t notify_msg;
-            ALOGV("%s: frame_number in the list is %d", __func__, i->frame_number);
-
-            // Flush out all entries with less or equal frame numbers.
-
-            //TODO: Make sure shutter timestamp really reflects shutter timestamp.
-            //Right now it's the same as metadata timestamp
-
-            //TODO: When there is metadata drop, how do we derive the timestamp of
-            //dropped frames? For now, we fake the dropped timestamp by substracting
-            //from the reported timestamp
-            nsecs_t current_capture_time = capture_time -
-                (frame_number - i->frame_number) * NSEC_PER_33MSEC;
-
-            // Send shutter notify to frameworks
-            notify_msg.type = CAMERA3_MSG_SHUTTER;
-            notify_msg.message.shutter.frame_number = i->frame_number;
-            notify_msg.message.shutter.timestamp = current_capture_time;
-            mCallbackOps->notify(mCallbackOps, &notify_msg);
-            ALOGV("%s: notify frame_number = %d, capture_time = %lld", __func__,
-                    i->frame_number, capture_time);
-
-            // Check whether any stream buffer corresponding to this is dropped or not
-            // If dropped, then send the ERROR_BUFFER for the corresponding stream
-            if (cam_frame_drop.frame_dropped) {
-                camera3_notify_msg_t notify_msg;
-                for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
-                        j != i->buffers.end(); j++) {
-                    QCamera3Channel *channel = (QCamera3Channel *)j->stream->priv;
-                    uint32_t streamTypeMask = channel->getStreamTypeMask();
-                    if (streamTypeMask & cam_frame_drop.stream_type_mask) {
-                        // Send Error notify to frameworks with CAMERA3_MSG_ERROR_BUFFER
-                        ALOGV("%s: Start of reporting error frame#=%d, streamMask=%d",
-                               __func__, i->frame_number, streamTypeMask);
-                        notify_msg.type = CAMERA3_MSG_ERROR;
-                        notify_msg.message.error.frame_number = i->frame_number;
-                        notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER ;
-                        notify_msg.message.error.error_stream = j->stream;
-                        mCallbackOps->notify(mCallbackOps, &notify_msg);
-                        ALOGV("%s: End of reporting error frame#=%d, streamMask=%d",
-                               __func__, i->frame_number, streamTypeMask);
-                        PendingFrameDropInfo PendingFrameDrop;
-                        PendingFrameDrop.frame_number=i->frame_number;
-                        PendingFrameDrop.stream_type_mask = cam_frame_drop.stream_type_mask;
-                        // Add the Frame drop info to mPendingFrameDropList
-                        mPendingFrameDropList.push_back(PendingFrameDrop);
-                    }
-                }
-            }
-
-            // Send empty metadata with already filled buffers for dropped metadata
-            // and send valid metadata with already filled buffers for current metadata
-            if (i->frame_number < frame_number) {
-                CameraMetadata dummyMetadata;
-                dummyMetadata.update(ANDROID_SENSOR_TIMESTAMP,
-                        &current_capture_time, 1);
-                dummyMetadata.update(ANDROID_REQUEST_ID,
-                        &(i->request_id), 1);
-                result.result = dummyMetadata.release();
-            } else {
-                result.result = translateCbMetadataToResultMetadata(metadata,
-                        current_capture_time, i->request_id, i->blob_request,
-                        &(i->input_jpeg_settings));
-                if (mIsZslMode) {
-                   int found_metadata = 0;
-                   //for ZSL case store the metadata buffer and corresp. ZSL handle ptr
-                   for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
-                        j != i->buffers.end(); j++) {
-                      if (j->stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
-                         //check if corresp. zsl already exists in the stored metadata list
-                         for (List<MetadataBufferInfo>::iterator m = mStoredMetadataList.begin();
-                               m != mStoredMetadataList.begin(); m++) {
-                            if (m->frame_number == frame_number) {
-                               m->meta_buf = metadata_buf;
-                               found_metadata = 1;
-                               break;
-                            }
-                         }
-                         if (!found_metadata) {
-                            MetadataBufferInfo store_meta_info;
-                            store_meta_info.meta_buf = metadata_buf;
-                            store_meta_info.frame_number = frame_number;
-                            mStoredMetadataList.push_back(store_meta_info);
-                            found_metadata = 1;
-                         }
-                      }
-                   }
-                   if (!found_metadata) {
-                       if (!i->input_buffer_present && i->blob_request) {
-                          //livesnapshot or fallback non-zsl snapshot case
-                          for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
-                                j != i->buffers.end(); j++){
-                              if (j->stream->stream_type == CAMERA3_STREAM_OUTPUT &&
-                                  j->stream->format == HAL_PIXEL_FORMAT_BLOB) {
-                                 mPictureChannel->queueMetadata(metadata_buf,mMetadataChannel,true);
-                                 break;
-                              }
-                         }
-                       } else {
-                            //return the metadata immediately
-                            mMetadataChannel->bufDone(metadata_buf);
-                            free(metadata_buf);
-                       }
-                   }
-               } else if (!mIsZslMode && i->blob_request) {
-                   //If it is a blob request then send the metadata to the picture channel
-                   mPictureChannel->queueMetadata(metadata_buf,mMetadataChannel,true);
-               } else {
-                   // Return metadata buffer
-                   mMetadataChannel->bufDone(metadata_buf);
-                   free(metadata_buf);
-               }
-
-            }
-            if (!result.result) {
-                ALOGE("%s: metadata is NULL", __func__);
-            }
-            result.frame_number = i->frame_number;
-            result.num_output_buffers = 0;
-            result.output_buffers = NULL;
-            for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
-                    j != i->buffers.end(); j++) {
-                if (j->buffer) {
-                    result.num_output_buffers++;
-                }
-            }
-
-            if (result.num_output_buffers > 0) {
-                camera3_stream_buffer_t *result_buffers =
-                    new camera3_stream_buffer_t[result.num_output_buffers];
-                if (!result_buffers) {
-                    ALOGE("%s: Fatal error: out of memory", __func__);
-                }
-                size_t result_buffers_idx = 0;
-                for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
-                     j != i->buffers.end(); j++) {
-                     if (j->buffer) {
-                         for (List<PendingFrameDropInfo>::iterator m = mPendingFrameDropList.begin();
-                              m != mPendingFrameDropList.end(); m++) {
-                              QCamera3Channel *channel = (QCamera3Channel *)j->buffer->stream->priv;
-                              uint32_t streamTypeMask = channel->getStreamTypeMask();
-                              if((m->stream_type_mask & streamTypeMask) &&
-                                  (m->frame_number==frame_number)) {
-                                  j->buffer->status=CAMERA3_BUFFER_STATUS_ERROR;
-                                  ALOGV("%s: Stream STATUS_ERROR frame_number=%d, streamTypeMask=%d",
-                                        __func__, frame_number, streamTypeMask);
-                                  m = mPendingFrameDropList.erase(m);
-                                  break;
-                              }
-                         }
-                         result_buffers[result_buffers_idx++] = *(j->buffer);
-                         free(j->buffer);
-                         j->buffer = NULL;
-                         mPendingBuffersMap.editValueFor(j->stream)--;
-                    }
-                }
-                result.output_buffers = result_buffers;
-
-                mCallbackOps->process_capture_result(mCallbackOps, &result);
-                ALOGV("%s: meta frame_number = %d, capture_time = %lld",
-                        __func__, result.frame_number, current_capture_time);
-                free_camera_metadata((camera_metadata_t *)result.result);
-                delete[] result_buffers;
-            } else {
-                mCallbackOps->process_capture_result(mCallbackOps, &result);
-                ALOGV("%s: meta frame_number = %d, capture_time = %lld",
-                        __func__, result.frame_number, current_capture_time);
-                free_camera_metadata((camera_metadata_t *)result.result);
-            }
-            // erase the element from the list
-            i = mPendingRequestsList.erase(i);
-        }
-
-
-done_metadata:
-        bool max_buffers_dequeued = false;
-        for (size_t i = 0; i < mPendingBuffersMap.size(); i++) {
-            const camera3_stream_t *stream = mPendingBuffersMap.keyAt(i);
-            uint32_t queued_buffers = mPendingBuffersMap.valueAt(i);
-            if (queued_buffers == stream->max_buffers) {
-                max_buffers_dequeued = true;
-                break;
-            }
-        }
-        if (!max_buffers_dequeued && !pending_requests) {
-            // Unblock process_capture_request
-            mPendingRequest = 0;
-            pthread_cond_signal(&mRequestCond);
-        }
-    } else {
-        // If the frame number doesn't exist in the pending request list,
-        // directly send the buffer to the frameworks, and update pending buffers map
-        // Otherwise, book-keep the buffer.
-        List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin();
-        while (i != mPendingRequestsList.end() && i->frame_number != frame_number){
-            i++;
-        }
-        if (i == mPendingRequestsList.end()) {
-            // Verify all pending requests frame_numbers are greater
-            for (List<PendingRequestInfo>::iterator j = mPendingRequestsList.begin();
-                    j != mPendingRequestsList.end(); j++) {
-                if (j->frame_number < frame_number) {
-                    ALOGE("%s: Error: pending frame number %d is smaller than %d",
-                            __func__, j->frame_number, frame_number);
-                }
-            }
-            camera3_capture_result_t result;
-            result.result = NULL;
-            result.frame_number = frame_number;
-            result.num_output_buffers = 1;
-            for (List<PendingFrameDropInfo>::iterator m = mPendingFrameDropList.begin();
-                  m != mPendingFrameDropList.end(); m++) {
-                QCamera3Channel *channel = (QCamera3Channel *)buffer->stream->priv;
-                uint32_t streamTypeMask = channel->getStreamTypeMask();
-                if((m->stream_type_mask & streamTypeMask) &&
-                    (m->frame_number==frame_number) ) {
-                    buffer->status=CAMERA3_BUFFER_STATUS_ERROR;
-                    ALOGV("%s: Stream STATUS_ERROR frame_number=%d, streamTypeMask=%d",
-                            __func__, frame_number, streamTypeMask);
-                    m = mPendingFrameDropList.erase(m);
-                    break;
-                }
-            }
-            result.output_buffers = buffer;
-            ALOGV("%s: result frame_number = %d, buffer = %p",
-                    __func__, frame_number, buffer);
-            mPendingBuffersMap.editValueFor(buffer->stream)--;
-            if (buffer->stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
-                int found = 0;
-                for (List<MetadataBufferInfo>::iterator k = mStoredMetadataList.begin();
-                      k != mStoredMetadataList.end(); k++) {
-                    if (k->frame_number == frame_number) {
-                        k->zsl_buf_hdl = buffer->buffer;
-                        found = 1;
-                        break;
-                    }
-                }
-                if (!found) {
-                   MetadataBufferInfo meta_info;
-                   meta_info.frame_number = frame_number;
-                   meta_info.zsl_buf_hdl = buffer->buffer;
-                   mStoredMetadataList.push_back(meta_info);
-                }
-            }
-            mCallbackOps->process_capture_result(mCallbackOps, &result);
-        } else {
-            for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
-                    j != i->buffers.end(); j++) {
-                if (j->stream == buffer->stream) {
-                    if (j->buffer != NULL) {
-                        ALOGE("%s: Error: buffer is already set", __func__);
-                    } else {
-                        j->buffer = (camera3_stream_buffer_t *)malloc(
-                                sizeof(camera3_stream_buffer_t));
-                        *(j->buffer) = *buffer;
-                        ALOGV("%s: cache buffer %p at result frame_number %d",
-                                __func__, buffer, frame_number);
-                    }
-                }
-            }
-        }
-    }
     pthread_mutex_unlock(&mMutex);
     return;
 }
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index 5ffc8d2..9073cbe 100755
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -163,6 +163,11 @@
 
     void deriveMinFrameDuration();
     int64_t getMinFrameDuration(const camera3_capture_request_t *request);
+
+    void handleMetadataWithLock(mm_camera_super_buf_t *metadata_buf);
+    void handleBufferWithLock(camera3_stream_buffer_t *buffer,
+        uint32_t frame_number);
+    void unblockRequestIfNecessary();
 public:
 
     bool needOnlineRotation();