Camera3: Implement flush call for version 3.1

When flush is called, HAL drops all inflight requests
and buffers as soon as possible.

HAL implements this feature by:
1. Streams off all active streams,
2. Calls process_capture_result with ERROR_BUFFER for
   pending requests for which metadata is generated, but
   not all buffers are filled, and
3. Calls process_capture_result with ERROR_RESULT for
   pending requests for which metadata is not generated
   yet.

This change also fixes a bug in mm-camera-interface so
that queued_buffer_count is reset during reg_buf.

Bug: 9758581
Change-Id: Ibcb5dc52faf8d50f781ef514e4c79185311dafce
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index da8282f..4f10698 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -224,7 +224,7 @@
         /*flush the metadata list*/
     if (!mStoredMetadataList.empty()) {
         for (List<MetadataBufferInfo>::iterator m = mStoredMetadataList.begin();
-              m != mStoredMetadataList.end(); m++) {
+              m != mStoredMetadataList.end(); ) {
             mMetadataChannel->bufDone(m->meta_buf);
             free(m->meta_buf);
             m = mStoredMetadataList.erase(m);
@@ -272,6 +272,9 @@
     if (mCameraOpened)
         closeCamera();
 
+    mPendingBuffersMap.mPendingBufferList.clear();
+    mPendingRequestsList.clear();
+
     for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++)
         if (mDefaultMetadata[i])
             free_camera_metadata(mDefaultMetadata[i]);
@@ -743,19 +746,14 @@
                         __func__, channel, (*it)->buffer_set.num_buffers);
             }
         }
-
-        ssize_t index = mPendingBuffersMap.indexOfKey((*it)->stream);
-        if (index == NAME_NOT_FOUND) {
-            mPendingBuffersMap.add((*it)->stream, 0);
-        } else {
-            mPendingBuffersMap.editValueAt(index) = 0;
-        }
     }
 
     /* Initialize mPendingRequestInfo and mPendnigBuffersMap */
     mPendingRequestsList.clear();
-
     mPendingFrameDropList.clear();
+    // Initialize/Reset the pending buffers list
+    mPendingBuffersMap.num_buffers = 0;
+    mPendingBuffersMap.mPendingBufferList.clear();
 
     /*flush the metadata list*/
     if (!mStoredMetadataList.empty()) {
@@ -1182,10 +1180,23 @@
                             break;
                         }
                     }
+
+                    for (List<PendingBufferInfo>::iterator k =
+                      mPendingBuffersMap.mPendingBufferList.begin();
+                      k != mPendingBuffersMap.mPendingBufferList.end(); k++) {
+                      if (k->buffer == j->buffer->buffer) {
+                        ALOGV("%s: Found buffer %p in pending buffer List "
+                              "for frame %d, Take it out!!", __func__,
+                               k->buffer, k->frame_number);
+                        mPendingBuffersMap.num_buffers--;
+                        k = mPendingBuffersMap.mPendingBufferList.erase(k);
+                        break;
+                      }
+                    }
+
                     result_buffers[result_buffers_idx++] = *(j->buffer);
                     free(j->buffer);
                     j->buffer = NULL;
-                    mPendingBuffersMap.editValueFor(j->stream)--;
                 }
             }
             result.output_buffers = result_buffers;
