QCamera3: Try to recover from offline reprocess failures

Offline reprocessing failures should return appropriate status
to camera service otherwise the request will not complete and
camera will go in a bad state.

Bug: 37559776
Test: Complete Camera/Camera2 CTS
Change-Id: Ifbc59f05836a9cab2c80dd7865555478c96888f5
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.cpp b/camera/QCamera2/HAL3/QCamera3Channel.cpp
index 52acc1c..efbf107 100644
--- a/camera/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/camera/QCamera2/HAL3/QCamera3Channel.cpp
@@ -4242,6 +4242,14 @@
         ALOGE("%s: Input buffer memory map failed: %d", __func__, rc);
     }
 
+    if (rc != NO_ERROR) {
+        //Try to recover by returning input with error status
+        camera3_stream_buffer_t result;
+        memset(&result, 0, sizeof(result));
+        result.status = CAMERA3_BUFFER_STATUS_ERROR;
+        mChannelCB(NULL, &result, frame->frameNumber, true, mUserData);
+    }
+
     return rc;
 }
 
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index d32a7e1..f94d211 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -2877,12 +2877,15 @@
  *
  * DESCRIPTION: Handles input buffer and shutter callback with mMutex lock held.
  *
- * PARAMETERS : @frame_number: frame number of the input buffer
+ * PARAMETERS :
+ *  @buffer: contains status information about the processed buffer
+ *  @frame_number: frame number of the input buffer
  *
  * RETURN     :
  *
  *==========================================================================*/
-void QCamera3HardwareInterface::handleInputBufferWithLock(uint32_t frame_number)
+void QCamera3HardwareInterface::handleInputBufferWithLock(
+        camera3_stream_buffer_t *buffer, uint32_t frame_number)
 {
     ATRACE_CALL();
     pendingRequestIterator i = mPendingRequestsList.begin();
@@ -2925,14 +2928,55 @@
            }
         }
 
-        camera3_capture_result result;
-        memset(&result, 0, sizeof(camera3_capture_result));
-        result.frame_number = frame_number;
-        result.result = i->settings;
-        result.input_buffer = i->input_buffer;
-        result.partial_result = PARTIAL_RESULT_COUNT;
+        if ((nullptr != buffer) && (CAMERA3_BUFFER_STATUS_OK != buffer->status)) {
+            camera3_notify_msg_t notify_msg;
+            memset(&notify_msg, 0, sizeof(camera3_notify_msg_t));
+            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 = frame_number;
+            mCallbackOps->notify(mCallbackOps, &notify_msg);
 
-        mCallbackOps->process_capture_result(mCallbackOps, &result);
+            Vector<camera3_stream_buffer_t> pendingBuffers;
+            camera3_stream_buffer_t pending;
+            memset(&pending, 0, sizeof(pending));
+            pending.acquire_fence = -1;
+            pending.release_fence = -1;
+            pending.status = CAMERA3_BUFFER_STATUS_ERROR;
+            for (List<PendingBufferInfo>::iterator k =
+                    mPendingBuffersMap.mPendingBufferList.begin();
+                    k != mPendingBuffersMap.mPendingBufferList.end();) {
+                if (k->frame_number == frame_number) {
+                    pending.buffer = k->buffer;
+                    pending.stream = k->stream;
+                    pendingBuffers.add(pending);
+
+                    mPendingBuffersMap.num_buffers--;
+                    k = mPendingBuffersMap.mPendingBufferList.erase(k);
+                } else {
+                    k++;
+                }
+            }
+
+            camera3_capture_result result;
+            memset(&result, 0, sizeof(camera3_capture_result));
+            result.input_buffer = i->input_buffer;
+            result.num_output_buffers = pendingBuffers.size();
+            result.output_buffers = pendingBuffers.array();
+            result.result = NULL;
+            result.frame_number = frame_number;
+            mCallbackOps->process_capture_result(mCallbackOps, &result);
+        } else {
+            camera3_capture_result result;
+            memset(&result, 0, sizeof(camera3_capture_result));
+            result.frame_number = frame_number;
+            result.result = i->settings;
+            result.input_buffer = i->input_buffer;
+
+            result.partial_result = PARTIAL_RESULT_COUNT;
+
+            mCallbackOps->process_capture_result(mCallbackOps, &result);
+        }
         CDBG("%s: Input request metadata and input buffer frame_number = %u",
                        __func__, i->frame_number);
         i = erasePendingRequest(i);
@@ -4107,7 +4151,7 @@
         }
     } else if (isInputBuffer) {
         pthread_mutex_lock(&mMutex);
-        handleInputBufferWithLock(frame_number);
+        handleInputBufferWithLock(buffer, frame_number);
         pthread_mutex_unlock(&mMutex);
     } else {
         pthread_mutex_lock(&mMutex);
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index 68faca1..e22cb29 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -243,7 +243,8 @@
             bool free_and_bufdone_meta_buf);
     void handleBufferWithLock(camera3_stream_buffer_t *buffer,
             uint32_t frame_number);
-    void handleInputBufferWithLock(uint32_t frame_number);
+    void handleInputBufferWithLock(camera3_stream_buffer_t *buffer,
+            uint32_t frame_number);
     void unblockRequestIfNecessary();
     void dumpMetadataToFile(tuning_params_t &meta, uint32_t &dumpFrameCount,
             bool enabled, const char *type, uint32_t frameNumber);