Camera3: Rework flush functionality

 We can have two output buffers per request
 for cases like ZSL. When doing flush the
 process capture result has to be called
 only once for each frame number and should
 contain all cancelled output buffers. Doing
 this on a buffer basis will result in
 unexpected frame number errors in the upper
 framework.
 The buffers should be again grouped depending
 on their frame number and returned back in
 single 'process_capture_result()' call.

Bug: 17113762
Change-Id: I422e86debb2d8e5e8bca1d402479e42f02d915a4
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index 4ce7109..f472b7e 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -1875,14 +1875,16 @@
  *==========================================================================*/
 int QCamera3HardwareInterface::flush()
 {
-
     unsigned int frameNum = 0;
     camera3_notify_msg_t notify_msg;
     camera3_capture_result_t result;
-    camera3_stream_buffer_t pStream_Buf;
+    camera3_stream_buffer_t *pStream_Buf = NULL;
+    FlushMap flushMap;
 
     ALOGV("%s: Unblocking Process Capture Request", __func__);
 
+    memset(&result, 0, sizeof(camera3_capture_result_t));
+
     // Stop the Streams/Channels
     for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
         it != mStreamInfo.end(); it++) {
@@ -1908,105 +1910,132 @@
 
     List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin();
     frameNum = i->frame_number;
-    ALOGV("%s: Latest frame num on  mPendingRequestsList = %d",
+    ALOGV("%s: Oldest frame num on  mPendingRequestsList = %d",
       __func__, frameNum);
 
-    // Go through the pending buffers and send buffer errors
+    // Go through the pending buffers and group them depending
+    // on frame number
     for (List<PendingBufferInfo>::iterator k =
-         mPendingBuffersMap.mPendingBufferList.begin();
-         k != mPendingBuffersMap.mPendingBufferList.end();  ) {
-         ALOGV("%s: frame = %d, buffer = %p, stream = %p, stream format = %d",
-          __func__, k->frame_number, k->buffer, k->stream,
-          k->stream->format);
+            mPendingBuffersMap.mPendingBufferList.begin();
+            k != mPendingBuffersMap.mPendingBufferList.end();) {
 
         if (k->frame_number < frameNum) {
-            // Send Error notify to frameworks for each buffer for which
-            // metadata buffer is already sent
-            ALOGV("%s: Sending ERROR BUFFER for frame %d, buffer %p",
-              __func__, k->frame_number, k->buffer);
-
-            notify_msg.type = CAMERA3_MSG_ERROR;
-            notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
-            notify_msg.message.error.error_stream = k->stream;
-            notify_msg.message.error.frame_number = k->frame_number;
-            mCallbackOps->notify(mCallbackOps, &notify_msg);
-            ALOGV("%s: notify frame_number = %d", __func__,
-                    i->frame_number);
-
-            pStream_Buf.acquire_fence = -1;
-            pStream_Buf.release_fence = -1;
-            pStream_Buf.buffer = k->buffer;
-            pStream_Buf.status = CAMERA3_BUFFER_STATUS_ERROR;
-            pStream_Buf.stream = k->stream;
-
-            memset(&result, 0, sizeof(camera3_capture_result_t));
-            result.result = NULL;
-            result.frame_number = k->frame_number;
-            result.num_output_buffers = 1;
-            result.output_buffers = &pStream_Buf ;
-            mCallbackOps->process_capture_result(mCallbackOps, &result);
+            ssize_t idx = flushMap.indexOfKey(k->frame_number);
+            if (idx == NAME_NOT_FOUND) {
+                Vector<PendingBufferInfo> pending;
+                pending.add(*k);
+                flushMap.add(k->frame_number, pending);
+            } else {
+                Vector<PendingBufferInfo> &pending =
+                        flushMap.editValueFor(k->frame_number);
+                pending.add(*k);
+            }
 
             mPendingBuffersMap.num_buffers--;
             k = mPendingBuffersMap.mPendingBufferList.erase(k);
+        } else {
+            k++;
         }
-        else {
-          k++;
+    }
+
+    for (size_t i = 0; i < flushMap.size(); i++) {
+        uint32_t frame_number = flushMap.keyAt(i);
+        const Vector<PendingBufferInfo> &pending = flushMap.valueAt(i);
+
+        // Send Error notify to frameworks for each buffer for which
+        // metadata buffer is already sent
+        ALOGV("%s: Sending ERROR BUFFER for frame %d number of buffer %d",
+          __func__, frame_number, pending.size());
+
+        pStream_Buf = new camera3_stream_buffer_t[pending.size()];
+        if (NULL == pStream_Buf) {
+            ALOGE("%s: No memory for pending buffers array", __func__);
+            pthread_mutex_unlock(&mMutex);
+            return NO_MEMORY;
         }
+
+        for (size_t j = 0; j < pending.size(); j++) {
+            const PendingBufferInfo &info = pending.itemAt(j);
+            notify_msg.type = CAMERA3_MSG_ERROR;
+            notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER;
+            notify_msg.message.error.error_stream = info.stream;
+            notify_msg.message.error.frame_number = frame_number;
+            pStream_Buf[j].acquire_fence = -1;
+            pStream_Buf[j].release_fence = -1;
+            pStream_Buf[j].buffer = info.buffer;
+            pStream_Buf[j].status = CAMERA3_BUFFER_STATUS_ERROR;
+            pStream_Buf[j].stream = info.stream;
+            mCallbackOps->notify(mCallbackOps, &notify_msg);
+            ALOGV("%s: notify frame_number = %d stream %p", __func__,
+                    frame_number, info.stream);
+        }
+
+        result.result = NULL;
+        result.frame_number = frame_number;
+        result.num_output_buffers = pending.size();
+        result.output_buffers = pStream_Buf;
+        mCallbackOps->process_capture_result(mCallbackOps, &result);
+
+        delete [] pStream_Buf;
     }
 
     ALOGV("%s:Sending ERROR REQUEST for all pending requests", __func__);
 
+    flushMap.clear();
+    for (List<PendingBufferInfo>::iterator k =
+            mPendingBuffersMap.mPendingBufferList.begin();
+            k != mPendingBuffersMap.mPendingBufferList.end();) {
+        ssize_t idx = flushMap.indexOfKey(k->frame_number);
+        if (idx == NAME_NOT_FOUND) {
+            Vector<PendingBufferInfo> pending;
+            pending.add(*k);
+            flushMap.add(k->frame_number, pending);
+        } else {
+            Vector<PendingBufferInfo> &pending =
+                    flushMap.editValueFor(k->frame_number);
+            pending.add(*k);
+        }
+
+        mPendingBuffersMap.num_buffers--;
+        k = mPendingBuffersMap.mPendingBufferList.erase(k);
+    }
+
     // Go through the pending requests info and send error request to framework
-    for (i = mPendingRequestsList.begin(); i != mPendingRequestsList.end(); ) {
-        int numBuffers = 0;
+    for (size_t i = 0; i < flushMap.size(); i++) {
+        uint32_t frame_number = flushMap.keyAt(i);
+        const Vector<PendingBufferInfo> &pending = flushMap.valueAt(i);
         ALOGV("%s:Sending ERROR REQUEST for frame %d",
-              __func__, i->frame_number);
+              __func__, frame_number);
 
         // Send shutter notify to frameworks
         notify_msg.type = CAMERA3_MSG_ERROR;
         notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_REQUEST;
         notify_msg.message.error.error_stream = NULL;
-        notify_msg.message.error.frame_number = i->frame_number;
+        notify_msg.message.error.frame_number = frame_number;
         mCallbackOps->notify(mCallbackOps, &notify_msg);
 
-        memset(&result, 0, sizeof(camera3_capture_result_t));
-        result.frame_number = i->frame_number;
-        result.num_output_buffers = 0;
-        result.output_buffers = NULL;
-        numBuffers = 0;
-
-        for (List<PendingBufferInfo>::iterator k =
-             mPendingBuffersMap.mPendingBufferList.begin();
-             k != mPendingBuffersMap.mPendingBufferList.end(); ) {
-          if (k->frame_number == i->frame_number) {
-            ALOGV("%s: Sending Error for frame = %d, buffer = %p,"
-                   " stream = %p, stream format = %d",__func__,
-                   k->frame_number, k->buffer, k->stream, k->stream->format);
-
-            pStream_Buf.acquire_fence = -1;
-            pStream_Buf.release_fence = -1;
-            pStream_Buf.buffer = k->buffer;
-            pStream_Buf.status = CAMERA3_BUFFER_STATUS_ERROR;
-            pStream_Buf.stream = k->stream;
-
-            result.num_output_buffers = 1;
-            result.output_buffers = &pStream_Buf;
-            result.result = NULL;
-            result.frame_number = i->frame_number;
-
-            mCallbackOps->process_capture_result(mCallbackOps, &result);
-            mPendingBuffersMap.num_buffers--;
-            k = mPendingBuffersMap.mPendingBufferList.erase(k);
-            numBuffers++;
-          }
-          else {
-            k++;
-          }
+        pStream_Buf = new camera3_stream_buffer_t[pending.size()];
+        if (NULL == pStream_Buf) {
+            ALOGE("%s: No memory for pending buffers array", __func__);
+            pthread_mutex_unlock(&mMutex);
+            return NO_MEMORY;
         }
-        ALOGV("%s: mPendingBuffersMap.num_buffers = %d",
-              __func__, mPendingBuffersMap.num_buffers);
 
-        i = mPendingRequestsList.erase(i);
+        for (size_t j = 0; j < pending.size(); j++) {
+            const PendingBufferInfo &info = pending.itemAt(j);
+            pStream_Buf[j].acquire_fence = -1;
+            pStream_Buf[j].release_fence = -1;
+            pStream_Buf[j].buffer = info.buffer;
+            pStream_Buf[j].status = CAMERA3_BUFFER_STATUS_ERROR;
+            pStream_Buf[j].stream = info.stream;
+        }
+
+        result.num_output_buffers = pending.size();
+        result.output_buffers = pStream_Buf;
+        result.result = NULL;
+        result.frame_number = frame_number;
+        mCallbackOps->process_capture_result(mCallbackOps, &result);
+        delete [] pStream_Buf;
     }
 
     /* Reset pending buffer list and requests list */
@@ -2014,6 +2043,7 @@
     /* Reset pending frame Drop list and requests list */
     mPendingFrameDropList.clear();
 
+    flushMap.clear();
     mPendingBuffersMap.num_buffers = 0;
     mPendingBuffersMap.mPendingBufferList.clear();
     ALOGV("%s: Cleared all the pending buffers ", __func__);
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index fb7e5be..70244a7 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -264,6 +264,8 @@
         List<PendingBufferInfo> mPendingBufferList;
     } PendingBuffersMap;
 
+    typedef KeyedVector<uint32_t, Vector<PendingBufferInfo> > FlushMap;
+
     List<PendingRequestInfo> mPendingRequestsList;
     List<PendingFrameDropInfo> mPendingFrameDropList;
     PendingBuffersMap mPendingBuffersMap;