@@ -1259,8 +1270,23 @@
         }
         result.output_buffers = buffer;
         ALOGV("%s: result frame_number = %d, buffer = %p",
-                __func__, frame_number, buffer);
-        mPendingBuffersMap.editValueFor(buffer->stream)--;
+                __func__, frame_number, buffer->buffer);
+
+        for (List<PendingBufferInfo>::iterator k =
+                mPendingBuffersMap.mPendingBufferList.begin();
+                k != mPendingBuffersMap.mPendingBufferList.end(); k++ ) {
+            if (k->buffer == buffer->buffer) {
+                ALOGV("%s: Found Frame buffer, take it out from list",
+                        __func__);
+
+                mPendingBuffersMap.num_buffers--;
+                k = mPendingBuffersMap.mPendingBufferList.erase(k);
+                break;
+            }
+        }
+        ALOGV("%s: mPendingBuffersMap.num_buffers = %d",
+            __func__, mPendingBuffersMap.num_buffers);
+
         if (buffer->stream->stream_type == CAMERA3_STREAM_BIDIRECTIONAL) {
             int found = 0;
             for (List<MetadataBufferInfo>::iterator k = mStoredMetadataList.begin();
@@ -1311,14 +1337,27 @@
 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;
+
+    uint32_t queued_buffers = 0;
+    for(List<stream_info_t*>::iterator it=mStreamInfo.begin();
+        it != mStreamInfo.end(); it++) {
+        queued_buffers = 0;
+        for (List<PendingBufferInfo>::iterator k =
+            mPendingBuffersMap.mPendingBufferList.begin();
+            k != mPendingBuffersMap.mPendingBufferList.end(); k++ ) {
+            if (k->stream == (*it)->stream)
+                queued_buffers++;
+
+            ALOGV("%s: Dequeued %d buffers for stream %p", __func__,
+                queued_buffers, (*it)->stream);
+            if (queued_buffers >=(* it)->stream->max_buffers) {
+                ALOGV("%s: Wait!!! Max buffers Dequed", __func__);
+                max_buffers_dequeued = true;
+                break;
+            }
         }
     }
+
     if (!max_buffers_dequeued) {
         // Unblock process_capture_request
         pthread_cond_signal(&mRequestCond);
@@ -1528,8 +1567,19 @@
         requestedBuf.buffer = NULL;
         pendingRequest.buffers.push_back(requestedBuf);
 
-        mPendingBuffersMap.editValueFor(requestedBuf.stream)++;
+        // Add to buffer handle the pending buffers list
+        PendingBufferInfo bufferInfo;
+        bufferInfo.frame_number = frameNumber;
+        bufferInfo.buffer = request->output_buffers[i].buffer;
+        bufferInfo.stream = request->output_buffers[i].stream;
+        mPendingBuffersMap.mPendingBufferList.push_back(bufferInfo);
+        mPendingBuffersMap.num_buffers++;
+        ALOGV("%s: frame = %d, buffer = %p, stream = %p, stream format = %d",
+          __func__, frameNumber, bufferInfo.buffer, bufferInfo.stream,
+          bufferInfo.stream->format);
     }
+    ALOGV("%s: mPendingBuffersMap.num_buffers = %d",
+          __func__, mPendingBuffersMap.num_buffers);
     mPendingRequestsList.push_back(pendingRequest);
 
     // Notify metadata channel we receive a request
@@ -1693,12 +1743,157 @@
  *==========================================================================*/
 int QCamera3HardwareInterface::flush()
 {
-    /*Enable lock when we implement this function*/
-    /*
+
+    unsigned int frameNum = 0;
+    camera3_notify_msg_t notify_msg;
+    camera3_capture_result_t result;
+    camera3_stream_buffer_t pStream_Buf;
+
+    ALOGV("%s: Unblocking Process Capture Request", __func__);
+
+    // Stop the Streams/Channels
+    for (List<stream_info_t *>::iterator it = mStreamInfo.begin();
+        it != mStreamInfo.end(); it++) {
+        QCamera3Channel *channel = (QCamera3Channel *)(*it)->stream->priv;
+        channel->stop();
+        (*it)->status = INVALID;
+    }
+
+    if (mMetadataChannel) {
+        /* If content of mStreamInfo is not 0, there is metadata stream */
+        mMetadataChannel->stop();
+    }
+
+    // Mutex Lock
     pthread_mutex_lock(&mMutex);
 
+    // Unblock process_capture_request
+    mPendingRequest = 0;
+    pthread_cond_signal(&mRequestCond);
+
+    List<PendingRequestInfo>::iterator i = mPendingRequestsList.begin();
+    frameNum = i->frame_number;
+    ALOGV("%s: Latest frame num on  mPendingRequestsList = %d",
+      __func__, frameNum);
+
+    // Go through the pending buffers and send buffer errors
+    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);
+
+        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;
+
+            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);
+
+            mPendingBuffersMap.num_buffers--;
+            k = mPendingBuffersMap.mPendingBufferList.erase(k);
+        }
+        else {
+          k++;
+        }
+    }
+
+    ALOGV("%s:Sending ERROR REQUEST for all pending requests", __func__);
+
+    // Go through the pending requests info and send error request to framework
+    for (i = mPendingRequestsList.begin(); i != mPendingRequestsList.end(); ) {
+        int numBuffers = 0;
+        ALOGV("%s:Sending ERROR REQUEST for frame %d",
+              __func__, i->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;
+        mCallbackOps->notify(mCallbackOps, &notify_msg);
+
+        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++;
+          }
+        }
+        ALOGV("%s: mPendingBuffersMap.num_buffers = %d",
+              __func__, mPendingBuffersMap.num_buffers);
+
+        i = mPendingRequestsList.erase(i);
+    }
+
+    /* Reset pending buffer list and requests list */
+    mPendingRequestsList.clear();
+    /* Reset pending frame Drop list and requests list */
+    mPendingFrameDropList.clear();
+
+    mPendingBuffersMap.num_buffers = 0;
+    mPendingBuffersMap.mPendingBufferList.clear();
+    ALOGV("%s: Cleared all the pending buffers ", __func__);
+
+    /*flush the metadata list*/
+    if (!mStoredMetadataList.empty()) {
+        for (List<MetadataBufferInfo>::iterator m = mStoredMetadataList.begin();
+              m != mStoredMetadataList.end(); ) {
+            mMetadataChannel->bufDone(m->meta_buf);
+            free(m->meta_buf);
+            m = mStoredMetadataList.erase(m);
+        }
+    }
+    ALOGV("%s: Flushing the metadata list done!! ", __func__);
+
+    mFirstRequest = true;
     pthread_mutex_unlock(&mMutex);
