merge in lmp-release history after reset to ccb4ac330dc282bcbf8e670a550d1b90d718bc76
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.cpp b/camera/QCamera2/HAL3/QCamera3Channel.cpp
index 866ae7a..e5cc688 100644
--- a/camera/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/camera/QCamera2/HAL3/QCamera3Channel.cpp
@@ -991,15 +991,6 @@
 
     QCamera3PicChannel *obj = (QCamera3PicChannel *)userdata;
     if (obj) {
-
-        //Release any cached metabuffer information
-        if (obj->mMetaFrame != NULL && obj->m_pMetaChannel != NULL) {
-            ((QCamera3MetadataChannel*)(obj->m_pMetaChannel))->bufDone(obj->mMetaFrame);
-            obj->mMetaFrame = NULL;
-            obj->m_pMetaChannel = NULL;
-        } else {
-            ALOGE("%s: Meta frame was NULL", __func__);
-        }
         //Construct payload for process_capture_result. Call mChannelCb
 
         qcamera_hal3_jpeg_data_t *job = obj->m_postprocessor.findJpegJobByJobId(jobId);
@@ -1008,6 +999,7 @@
             ALOGE("%s: Error in jobId: (%d) with status: %d", __func__, jobId, status);
             resultStatus = CAMERA3_BUFFER_STATUS_ERROR;
         }
+
         bufIdx = job->jpeg_settings->out_buf_index;
         CDBG("%s: jpeg out_buf_index: %d", __func__, bufIdx);
 
@@ -1055,8 +1047,8 @@
             if ((NULL != job->fwk_frame) || (NULL != job->fwk_src_buffer)) {
                 obj->mOfflineMetaMemory.deallocate();
                 obj->mOfflineMemory.unregisterBuffers();
-                obj->m_postprocessor.releaseOfflineBuffers();
             }
+            obj->m_postprocessor.releaseOfflineBuffers();
             obj->m_postprocessor.releaseJpegJobData(job);
             free(job);
         }
@@ -1075,7 +1067,8 @@
                     void *userData,
                     camera3_stream_t *stream,
                     uint32_t postprocess_mask,
-                    bool is4KVideo) :
+                    bool is4KVideo,
+                    QCamera3Channel *metadataChannel) :
                         QCamera3Channel(cam_handle, cam_ops, cb_routine,
                         paddingInfo, postprocess_mask, userData),
                         m_postprocessor(this),
@@ -1083,7 +1076,9 @@
                         mNumBufs(0),
                         mCurrentBufIndex(-1),
                         mPostProcStarted(false),
+                        mInputBufferConfig(false),
                         mYuvMemory(NULL),
+                        m_pMetaChannel(metadataChannel),
                         mMetaFrame(NULL)
 {
     QCamera3HardwareInterface* hal_obj = (QCamera3HardwareInterface*)mUserData;
@@ -1107,6 +1102,13 @@
     if (rc != 0) {
         ALOGE("De-init Postprocessor failed");
     }
+
+   if (0 < mOfflineMetaMemory.getCnt()) {
+       mOfflineMetaMemory.deallocate();
+   }
+   if (0 < mOfflineMemory.getCnt()) {
+       mOfflineMemory.unregisterBuffers();
+   }
 }
 
 int32_t QCamera3PicChannel::initialize()
@@ -1213,9 +1215,14 @@
     mCurrentBufIndex = index;
 
     // Start postprocessor
-    if(!mPostProcStarted) {
+    // This component needs to be re-configured
+    // once we switch from input(framework) buffer
+    // reprocess to standard capture!
+    bool restartNeeded = ((!mInputBufferConfig) != (NULL != pInputBuffer));
+    if((!mPostProcStarted) || restartNeeded) {
         m_postprocessor.start(reproc_cfg, metadata);
         mPostProcStarted = true;
+        mInputBufferConfig = (NULL == pInputBuffer);
     }
 
     // Queue jpeg settings
@@ -1224,6 +1231,13 @@
     if (pInputBuffer == NULL)
         mStreams[0]->bufDone(index);
     else {
+        if (0 < mOfflineMetaMemory.getCnt()) {
+            mOfflineMetaMemory.deallocate();
+        }
+        if (0 < mOfflineMemory.getCnt()) {
+            mOfflineMemory.unregisterBuffers();
+        }
+
         int input_index = mOfflineMemory.getMatchBufIndex((void*)pInputBuffer->buffer);
         if(input_index < 0) {
             rc = mOfflineMemory.registerBuffer(pInputBuffer->buffer);
@@ -1289,6 +1303,32 @@
     return rc;
 }
 
+
+/*===========================================================================
+ * FUNCTION : metadataBufDone
+ *
+ * DESCRIPTION: Buffer done method for a metadata buffer
+ *
+ * PARAMETERS :
+ * @recvd_frame : received metadata frame
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3PicChannel::metadataBufDone(mm_camera_super_buf_t *recvd_frame)
+{
+    int32_t rc = NO_ERROR;;
+    if ((NULL == m_pMetaChannel) || (NULL == recvd_frame)) {
+        ALOGE("%s: Metadata channel or metadata buffer invalid", __func__);
+        return BAD_VALUE;
+    }
+
+    rc = ((QCamera3MetadataChannel*)m_pMetaChannel)->bufDone(recvd_frame);
+
+    return rc;
+}
+
 /*===========================================================================
  * FUNCTION   : dataNotifyCB
  *
@@ -1454,7 +1494,7 @@
     mYuvMemory = NULL;
 }
 
-int32_t QCamera3PicChannel::queueReprocMetadata(metadata_buffer_t *metadata)
+int32_t QCamera3PicChannel::queueReprocMetadata(mm_camera_super_buf_t *metadata)
 {
     return m_postprocessor.processPPMetadata(metadata);
 }
@@ -2318,67 +2358,6 @@
     return pStream;
 }
 
-int32_t QCamera3ReprocessChannel::doReprocessOffline(mm_camera_super_buf_t *frame,
-        metadata_buffer_t *metadata)
-{
-    int32_t rc = 0;
-    CDBG("%s: E", __func__);
-    if (m_numStreams < 1) {
-        ALOGE("%s: No reprocess stream is created", __func__);
-        return -1;
-    }
-    if (m_pSrcChannel == NULL) {
-        ALOGE("%s: No source channel for reprocess", __func__);
-        return -1;
-    }
-
-    uint32_t buf_idx = 0;
-    for (int i = 0; i < frame->num_bufs; i++) {
-        QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
-        QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
-        if (pStream != NULL && pSrcStream != NULL) {
-
-            rc = mStreams[i]->mapBuf(
-                    CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
-                    frame->bufs[i]->buf_idx, -1,
-                    frame->bufs[i]->fd, frame->bufs[i]->frame_len);
-
-            if (rc == NO_ERROR) {
-                cam_stream_parm_buffer_t param;
-                memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
-                param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
-                param.reprocess.buf_index = frame->bufs[i]->buf_idx;
-
-                param.reprocess.meta_present = 1;
-                char* private_data = (char *)POINTER_OF_PARAM(
-                        CAM_INTF_META_PRIVATE_DATA, metadata);
-                memcpy(param.reprocess.private_data, private_data,
-                        MAX_METADATA_PRIVATE_PAYLOAD_SIZE);
-
-                // Find crop info for reprocess stream
-                cam_crop_data_t *crop_data = (cam_crop_data_t *)
-                        POINTER_OF_PARAM(CAM_INTF_META_CROP_DATA, metadata);
-                for (int j = 0; j < crop_data->num_of_streams; j++) {
-                    if (crop_data->crop_info[j].stream_id ==
-                           pSrcStream->getMyServerID()) {
-                        param.reprocess.crop_rect  =
-                                crop_data->crop_info[j].crop;
-                        break;
-                    }
-                }
-                CDBG("%s: reprocess.buf_index: %u", __func__,
-                    (uint32_t)param.reprocess.buf_index);
-                rc = pStream->setParameter(param);
-                if (rc != NO_ERROR) {
-                    ALOGE("%s: stream setParameter for reprocess failed", __func__);
-                    break;
-                }
-            }
-        }
-    }
-    return rc;
-}
-
 /*===========================================================================
  * FUNCTION   : stop
  *
@@ -2434,6 +2413,116 @@
     return rc;
 }
 
+
+/*===========================================================================
+ * FUNCTION   : extractFrameAndCrop
+ *
+ * DESCRIPTION: Extract output crop and frame data if present
+ *
+ * PARAMETERS :
+ *   @frame     : input frame from source stream
+ *   meta_buffer: metadata buffer
+ *   @metadata  : corresponding metadata
+ *   @fwk_frame :
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3ReprocessChannel::extractFrameAndCrop(mm_camera_super_buf_t *frame,
+        mm_camera_buf_def_t *meta_buffer, metadata_buffer_t *metadata, qcamera_fwk_input_pp_data_t &fwk_frame)
+{
+    if ((NULL == meta_buffer) || (NULL == frame) || (NULL == metadata)) {
+        return BAD_VALUE;
+    }
+
+    for (int i = 0; i < frame->num_bufs; i++) {
+
+        QCamera3Stream *pStream = getStreamBySrcHandle(frame->bufs[i]->stream_id);
+        QCamera3Stream *pSrcStream = getSrcStreamBySrcHandle(frame->bufs[i]->stream_id);
+
+            if (pStream != NULL && pSrcStream != NULL) {
+                // Find crop info for reprocess stream
+                cam_crop_data_t *crop_data = (cam_crop_data_t *)
+                        POINTER_OF_PARAM(CAM_INTF_META_CROP_DATA, metadata);
+                if (NULL != crop_data) {
+                    for (int j = 0; j < crop_data->num_of_streams; j++) {
+                        if (crop_data->crop_info[j].stream_id ==
+                               pSrcStream->getMyServerID()) {
+                            fwk_frame.reproc_config.output_crop =
+                                    crop_data->crop_info[j].crop;
+                            CDBG("%s: Found reprocess crop %dx%d %dx%d", __func__,
+                                    crop_data->crop_info[0].crop.left,
+                                    crop_data->crop_info[0].crop.top,
+                                    crop_data->crop_info[0].crop.width,
+                                    crop_data->crop_info[0].crop.height);
+                            break;
+                        }
+                    }
+                    fwk_frame.input_buffer = *frame->bufs[i];
+                    fwk_frame.metadata_buffer = *meta_buffer;
+                    break;
+                } else {
+                    continue;
+                }
+            } else {
+                ALOGE("%s: Source/Re-process streams are invalid", __func__);
+                return BAD_VALUE;
+        }
+    }
+
+    return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION   : extractCrop
+ *
+ * DESCRIPTION: Extract framework output crop if present
+ *
+ * PARAMETERS :
+ *   @frame     : input frame for reprocessing
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3ReprocessChannel::extractCrop(qcamera_fwk_input_pp_data_t *frame)
+{
+    if (NULL == frame) {
+        ALOGE("%s: Incorrect input frame", __func__);
+        return BAD_VALUE;
+    }
+
+    if (NULL == frame->metadata_buffer.buffer) {
+        ALOGE("%s: No metadata available", __func__);
+        return BAD_VALUE;
+    }
+
+    // Find crop info for reprocess stream
+    metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
+    if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, meta)) {
+        cam_crop_data_t *crop_data = (cam_crop_data_t *)
+                POINTER_OF_PARAM(CAM_INTF_META_CROP_DATA, meta);
+        if (1 == crop_data->num_of_streams) {
+            frame->reproc_config.output_crop = crop_data->crop_info[0].crop;
+            CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__,
+                    crop_data->crop_info[0].crop.left,
+                    crop_data->crop_info[0].crop.top,
+                    crop_data->crop_info[0].crop.width,
+                    crop_data->crop_info[0].crop.height);
+        } else {
+            ALOGE("%s: Incorrect number of offline crop data entries %d",
+                    __func__,
+                    crop_data->num_of_streams);
+            return BAD_VALUE;
+        }
+    } else {
+        CDBG_HIGH("%s: Crop data not present", __func__);
+    }
+
+    return NO_ERROR;
+}
+
 /*===========================================================================
  * FUNCTION   : doReprocessOffline
  *
@@ -2509,28 +2598,9 @@
         param.reprocess.buf_index = buf_idx;
         param.reprocess.meta_present = 1;
         param.reprocess.meta_buf_index = meta_buf_idx;
-
-        // Find crop info for reprocess stream
-        metadata_buffer_t *meta = (metadata_buffer_t *) frame->metadata_buffer.buffer;
-        if (IS_META_AVAILABLE(CAM_INTF_META_CROP_DATA, meta)) {
-            cam_crop_data_t *crop_data = (cam_crop_data_t *)
-                    POINTER_OF_PARAM(CAM_INTF_META_CROP_DATA, meta);
-            if (1 == crop_data->num_of_streams) {
-                param.reprocess.crop_rect = crop_data->crop_info[0].crop;
-                CDBG("%s: Found offline reprocess crop %dx%d %dx%d", __func__,
-                        crop_data->crop_info[0].crop.left,
-                        crop_data->crop_info[0].crop.top,
-                        crop_data->crop_info[0].crop.width,
-                        crop_data->crop_info[0].crop.height);
-            } else {
-                ALOGE("%s: Incorrect number of offline crop data entries %d",
-                        __func__,
-                        crop_data->num_of_streams);
-            }
-        } else {
-            ALOGE("%s: Crop data not present", __func__);
-        }
-
+        param.reprocess.frame_pp_config.crop.input_crop =
+                        frame->reproc_config.output_crop;
+        param.reprocess.frame_pp_config.crop.crop_enabled = 1;
         rc = pStream->setParameter(param);
         if (rc != NO_ERROR) {
             ALOGE("%s: stream setParameter for reprocess failed", __func__);
diff --git a/camera/QCamera2/HAL3/QCamera3Channel.h b/camera/QCamera2/HAL3/QCamera3Channel.h
index 61247c4..2e25ced 100644
--- a/camera/QCamera2/HAL3/QCamera3Channel.h
+++ b/camera/QCamera2/HAL3/QCamera3Channel.h
@@ -229,7 +229,8 @@
             void *userData,
             camera3_stream_t *stream,
             uint32_t postprocess_mask,
-            bool is4KVideo);
+            bool is4KVideo,
+            QCamera3Channel *metadataChannel);
     ~QCamera3PicChannel();
 
     virtual int32_t initialize();
@@ -246,6 +247,7 @@
 
     bool isWNREnabled() {return m_bWNROn;};
     bool needOnlineRotation();
+    int32_t metadataBufDone(mm_camera_super_buf_t *recvd_frame);
     QCamera3Exif *getExifData(metadata_buffer_t *metadata,
             jpeg_settings_t *jpeg_settings);
     void overrideYuvSize(uint32_t width, uint32_t height);
@@ -257,7 +259,7 @@
     static void dataNotifyCB(mm_camera_super_buf_t *recvd_frame,
             void *userdata);
     virtual int32_t registerBuffer(buffer_handle_t *buffer);
-    int32_t queueReprocMetadata(metadata_buffer_t *metadata);
+    int32_t queueReprocMetadata(mm_camera_super_buf_t *metadata);
 
 private:
     int32_t queueJpegSetting(int32_t out_buf_index, metadata_buffer_t *metadata);
@@ -276,6 +278,8 @@
     cam_format_t mStreamFormat;
     bool m_bWNROn;
     bool mPostProcStarted;
+    bool mInputBufferConfig;   // Set when the picture channel is configured
+                               // for processing input(framework) buffers
 
     QCamera3GrallocMemory mMemory;
     QCamera3HeapMemory *mYuvMemory;
@@ -298,11 +302,14 @@
     QCamera3ReprocessChannel();
     virtual ~QCamera3ReprocessChannel();
     // offline reprocess
-    int32_t doReprocessOffline(mm_camera_super_buf_t *frame,
-                        metadata_buffer_t *metadata);
     int32_t doReprocessOffline(qcamera_fwk_input_pp_data_t *frame);
     int32_t doReprocess(int buf_fd, uint32_t buf_length, int32_t &ret_val,
                         mm_camera_super_buf_t *meta_buf);
+    int32_t extractFrameAndCrop(mm_camera_super_buf_t *frame,
+            mm_camera_buf_def_t *meta_buffer,
+            metadata_buffer_t *metadata,
+            qcamera_fwk_input_pp_data_t &fwk_frame);
+    int32_t extractCrop(qcamera_fwk_input_pp_data_t *frame);
     virtual QCamera3Memory *getStreamBufs(uint32_t len);
     virtual void putStreamBufs();
     virtual int32_t initialize();
diff --git a/camera/QCamera2/HAL3/QCamera3HALHeader.h b/camera/QCamera2/HAL3/QCamera3HALHeader.h
index 429efa4..1aef175 100644
--- a/camera/QCamera2/HAL3/QCamera3HALHeader.h
+++ b/camera/QCamera2/HAL3/QCamera3HALHeader.h
@@ -71,6 +71,7 @@
         cam_dimension_t output_stream_dim;
         cam_padding_info_t *padding;
         QCamera3Channel *src_channel;
+        cam_rect_t output_crop;
     } reprocess_config_t;
 };//namespace qcamera
 
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index bbd0de7..0b674dd 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -57,6 +57,7 @@
 #define DATA_PTR(MEM_OBJ,INDEX) MEM_OBJ->getPtr( INDEX )
 
 #define EMPTY_PIPELINE_DELAY 2
+#define PARTIAL_RESULT_COUNT 2
 
 #define VIDEO_4K_WIDTH  3840
 #define VIDEO_4K_HEIGHT 2160
@@ -334,6 +335,7 @@
 
     mPendingBuffersMap.mPendingBufferList.clear();
     mPendingRequestsList.clear();
+    mPendingReprocessResultList.clear();
 
     for (size_t i = 0; i < CAMERA3_TEMPLATE_COUNT; i++)
         if (mDefaultMetadata[i])
@@ -790,7 +792,7 @@
                             mCameraHandle->ops, captureResultCb,
                             &gCamCapability[mCameraId]->padding_info, this, newStream,
                             stream_config_info.postprocess_mask[i],
-                            m_bIs4KVideo);
+                            m_bIs4KVideo, mMetadataChannel);
                     if (mPictureChannel == NULL) {
                         ALOGE("%s: allocation of channel failed", __func__);
                         pthread_mutex_unlock(&mMutex);
@@ -857,6 +859,7 @@
     // Initialize/Reset the pending buffers list
     mPendingBuffersMap.num_buffers = 0;
     mPendingBuffersMap.mPendingBufferList.clear();
+    mPendingReprocessResultList.clear();
 
     mFirstRequest = true;
 
@@ -1076,6 +1079,58 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : handlePendingReprocResults
+ *
+ * DESCRIPTION: check and notify on any pending reprocess results
+ *
+ * PARAMETERS :
+ *   @frame_number   : Pending request frame number
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera3HardwareInterface::handlePendingReprocResults(uint32_t frame_number)
+{
+    for (List<PendingReprocessResult>::iterator j = mPendingReprocessResultList.begin();
+            j != mPendingReprocessResultList.end(); j++) {
+        if (j->frame_number == frame_number) {
+            mCallbackOps->notify(mCallbackOps, &j->notify_msg);
+
+            CDBG("%s: Delayed reprocess notify %d", __func__,
+                    frame_number);
+
+            for (List<PendingRequestInfo>::iterator k = mPendingRequestsList.begin();
+                k != mPendingRequestsList.end(); k++) {
+
+                if (k->frame_number == j->frame_number) {
+                    CDBG("%s: Found reprocess frame number %d in pending reprocess List "
+                            "Take it out!!", __func__,
+                            k->frame_number);
+
+                    camera3_capture_result result;
+                    memset(&result, 0, sizeof(camera3_capture_result));
+                    result.frame_number = frame_number;
+                    result.num_output_buffers = 1;
+                    result.output_buffers =  &j->buffer;
+                    result.input_buffer = k->input_buffer;
+                    result.result = k->settings;
+                    result.partial_result = PARTIAL_RESULT_COUNT;
+                    mCallbackOps->process_capture_result(mCallbackOps, &result);
+
+                    mPendingRequestsList.erase(k);
+                    mPendingRequest--;
+                    break;
+                }
+            }
+            mPendingReprocessResultList.erase(j);
+            break;
+        }
+    }
+    return NO_ERROR;
+}
+
+/*===========================================================================
  * FUNCTION   : handleMetadataWithLock
  *
  * DESCRIPTION: Handles metadata buffer callback with mMutex lock held.
@@ -1243,19 +1298,13 @@
                     }
                 }
 
-                //If it is a blob request then send the metadata to the picture channel
-                metadata_buffer_t *reproc_meta =
-                        (metadata_buffer_t *)malloc(sizeof(metadata_buffer_t));
-                if (reproc_meta == NULL) {
-                    ALOGE("%s: Failed to allocate memory for reproc data.", __func__);
-                    goto done_metadata;
-                }
-                *reproc_meta = *metadata;
-                mPictureChannel->queueReprocMetadata(reproc_meta);
+
+                mPictureChannel->queueReprocMetadata(metadata_buf);
+            } else {
+                // Return metadata buffer
+                mMetadataChannel->bufDone(metadata_buf);
+                free(metadata_buf);
             }
-            // Return metadata buffer
-            mMetadataChannel->bufDone(metadata_buf);
-            free(metadata_buf);
         }
         if (!result.result) {
             ALOGE("%s: metadata is NULL", __func__);
@@ -1325,6 +1374,10 @@
         }
         // erase the element from the list
         i = mPendingRequestsList.erase(i);
+
+        if (!mPendingReprocessResultList.empty()) {
+            handlePendingReprocResults(frame_number + 1);
+        }
     }
 
 done_metadata:
@@ -1426,7 +1479,6 @@
             notify_msg.type = CAMERA3_MSG_SHUTTER;
             notify_msg.message.shutter.frame_number = frame_number;
             notify_msg.message.shutter.timestamp = capture_time;
-            mCallbackOps->notify(mCallbackOps, &notify_msg);
 
             sp<Fence> releaseFence = new Fence(i->input_buffer->release_fence);
             int32_t rc = releaseFence->wait(Fence::TIMEOUT_NEVER);
@@ -1434,15 +1486,6 @@
                 ALOGE("%s: input buffer fence wait failed %d", __func__, rc);
             }
 
-            camera3_capture_result result;
-            memset(&result, 0, sizeof(camera3_capture_result));
-            result.frame_number = frame_number;
-            result.result = settings.release();
-            result.input_buffer = i->input_buffer;
-            result.num_output_buffers = 1;
-            result.output_buffers = buffer;
-            result.partial_result = 0;
-
             for (List<PendingBufferInfo>::iterator k =
                     mPendingBuffersMap.mPendingBufferList.begin();
                     k != mPendingBuffersMap.mPendingBufferList.end(); k++ ) {
@@ -1458,9 +1501,40 @@
             CDBG("%s: mPendingBuffersMap.num_buffers = %d",
                 __func__, mPendingBuffersMap.num_buffers);
 
-            mCallbackOps->process_capture_result(mCallbackOps, &result);
-            i = mPendingRequestsList.erase(i);
-            mPendingRequest--;
+            bool notifyNow = true;
+            for (List<PendingRequestInfo>::iterator j = mPendingRequestsList.begin();
+                    j != mPendingRequestsList.end(); j++) {
+                if (j->frame_number < frame_number) {
+                    notifyNow = false;
+                    break;
+                }
+            }
+
+            if (notifyNow) {
+                camera3_capture_result result;
+                memset(&result, 0, sizeof(camera3_capture_result));
+                result.frame_number = frame_number;
+                result.result = settings.release();
+                result.input_buffer = i->input_buffer;
+                result.num_output_buffers = 1;
+                result.output_buffers = buffer;
+                result.partial_result = PARTIAL_RESULT_COUNT;
+
+                mCallbackOps->notify(mCallbackOps, &notify_msg);
+                mCallbackOps->process_capture_result(mCallbackOps, &result);
+                CDBG("%s: Notify reprocess now %d!", __func__, frame_number);
+                i = mPendingRequestsList.erase(i);
+                mPendingRequest--;
+            } else {
+                // Cache reprocess result for later
+                PendingReprocessResult pendingResult;
+                memset(&pendingResult, 0, sizeof(PendingReprocessResult));
+                pendingResult.notify_msg = notify_msg;
+                pendingResult.buffer = *buffer;
+                pendingResult.frame_number = frame_number;
+                mPendingReprocessResultList.push_back(pendingResult);
+                CDBG("%s: Cache reprocess result %d!", __func__, frame_number);
+            }
         } else {
             for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
                 j != i->buffers.end(); j++) {
@@ -2027,6 +2101,7 @@
     flushMap.clear();
     mPendingBuffersMap.num_buffers = 0;
     mPendingBuffersMap.mPendingBufferList.clear();
+    mPendingReprocessResultList.clear();
     CDBG("%s: Cleared all the pending buffers ", __func__);
 
     mFlush = false;
@@ -2464,7 +2539,7 @@
         int32_t *privateData = (int32_t *)
                 POINTER_OF_META(CAM_INTF_META_PRIVATE_DATA, metadata);
         camMetadata.update(QCAMERA3_PRIVATEDATA_REPROCESS,
-            privateData, MAX_METADATA_PRIVATE_PAYLOAD_SIZE);
+                privateData, MAX_METADATA_PRIVATE_PAYLOAD_SIZE);
     }
     if (IS_META_AVAILABLE(CAM_INTF_META_NEUTRAL_COL_POINT, metadata)) {
         cam_neutral_col_point_t *neuColPoint = (cam_neutral_col_point_t*)
@@ -3793,7 +3868,7 @@
                       &max_pipeline_depth,
                       1);
 
-    int32_t partial_result_count = 2;
+    int32_t partial_result_count = PARTIAL_RESULT_COUNT;
     staticInfo.update(ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
                       &partial_result_count,
                        1);
@@ -4967,12 +5042,15 @@
         rc = AddSetParmEntryToBatch(hal_metadata, CAM_INTF_META_MODE,
                 sizeof(metaMode), &metaMode);
         if (metaMode == ANDROID_CONTROL_MODE_USE_SCENE_MODE) {
-           uint8_t fwk_sceneMode = frame_settings.find(ANDROID_CONTROL_SCENE_MODE).data.u8[0];
-           uint8_t sceneMode = lookupHalName(SCENE_MODES_MAP,
-                                             sizeof(SCENE_MODES_MAP)/sizeof(SCENE_MODES_MAP[0]),
-                                             fwk_sceneMode);
-           rc = AddSetParmEntryToBatch(hal_metadata, CAM_INTF_PARM_BESTSHOT_MODE,
-                sizeof(sceneMode), &sceneMode);
+           camera_metadata_entry entry = frame_settings.find(ANDROID_CONTROL_SCENE_MODE);
+           if (0 < entry.count) {
+               uint8_t fwk_sceneMode = entry.data.u8[0];
+               uint8_t sceneMode = lookupHalName(SCENE_MODES_MAP,
+                                                 sizeof(SCENE_MODES_MAP)/sizeof(SCENE_MODES_MAP[0]),
+                                                 fwk_sceneMode);
+               rc = AddSetParmEntryToBatch(hal_metadata, CAM_INTF_PARM_BESTSHOT_MODE,
+                    sizeof(sceneMode), &sceneMode);
+           }
         } else if (metaMode == ANDROID_CONTROL_MODE_OFF) {
            uint8_t sceneMode = CAM_SCENE_MODE_OFF;
            rc = AddSetParmEntryToBatch(hal_metadata, CAM_INTF_PARM_BESTSHOT_MODE,
@@ -5590,9 +5668,9 @@
     // Internal metadata
     if (frame_settings.exists(QCAMERA3_PRIVATEDATA_REPROCESS)) {
         int32_t* privatedata =
-            frame_settings.find(QCAMERA3_PRIVATEDATA_REPROCESS).data.i32;
+                frame_settings.find(QCAMERA3_PRIVATEDATA_REPROCESS).data.i32;
         rc = AddSetParmEntryToBatch(hal_metadata, CAM_INTF_META_PRIVATE_DATA,
-            sizeof(int32_t) * MAX_METADATA_PRIVATE_PAYLOAD_SIZE, privatedata);
+                sizeof(int32_t) * MAX_METADATA_PRIVATE_PAYLOAD_SIZE, privatedata);
     }
 
     // EV step
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index 269caa8..df65097 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -197,6 +197,7 @@
     int validateCaptureRequest(camera3_capture_request_t *request);
 
     void deriveMinFrameDuration();
+    int32_t handlePendingReprocResults(uint32_t frame_number);
     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,
@@ -286,8 +287,15 @@
         List<PendingBufferInfo> mPendingBufferList;
     } PendingBuffersMap;
 
+    typedef struct {
+        camera3_notify_msg_t notify_msg;
+        camera3_stream_buffer_t buffer;
+        uint32_t frame_number;
+    } PendingReprocessResult;
+
     typedef KeyedVector<uint32_t, Vector<PendingBufferInfo> > FlushMap;
 
+    List<PendingReprocessResult> mPendingReprocessResultList;
     List<PendingRequestInfo> mPendingRequestsList;
     List<PendingFrameDropInfo> mPendingFrameDropList;
     PendingBuffersMap mPendingBuffersMap;
diff --git a/camera/QCamera2/HAL3/QCamera3PostProc.cpp b/camera/QCamera2/HAL3/QCamera3PostProc.cpp
index f66aeb8..c91c612 100644
--- a/camera/QCamera2/HAL3/QCamera3PostProc.cpp
+++ b/camera/QCamera2/HAL3/QCamera3PostProc.cpp
@@ -64,7 +64,7 @@
       m_inputJpegQ(releaseJpegData, this),
       m_ongoingJpegQ(releaseJpegData, this),
       m_inputRawQ(releasePPInputData, this),
-      m_inputMetaQ(NULL, this),
+      m_inputMetaQ(releaseMetadata, this),
       m_jpegSettingsQ(NULL, this)
 {
     memset(&mJpegHandle, 0, sizeof(mJpegHandle));
@@ -532,7 +532,7 @@
  *              none-zero failure code
  *
  *==========================================================================*/
-int32_t QCamera3PostProcessor::processPPMetadata(metadata_buffer_t *reproc_meta)
+int32_t QCamera3PostProcessor::processPPMetadata(mm_camera_super_buf_t *reproc_meta)
 {
    pthread_mutex_lock(&mReprocJobLock);
     // enqueue to metadata input queue
@@ -636,6 +636,7 @@
                 (metadata_buffer_t *) job->fwk_src_frame->metadata_buffer.buffer;
         jpeg_job->fwk_src_buffer = job->fwk_src_frame;
     }
+    jpeg_job->src_metadata = job->src_metadata;
     jpeg_job->jpeg_settings = jpeg_settings;
 
     // free pp job buf
@@ -697,6 +698,25 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : releaseMetaData
+ *
+ * DESCRIPTION: callback function to release metadata camera buffer
+ *
+ * PARAMETERS :
+ *   @data      : ptr to post process input data
+ *   @user_data : user data ptr (QCamera3Reprocessor)
+ *
+ * RETURN     : None
+ *==========================================================================*/
+void QCamera3PostProcessor::releaseMetadata(void *data, void *user_data)
+{
+    QCamera3PostProcessor *pme = (QCamera3PostProcessor *)user_data;
+    if (NULL != pme) {
+        pme->m_parent->metadataBufDone((mm_camera_super_buf_t *)data);
+    }
+}
+
+/*===========================================================================
  * FUNCTION   : releaseJpegData
  *
  * DESCRIPTION: callback function to release jpeg job node
@@ -734,10 +754,18 @@
         if (NULL != pp_job->src_frame) {
             pme->releaseSuperBuf(pp_job->src_frame);
             free(pp_job->src_frame);
-            free(pp_job->metadata);
+            if (NULL != pp_job->src_metadata) {
+                pme->m_parent->metadataBufDone(pp_job->src_metadata);
+                free(pp_job->src_metadata);
+            }
             pp_job->src_frame = NULL;
             pp_job->metadata = NULL;
         }
+
+        if (NULL != pp_job->fwk_src_frame) {
+            free(pp_job->fwk_src_frame);
+            pp_job->fwk_src_frame = NULL;
+        }
     }
 }
 
@@ -819,9 +847,10 @@
         if (NULL != job->fwk_src_buffer) {
             free(job->fwk_src_buffer);
             job->fwk_src_buffer = NULL;
-        } else if (NULL != job->metadata) {
-            free(job->metadata);
-            job->metadata = NULL;
+        } else if (NULL != job->src_metadata) {
+            m_parent->metadataBufDone(job->src_metadata);
+            free(job->src_metadata);
+            job->src_metadata = NULL;
         }
 
         if (NULL != job->fwk_frame) {
@@ -1302,7 +1331,7 @@
     int ret;
     uint8_t is_active = FALSE;
     uint8_t needNewSess = TRUE;
-    metadata_buffer_t *meta_buffer = NULL;
+    mm_camera_super_buf_t *meta_buffer = NULL;
     CDBG("%s: E", __func__);
     QCamera3PostProcessor *pme = (QCamera3PostProcessor *)data;
     QCameraCmdThread *cmdThread = &pme->m_dataProcTh;
@@ -1415,6 +1444,10 @@
                             if (pp_job != NULL) {
                                 memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
                                 if (pme->m_pReprocChannel != NULL) {
+                                    if (NO_ERROR !=
+                                            pme->m_pReprocChannel->extractCrop(fwk_frame)) {
+                                        ALOGE("%s: Failed to extract output crop", __func__);
+                                    }
                                     // add into ongoing PP job Q
                                     pp_job->fwk_src_frame = fwk_frame;
                                     pme->m_ongoingPPQ.enqueue((void *)pp_job);
@@ -1451,21 +1484,31 @@
                         mm_camera_super_buf_t *pp_frame =
                             (mm_camera_super_buf_t *)pme->m_inputPPQ.dequeue();
                         meta_buffer =
-                            (metadata_buffer_t *)pme->m_inputMetaQ.dequeue();
+                            (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
                         pthread_mutex_unlock(&pme->mReprocJobLock);
                         qcamera_hal3_pp_data_t *pp_job =
                             (qcamera_hal3_pp_data_t *)malloc(sizeof(qcamera_hal3_pp_data_t));
                         if (pp_job != NULL) {
                             memset(pp_job, 0, sizeof(qcamera_hal3_pp_data_t));
                             pp_job->src_frame = pp_frame;
-                            pp_job->metadata = meta_buffer;
+                            pp_job->src_metadata = meta_buffer;
+                            pp_job->metadata =
+                                    (metadata_buffer_t *)meta_buffer->bufs[0]->buffer;
                             pme->m_ongoingPPQ.enqueue((void *)pp_job);
                             if (pme->m_pReprocChannel != NULL) {
-                                // add into ongoing PP job Q
-                                ret = pme->m_pReprocChannel->doReprocessOffline(pp_frame, meta_buffer);
-                                if (NO_ERROR != ret) {
-                                    // remove from ongoing PP job Q
-                                    pme->m_ongoingPPQ.dequeue(false);
+                                qcamera_fwk_input_pp_data_t fwk_frame;
+                                memset(&fwk_frame, 0, sizeof(qcamera_fwk_input_pp_data_t));
+                                ret = pme->m_pReprocChannel->extractFrameAndCrop(
+                                        pp_frame, meta_buffer->bufs[0],
+                                        pp_job->metadata, fwk_frame);
+                                if (NO_ERROR == ret) {
+                                    // add into ongoing PP job Q
+                                    ret = pme->m_pReprocChannel->doReprocessOffline(
+                                            &fwk_frame);
+                                    if (NO_ERROR != ret) {
+                                        // remove from ongoing PP job Q
+                                        pme->m_ongoingPPQ.dequeue(false);
+                                    }
                                 }
                             } else {
                                 CDBG_HIGH("%s: No reprocess. Calling processPPData directly",
@@ -1487,6 +1530,11 @@
                                 pme->releaseSuperBuf(pp_frame);
                                 free(pp_frame);
                             }
+                            //free metadata
+                            if (NULL != meta_buffer) {
+                                pme->m_parent->metadataBufDone(meta_buffer);
+                                free(meta_buffer);
+                            }
                         }
                     } else {
                         pthread_mutex_unlock(&pme->mReprocJobLock);
@@ -1509,9 +1557,11 @@
                         pme->releaseSuperBuf(super_buf);
                         free(super_buf);
                     }
-                    metadata_buffer_t *metadata = (metadata_buffer_t *)pme->m_inputMetaQ.dequeue();
-                    if (metadata != NULL)
+                    mm_camera_super_buf_t *metadata = (mm_camera_super_buf_t *)pme->m_inputMetaQ.dequeue();
+                    if (metadata != NULL) {
+                        pme->m_parent->metadataBufDone(metadata);
                         free(metadata);
+                    }
                     qcamera_fwk_input_pp_data_t *fwk_frame =
                             (qcamera_fwk_input_pp_data_t *) pme->m_inputFWKPPQ.dequeue();
                     if (NULL != fwk_frame) {
diff --git a/camera/QCamera2/HAL3/QCamera3PostProc.h b/camera/QCamera2/HAL3/QCamera3PostProc.h
index 69303b1..ac9cb35 100644
--- a/camera/QCamera2/HAL3/QCamera3PostProc.h
+++ b/camera/QCamera2/HAL3/QCamera3PostProc.h
@@ -65,6 +65,7 @@
     qcamera_fwk_input_pp_data_t *fwk_src_buffer; // original framework source frame for reproc
     QCamera3Exif *pJpegExifObj;
     metadata_buffer_t *metadata;
+    mm_camera_super_buf_t *src_metadata;
     jpeg_settings_t *jpeg_settings;
 } qcamera_hal3_jpeg_data_t;
 
@@ -73,6 +74,7 @@
     mm_camera_super_buf_t *src_frame;// source frame (need to be returned back to kernel after done)
     qcamera_fwk_input_pp_data_t *fwk_src_frame;// source frame
     metadata_buffer_t *metadata;
+    mm_camera_super_buf_t *src_metadata;
 } qcamera_hal3_pp_data_t;
 
 #define MAX_HAL3_EXIF_TABLE_ENTRIES 22
@@ -112,7 +114,7 @@
     int32_t processData(mm_camera_super_buf_t *frame);
     int32_t processRawData(mm_camera_super_buf_t *frame);
     int32_t processPPData(mm_camera_super_buf_t *frame);
-    int32_t processPPMetadata(metadata_buffer_t *reproc_meta);
+    int32_t processPPMetadata(mm_camera_super_buf_t *reproc_meta);
     int32_t processJpegSettingData(jpeg_settings_t *jpeg_settings);
     qcamera_hal3_jpeg_data_t *findJpegJobByJobId(uint32_t jobId);
     void releaseJpegJobData(qcamera_hal3_jpeg_data_t *job);
@@ -138,6 +140,7 @@
 
     static void releaseJpegData(void *data, void *user_data);
     static void releasePPInputData(void *data, void *user_data);
+    static void releaseMetadata(void *data, void *user_data);
     static void releaseOngoingPPData(void *data, void *user_data);
 
     static void *dataProcessRoutine(void *data);
diff --git a/camera/QCamera2/stack/common/cam_intf.h b/camera/QCamera2/stack/common/cam_intf.h
index ac9d9fc..70a9e55 100644
--- a/camera/QCamera2/stack/common/cam_intf.h
+++ b/camera/QCamera2/stack/common/cam_intf.h
@@ -207,8 +207,7 @@
     float filter_densities[CAM_FILTER_DENSITIES_MAX];
     uint8_t filter_densities_count;
 
-    cam_optical_stab_modes_t
-        optical_stab_modes[CAM_OPT_STAB_MAX];
+    uint8_t optical_stab_modes[CAM_OPT_STAB_MAX];
     uint8_t optical_stab_modes_count;
 
     cam_dimension_t lens_shading_map_size;
diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml
index cf44d59..58f911b 100644
--- a/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/overlay/frameworks/base/core/res/res/values/config.xml
@@ -266,4 +266,9 @@
     <integer name="config_multiuserMaximumUsers">4</integer>
     <!--  Whether Multiuser UI should be shown -->
     <bool name="config_enableMultiUserUI">true</bool>
+
+    <!-- Dream of notifications -->
+    <string name="config_dozeComponent">com.android.systemui/com.android.systemui.doze.DozeService</string>
+    <bool name="config_powerDecoupleAutoSuspendModeFromDisplay">true</bool>
+    <bool name="config_powerDecoupleInteractiveModeFromDisplay">true</bool>
 </resources>
diff --git a/overlay/frameworks/base/packages/SystemUI/res/values/config.xml b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
index e9748c9..d31a670 100644
--- a/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
+++ b/overlay/frameworks/base/packages/SystemUI/res/values/config.xml
@@ -30,5 +30,8 @@
 
     <!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
     <bool name="config_show4GForLTE">false</bool>
+
+    <!-- Doze: does this device support STATE_DOZE and STATE_DOZE_SUSPEND?  -->
+    <bool name="doze_display_state_supported">true</bool>
 </resources>