-    */
     return 0;
 }
 
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index aa441fd..c4d7f52 100755
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
@@ -221,7 +221,6 @@
         uint32_t frame_number;
         uint32_t stream_ID;
     } PendingFrameDropInfo;
-    typedef KeyedVector<camera3_stream_t *, uint32_t> PendingBuffersMap;
     /*Data structure to store metadata information*/
     typedef struct {
        mm_camera_super_buf_t* meta_buf;
@@ -229,6 +228,22 @@
        uint32_t               frame_number;
     }MetadataBufferInfo;
 
+    // Store the Pending buffers for Flushing
+    typedef struct {
+        // Frame number pertaining to the buffer
+        uint32_t frame_number;
+        camera3_stream_t *stream;
+        // Buffer handle
+        buffer_handle_t *buffer;
+    } PendingBufferInfo;
+
+    typedef struct {
+        // Total number of buffer requests pending
+        uint32_t num_buffers;
+        // List of pending buffers
+        List<PendingBufferInfo> mPendingBufferList;
+    } PendingBuffersMap;
+
     List<MetadataBufferInfo> mStoredMetadataList;
     List<PendingRequestInfo> mPendingRequestsList;
     List<PendingFrameDropInfo> mPendingFrameDropList;
diff --git a/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
index 89e0c48..dd393bb 100644
--- a/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
+++ b/camera/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -1519,6 +1519,7 @@
     }
 
     pthread_mutex_lock(&my_obj->buf_lock);
+    my_obj->queued_buffer_count = 0;
     for(i = 0; i < my_obj->buf_num; i++){
         /* check if need to qbuf initially */
         if (my_obj->buf_status[i].initial_reg_flag) {