Merge "QCamera2: Adds ability to disable debug logs at build time"
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index 0f716c9..26eedd3 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -918,7 +918,8 @@
       m_bShutterSoundPlayed(false),
       m_bAutoFocusRunning(false),
       m_bStartZSLSnapshotCalled(false),
-      m_pPowerModule(NULL)
+      m_pPowerModule(NULL),
+      mDumpFrmCnt(0)
 {
     mCameraDevice.common.tag = HARDWARE_DEVICE_TAG;
     mCameraDevice.common.version = HARDWARE_DEVICE_API_VERSION(1, 0);
@@ -1142,6 +1143,7 @@
     }
     memcpy(gCamCapability[cameraId], DATA_PTR(capabilityHeap,0),
                                         sizeof(cam_capability_t));
+
     rc = NO_ERROR;
 
 query_failed:
@@ -1218,56 +1220,83 @@
 {
     int bufferCnt = 0;
     int minCaptureBuffers = mParameters.getNumOfSnapshots();
-    int zslBuffers = mParameters.getZSLQueueDepth();
-    if (CAMERA_MIN_JPEG_ENCODING_BUFFERS < minCaptureBuffers) {
-        zslBuffers += minCaptureBuffers;
-    } else {
-        zslBuffers += CAMERA_MIN_JPEG_ENCODING_BUFFERS;
-    }
-    zslBuffers += mParameters.getNumOfExtraHDRBufsIfNeeded();
 
-    // TODO: hardcode for now until mctl add support for min_num_pp_bufs
-    gCamCapability[mCameraId]->min_num_pp_bufs = 2;
+    int zslQBuffers = mParameters.getZSLQueueDepth() +
+                      mParameters.getMaxUnmatchedFramesInQueue();
+
+    int minCircularBufNum = CAMERA_MIN_STREAMING_BUFFERS +
+                            CAMERA_MIN_JPEG_ENCODING_BUFFERS +
+                            mParameters.getMaxUnmatchedFramesInQueue() +
+                            mParameters.getNumOfHDRBufsIfNeeded();
 
     // Get buffer count for the particular stream type
     switch (stream_type) {
     case CAM_STREAM_TYPE_PREVIEW:
-        bufferCnt = CAMERA_MIN_STREAMING_BUFFERS +
-                    gCamCapability[mCameraId]->min_num_pp_bufs;
-        if (mParameters.isZSLMode()) {
-            bufferCnt += zslBuffers;
+        {
+            if (mParameters.isZSLMode()) {
+                bufferCnt = zslQBuffers + minCircularBufNum;
+            } else {
+                bufferCnt = CAMERA_MIN_STREAMING_BUFFERS +
+                            mParameters.getMaxUnmatchedFramesInQueue();
+            }
         }
         break;
     case CAM_STREAM_TYPE_POSTVIEW:
-        bufferCnt = minCaptureBuffers +
-                    gCamCapability[mCameraId]->min_num_pp_bufs +
-                    mParameters.getNumOfExtraHDRBufsIfNeeded();
+        {
+            bufferCnt = minCaptureBuffers +
+                        mParameters.getMaxUnmatchedFramesInQueue() +
+                        mParameters.getNumOfExtraHDRBufsIfNeeded() +
+                        CAMERA_MIN_STREAMING_BUFFERS;
+        }
         break;
     case CAM_STREAM_TYPE_SNAPSHOT:
-        if (mParameters.isZSLMode()) {
-            bufferCnt = CAMERA_MIN_STREAMING_BUFFERS + zslBuffers;
-        } else {
-            bufferCnt = minCaptureBuffers +
-                        gCamCapability[mCameraId]->min_num_pp_bufs +
-                        mParameters.getNumOfExtraHDRBufsIfNeeded();
+        {
+            if (mParameters.isZSLMode()) {
+                bufferCnt = zslQBuffers + minCircularBufNum;
+            } else {
+                bufferCnt = minCaptureBuffers +
+                            mParameters.getMaxUnmatchedFramesInQueue() +
+                            mParameters.getNumOfExtraHDRBufsIfNeeded() +
+                            CAMERA_MIN_STREAMING_BUFFERS;
+            }
         }
         break;
     case CAM_STREAM_TYPE_RAW:
         if (mParameters.isZSLMode()) {
-            bufferCnt = CAMERA_MIN_STREAMING_BUFFERS + zslBuffers;
+            bufferCnt = zslQBuffers + CAMERA_MIN_STREAMING_BUFFERS;
         } else {
-            bufferCnt = minCaptureBuffers;
+            bufferCnt = minCaptureBuffers +
+                        mParameters.getMaxUnmatchedFramesInQueue() +
+                        mParameters.getNumOfExtraHDRBufsIfNeeded() +
+                        CAMERA_MIN_STREAMING_BUFFERS;
         }
         break;
     case CAM_STREAM_TYPE_VIDEO:
-        bufferCnt = CAMERA_MIN_VIDEO_BUFFERS +
-                    gCamCapability[mCameraId]->min_num_pp_bufs;
+        {
+            bufferCnt = CAMERA_MIN_VIDEO_BUFFERS +
+                        mParameters.getMaxUnmatchedFramesInQueue() +
+                        CAMERA_MIN_STREAMING_BUFFERS;
+        }
         break;
     case CAM_STREAM_TYPE_METADATA:
-        bufferCnt = CAMERA_MIN_STREAMING_BUFFERS + zslBuffers;
+        {
+            bufferCnt = minCaptureBuffers +
+                        mParameters.getMaxUnmatchedFramesInQueue() +
+                        mParameters.getNumOfExtraHDRBufsIfNeeded() +
+                        CAMERA_MIN_STREAMING_BUFFERS;
+            if (bufferCnt < zslQBuffers + minCircularBufNum) {
+                bufferCnt = zslQBuffers + minCircularBufNum;
+            }
+        }
         break;
     case CAM_STREAM_TYPE_OFFLINE_PROC:
-        bufferCnt = minCaptureBuffers;
+        {
+            bufferCnt = minCaptureBuffers +
+                        mParameters.getMaxUnmatchedFramesInQueue();
+            if (bufferCnt < CAMERA_MIN_STREAMING_BUFFERS) {
+                bufferCnt = CAMERA_MIN_STREAMING_BUFFERS;
+            }
+        }
         break;
     case CAM_STREAM_TYPE_DEFAULT:
     case CAM_STREAM_TYPE_MAX:
@@ -1507,6 +1536,26 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : msgTypeEnabledWithLock
+ *
+ * DESCRIPTION: impl to determine if certain msg_type is enabled with lock
+ *
+ * PARAMETERS :
+ *   @msg_type  : msg type mask
+ *
+ * RETURN     : 0 -- not enabled
+ *              none 0 -- enabled
+ *==========================================================================*/
+int QCamera2HardwareInterface::msgTypeEnabledWithLock(int32_t msg_type)
+{
+    int enabled = 0;
+    lockAPI();
+    enabled = mMsgEnabled & msg_type;
+    unlockAPI();
+    return enabled;
+}
+
+/*===========================================================================
  * FUNCTION   : startPreview
  *
  * DESCRIPTION: start preview impl
@@ -2062,6 +2111,7 @@
     rc = imgBuf->allocate(1, config->input_buf_planes.plane_info.frame_len);
     if (rc < 0) {
         ALOGE("%s: Unable to allocate heap memory for image buf", __func__);
+        delete imgBuf;
         return NO_MEMORY;
     }
 
@@ -2092,6 +2142,7 @@
         ALOGE("%s: Cannot start reprocess channel", __func__);
         imgBuf->deallocate();
         delete imgBuf;
+        delete pChannel;
         return rc;
     }
 
@@ -2812,6 +2863,7 @@
     attr.look_back = mParameters.getZSLBackLookCount();
     attr.post_frame_skip = mParameters.getZSLBurstInterval();
     attr.water_mark = mParameters.getZSLQueueDepth();
+    attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue();
     rc = pChannel->init(&attr,
                         zsl_channel_cb,
                         this);
@@ -2890,6 +2942,8 @@
     mm_camera_channel_attr_t attr;
     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
+    attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue();
+
     rc = pChannel->init(&attr,
                         capture_channel_cb_routine,
                         this);
@@ -3015,6 +3069,7 @@
     mm_camera_channel_attr_t attr;
     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
+    attr.max_unmatched_frames = mParameters.getMaxUnmatchedFramesInQueue();
     rc = pChannel->init(&attr,
                         postproc_channel_cb_routine,
                         this);
@@ -3312,7 +3367,7 @@
  *==========================================================================*/
 void QCamera2HardwareInterface::playShutter(){
      if (mNotifyCb == NULL ||
-         msgTypeEnabled(CAMERA_MSG_SHUTTER) == 0){
+         msgTypeEnabledWithLock(CAMERA_MSG_SHUTTER) == 0){
          ALOGV("%s: shutter msg not enabled or NULL cb", __func__);
          return;
      }
@@ -3373,7 +3428,7 @@
         return NO_ERROR;
     }
 
-    if ((NULL == mDataCb) || (msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) == 0)) {
+    if ((NULL == mDataCb) || (msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_METADATA) == 0)) {
         ALOGD("%s: prevew metadata msgtype not enabled, no ops here", __func__);
         return NO_ERROR;
     }
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index 97558fc..df6b653 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -230,6 +230,7 @@
     int enableMsgType(int32_t msg_type);
     int disableMsgType(int32_t msg_type);
     int msgTypeEnabled(int32_t msg_type);
+    int msgTypeEnabledWithLock(int32_t msg_type);
     int startPreview();
     int stopPreview();
     int storeMetaDataInBuffers(int enable);
@@ -412,6 +413,7 @@
 
     power_module_t *m_pPowerModule;   // power module
 
+    int mDumpFrmCnt; //frame dump count
 };
 
 }; // namespace qcamera
diff --git a/QCamera2/HAL/QCamera2HWICallbacks.cpp b/QCamera2/HAL/QCamera2HWICallbacks.cpp
index cf5d6fe..aba232a 100644
--- a/QCamera2/HAL/QCamera2HWICallbacks.cpp
+++ b/QCamera2/HAL/QCamera2HWICallbacks.cpp
@@ -282,7 +282,7 @@
     int idx = frame->buf_idx;
     memory->cleanCache(idx);
     pme->dumpFrameToFile(frame->buffer, frame->frame_len,
-                         frame->buf_idx, QCAMERA_DUMP_FRM_PREVIEW);
+                         frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW);
 
     // Display the buffer.
     int dequeuedIdx = memory->displayBuffer(idx);
@@ -298,7 +298,7 @@
     }
 
     // Handle preview data callback
-    if (pme->mDataCb != NULL && pme->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME) > 0) {
+    if (pme->mDataCb != NULL && pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0) {
         camera_memory_t *previewMem = NULL;
         camera_memory_t *data = NULL;
         int previewBufSize;
@@ -401,17 +401,19 @@
     }
 
     QCameraMemory *previewMemObj = (QCameraMemory *)frame->mem_info;
-    camera_memory_t *preview_mem =
-        previewMemObj->getMemory(frame->buf_idx, false);
+    camera_memory_t *preview_mem = NULL;
+    if (previewMemObj != NULL) {
+        preview_mem = previewMemObj->getMemory(frame->buf_idx, false);
+    }
     if (NULL != previewMemObj && NULL != preview_mem) {
         previewMemObj->cleanCache(frame->buf_idx);
 
         pme->dumpFrameToFile(frame->buffer, frame->frame_len,
-                             frame->buf_idx, QCAMERA_DUMP_FRM_PREVIEW);
+                             frame->frame_idx, QCAMERA_DUMP_FRM_PREVIEW);
 
         if (pme->needProcessPreviewFrame() &&
             pme->mDataCb != NULL &&
-            pme->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME) > 0 ) {
+            pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0 ) {
             qcamera_callback_argm_t cbArg;
             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
             cbArg.cb_type = QCAMERA_DATA_CALLBACK;
@@ -477,7 +479,7 @@
         memObj->cleanCache(frame->buf_idx);
 
         pme->dumpFrameToFile(frame->buffer, frame->frame_len,
-                             frame->buf_idx, QCAMERA_DUMP_FRM_THUMBNAIL);
+                             frame->frame_idx, QCAMERA_DUMP_FRM_THUMBNAIL);
     }
 
     // Display the buffer.
@@ -547,14 +549,16 @@
     nsecs_t timeStamp = nsecs_t(frame->ts.tv_sec) * 1000000000LL + frame->ts.tv_nsec;
     ALOGE("Send Video frame to services/encoder TimeStamp : %lld", timeStamp);
     QCameraMemory *videoMemObj = (QCameraMemory *)frame->mem_info;
-    camera_memory_t *video_mem =
-        videoMemObj->getMemory(frame->buf_idx, (pme->mStoreMetaDataInFrame > 0)? true : false);
+    camera_memory_t *video_mem = NULL;
+    if (NULL != videoMemObj) {
+        video_mem = videoMemObj->getMemory(frame->buf_idx, (pme->mStoreMetaDataInFrame > 0)? true : false);
+    }
     if (NULL != videoMemObj && NULL != video_mem) {
         videoMemObj->cleanCache(frame->buf_idx);
         pme->dumpFrameToFile(frame->buffer, frame->frame_len,
-                             frame->buf_idx, QCAMERA_DUMP_FRM_VIDEO);
+                             frame->frame_idx, QCAMERA_DUMP_FRM_VIDEO);
         if ((pme->mDataCbTimestamp != NULL) &&
-            pme->msgTypeEnabled(CAMERA_MSG_VIDEO_FRAME) > 0) {
+            pme->msgTypeEnabledWithLock(CAMERA_MSG_VIDEO_FRAME) > 0) {
             qcamera_callback_argm_t cbArg;
             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
             cbArg.cb_type = QCAMERA_DATA_TIMESTAMP_CALLBACK;
@@ -807,30 +811,43 @@
                                                 int index,
                                                 int dump_type)
 {
+
     if ((mParameters.getEnabledFileDumpMask() & dump_type) == 0) {
         ALOGV("dumping frame to file not enabled");
         return;
     }
 
+    if(mDumpFrmCnt < 0 || mDumpFrmCnt > 255){
+        mDumpFrmCnt = 0;
+    }
+
     char buf[32];
+    cam_dimension_t dim;
+    memset(&dim, 0, sizeof(dim));
     switch (dump_type) {
     case QCAMERA_DUMP_FRM_PREVIEW:
-        snprintf(buf, sizeof(buf), "/data/%s_%d.%s", "preview", index, "yuv");
+        mParameters.getStreamDimension(CAM_STREAM_TYPE_PREVIEW, dim);
+        snprintf(buf, sizeof(buf), "/data/%dp_%dx%d_%d.yuv", mDumpFrmCnt, dim.width, dim.height, index);
         break;
     case QCAMERA_DUMP_FRM_THUMBNAIL:
-        snprintf(buf, sizeof(buf), "/data/%s_%d.%s", "thumbnail", index, "yuv");
+        mParameters.getStreamDimension(CAM_STREAM_TYPE_POSTVIEW, dim);
+        snprintf(buf, sizeof(buf), "/data/%dt_%dx%d_%d.yuv", mDumpFrmCnt, dim.width, dim.height, index);
         break;
     case QCAMERA_DUMP_FRM_SNAPSHOT:
-        snprintf(buf, sizeof(buf), "/data/%s_%d.%s", "main", index, "yuv");
+        mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim);
+        snprintf(buf, sizeof(buf), "/data/%ds_%dx%d_%d.yuv", mDumpFrmCnt, dim.width, dim.height, index);
         break;
     case QCAMERA_DUMP_FRM_VIDEO:
-        snprintf(buf, sizeof(buf), "/data/%s_%d.%s", "video", index, "yuv");
+        mParameters.getStreamDimension(CAM_STREAM_TYPE_VIDEO, dim);
+        snprintf(buf, sizeof(buf), "/data/%dv_%dx%d_%d.yuv", mDumpFrmCnt, dim.width, dim.height, index);
         break;
     case QCAMERA_DUMP_FRM_RAW:
-        snprintf(buf, sizeof(buf), "/data/%s_%d.%s", "raw", index, "raw");
+        mParameters.getStreamDimension(CAM_STREAM_TYPE_RAW, dim);
+        snprintf(buf, sizeof(buf), "/data/%dr_%dx%d_%d.yuv", mDumpFrmCnt, dim.width, dim.height, index);
         break;
     case QCAMERA_DUMP_FRM_JPEG:
-        snprintf(buf, sizeof(buf), "/data/%s_%d.%s", "jpeg", index, "jpg");
+        mParameters.getStreamDimension(CAM_STREAM_TYPE_SNAPSHOT, dim);
+        snprintf(buf, sizeof(buf), "/data/%dj_%dx%d_%d.yuv", mDumpFrmCnt, dim.width, dim.height, index);
         break;
     default:
         ALOGE("%s: Not supported for dumping stream type %d", __func__, dump_type);
@@ -842,6 +859,7 @@
     int written_len = write(file_fd, data, size);
     ALOGD("%s: written number of bytes %d\n", __func__, written_len);
     close(file_fd);
+    mDumpFrmCnt++;
 }
 
 /*===========================================================================
@@ -1020,7 +1038,8 @@
                     ALOGV("%s: cb type %d received",
                           __func__,
                           cb->cb_type);
-                    if (pme->mParent->msgTypeEnabled(cb->msg_type)) {
+
+                    if (pme->mParent->msgTypeEnabledWithLock(cb->msg_type)) {
                         switch (cb->cb_type) {
                         case QCAMERA_NOTIFY_CALLBACK:
                             {
diff --git a/QCamera2/HAL/QCameraMem.cpp b/QCamera2/HAL/QCameraMem.cpp
index cd059ea..03da59f 100644
--- a/QCamera2/HAL/QCameraMem.cpp
+++ b/QCamera2/HAL/QCameraMem.cpp
@@ -428,7 +428,7 @@
  *==========================================================================*/
 int QCameraHeapMemory::allocate(int count, int size)
 {
-    int heap_mask = (0x1 << ION_CP_MM_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+    int heap_mask = 0x1 << ION_IOMMU_HEAP_ID;
     int rc = alloc(count, size, heap_mask);
     if (rc < 0)
         return rc;
@@ -601,7 +601,7 @@
  *==========================================================================*/
 int QCameraStreamMemory::allocate(int count, int size)
 {
-    int heap_mask = (0x1 << ION_CP_MM_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+    int heap_mask = 0x1 << ION_IOMMU_HEAP_ID;
     int rc = alloc(count, size, heap_mask);
     if (rc < 0)
         return rc;
@@ -1010,8 +1010,9 @@
 {
     int err = 0;
     status_t ret = NO_ERROR;
-    int gralloc_usage;
+    int gralloc_usage = 0;
     struct ion_fd_data ion_info_fd;
+    memset(&ion_info_fd, 0, sizeof(ion_info_fd));
 
     ALOGI(" %s : E ", __FUNCTION__);
 
@@ -1046,7 +1047,7 @@
          goto end;
     }
 
-    gralloc_usage = GRALLOC_USAGE_PRIVATE_MM_HEAP | GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+    gralloc_usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
     err = mWindow->set_usage(mWindow, gralloc_usage);
     if(err != 0) {
         /* set_usage error out */
@@ -1090,14 +1091,51 @@
         mPrivateHandle[cnt] =
             (struct private_handle_t *)(*mBufferHandle[cnt]);
         mMemInfo[cnt].main_ion_fd = open("/dev/ion", O_RDONLY);
-        if (mMemInfo[cnt].main_ion_fd < 0) {
+        if (mMemInfo[cnt].main_ion_fd <= 0) {
             ALOGE("%s: failed: could not open ion device", __func__);
+            for(int i = 0; i < cnt; i++) {
+                struct ion_handle_data ion_handle;
+                memset(&ion_handle, 0, sizeof(ion_handle));
+                ion_handle.handle = mMemInfo[i].handle;
+                if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
+                    ALOGE("%s: ion free failed", __func__);
+                }
+                close(mMemInfo[i].main_ion_fd);
+                if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
+                    err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
+                    ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
+                }
+                mLocalFlag[i] = BUFFER_NOT_OWNED;
+                mBufferHandle[i] = NULL;
+            }
+            memset(&mMemInfo, 0, sizeof(mMemInfo));
+            ret = UNKNOWN_ERROR;
+            goto end;
         } else {
-            memset(&ion_info_fd, 0, sizeof(ion_info_fd));
             ion_info_fd.fd = mPrivateHandle[cnt]->fd;
             if (ioctl(mMemInfo[cnt].main_ion_fd,
                       ION_IOC_IMPORT, &ion_info_fd) < 0) {
                 ALOGE("%s: ION import failed\n", __func__);
+                for(int i = 0; i < cnt; i++) {
+                    struct ion_handle_data ion_handle;
+                    memset(&ion_handle, 0, sizeof(ion_handle));
+                    ion_handle.handle = mMemInfo[i].handle;
+                    if (ioctl(mMemInfo[i].main_ion_fd, ION_IOC_FREE, &ion_handle) < 0) {
+                        ALOGE("ion free failed");
+                    }
+                    close(mMemInfo[i].main_ion_fd);
+
+                    if(mLocalFlag[i] != BUFFER_NOT_OWNED) {
+                        err = mWindow->cancel_buffer(mWindow, mBufferHandle[i]);
+                        ALOGD("%s: cancel_buffer: hdl =%p", __func__, (*mBufferHandle[i]));
+                    }
+                    mLocalFlag[i] = BUFFER_NOT_OWNED;
+                    mBufferHandle[i] = NULL;
+                }
+                close(mMemInfo[cnt].main_ion_fd);
+                memset(&mMemInfo, 0, sizeof(mMemInfo));
+                ret = UNKNOWN_ERROR;
+                goto end;
             }
         }
         mCameraMemory[cnt] =
diff --git a/QCamera2/HAL/QCameraParameters.cpp b/QCamera2/HAL/QCameraParameters.cpp
index 03c6d54..1dbab44 100644
--- a/QCamera2/HAL/QCameraParameters.cpp
+++ b/QCamera2/HAL/QCameraParameters.cpp
@@ -37,7 +37,6 @@
 #include <gralloc_priv.h>
 #include "QCamera2HWI.h"
 #include "QCameraParameters.h"
-#include "mm_camera_interface.h"
 
 #define ASPECT_TOLERANCE 0.001
 #define FLIP_V_H (FLIP_H | FLIP_V)
@@ -2757,7 +2756,8 @@
     setFloat(KEY_VERTICAL_VIEW_ANGLE, m_pCapability->ver_view_angle);
 
     // Set supported preview sizes
-    if (m_pCapability->preview_sizes_tbl_cnt > 0) {
+    if (m_pCapability->preview_sizes_tbl_cnt > 0 &&
+        m_pCapability->preview_sizes_tbl_cnt <= MAX_SIZES_CNT) {
         String8 previewSizeValues = createSizesString(
                 m_pCapability->preview_sizes_tbl, m_pCapability->preview_sizes_tbl_cnt);
         set(KEY_SUPPORTED_PREVIEW_SIZES, previewSizeValues.string());
@@ -2766,11 +2766,12 @@
         CameraParameters::setPreviewSize(m_pCapability->preview_sizes_tbl[0].width,
                                          m_pCapability->preview_sizes_tbl[0].height);
     } else {
-        ALOGE("%s: supported preview sizes cnt is 0!!!", __func__);
+        ALOGE("%s: supported preview sizes cnt is 0 or exceeds max!!!", __func__);
     }
 
     // Set supported video sizes
-    if (m_pCapability->video_sizes_tbl_cnt > 0) {
+    if (m_pCapability->video_sizes_tbl_cnt > 0 &&
+        m_pCapability->video_sizes_tbl_cnt <= MAX_SIZES_CNT) {
         String8 videoSizeValues = createSizesString(
                 m_pCapability->video_sizes_tbl, m_pCapability->video_sizes_tbl_cnt);
         set(KEY_SUPPORTED_VIDEO_SIZES, videoSizeValues.string());
@@ -2783,11 +2784,12 @@
         String8 vSize = createSizesString(&m_pCapability->video_sizes_tbl[0], 1);
         set(KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO, vSize.string());
     } else {
-        ALOGE("%s: supported video sizes cnt is 0!!!", __func__);
+        ALOGE("%s: supported video sizes cnt is 0 or exceeds max!!!", __func__);
     }
 
     // Set supported picture sizes
-    if (m_pCapability->picture_sizes_tbl_cnt) {
+    if (m_pCapability->picture_sizes_tbl_cnt > 0 &&
+        m_pCapability->picture_sizes_tbl_cnt <= MAX_SIZES_CNT) {
         String8 pictureSizeValues = createSizesString(
                 m_pCapability->picture_sizes_tbl, m_pCapability->picture_sizes_tbl_cnt);
         set(KEY_SUPPORTED_PICTURE_SIZES, pictureSizeValues.string());
@@ -2797,7 +2799,7 @@
            m_pCapability->picture_sizes_tbl[m_pCapability->picture_sizes_tbl_cnt-1].width,
            m_pCapability->picture_sizes_tbl[m_pCapability->picture_sizes_tbl_cnt-1].height);
     } else {
-        ALOGE("%s: supported picture sizes cnt is 0!!!", __func__);
+        ALOGE("%s: supported picture sizes cnt is 0 or exceeds max!!!", __func__);
     }
 
     // Set supported thumbnail sizes
@@ -2810,7 +2812,8 @@
     set(KEY_JPEG_THUMBNAIL_HEIGHT, THUMBNAIL_SIZES_MAP[0].height);
 
     // Set supported livesnapshot sizes
-    if (m_pCapability->livesnapshot_sizes_tbl_cnt) {
+    if (m_pCapability->livesnapshot_sizes_tbl_cnt > 0 &&
+        m_pCapability->livesnapshot_sizes_tbl_cnt <= MAX_SIZES_CNT) {
         String8 liveSnpashotSizeValues = createSizesString(
                 m_pCapability->livesnapshot_sizes_tbl,
                 m_pCapability->livesnapshot_sizes_tbl_cnt);
@@ -2859,7 +2862,8 @@
     set(KEY_JPEG_THUMBNAIL_QUALITY, 85);
 
     // Set FPS ranges
-    if (m_pCapability->fps_ranges_tbl_cnt > 0) {
+    if (m_pCapability->fps_ranges_tbl_cnt > 0 &&
+        m_pCapability->fps_ranges_tbl_cnt <= MAX_SIZES_CNT) {
         int default_fps_index = 0;
         String8 fpsRangeValues = createFpsRangeString(m_pCapability->fps_ranges_tbl,
                                                       m_pCapability->fps_ranges_tbl_cnt,
@@ -2878,7 +2882,7 @@
         set(KEY_SUPPORTED_PREVIEW_FRAME_RATES, fpsValues.string());
         CameraParameters::setPreviewFrameRate(max_fps);
     } else {
-        ALOGE("%s: supported fps ranges cnt is 0!!!", __func__);
+        ALOGE("%s: supported fps ranges cnt is 0 or exceeds max!!!", __func__);
     }
 
     // Set supported focus modes
@@ -3139,6 +3143,9 @@
     // Set default Camera mode
     set(KEY_QC_CAMERA_MODE, 0);
 
+    // TODO: hardcode for now until mctl add support for min_num_pp_bufs
+    m_pCapability->min_num_pp_bufs = 3;
+
     int32_t rc = commitParameters();
     if (rc == NO_ERROR) {
         rc = setNumOfSnapshot();
@@ -4105,20 +4112,25 @@
         return NO_ERROR;
     }
 
-    cam_rect_t *areas = new cam_rect_t[m_pCapability->max_num_focus_areas];
+    cam_rect_t *areas = (cam_rect_t *)malloc(sizeof(cam_rect_t) * m_pCapability->max_num_focus_areas);
+    if (NULL == areas) {
+        ALOGE("%s: No memory for areas", __func__);
+        return NO_MEMORY;
+    }
+    memset(areas, 0, sizeof(cam_rect_t) * m_pCapability->max_num_focus_areas);
     int num_areas_found = 0;
     if (parseCameraAreaString(focusAreasStr,
                               m_pCapability->max_num_focus_areas,
                               areas,
                               num_areas_found) != NO_ERROR) {
         ALOGE("%s: Failed to parse the string: %s", __func__, focusAreasStr);
-        delete areas;
+        free(areas);
         return BAD_VALUE;
     }
 
     if (validateCameraAreas(areas, num_areas_found) == false) {
         ALOGE("%s: invalid areas specified : %s", __func__, focusAreasStr);
-        delete areas;
+        free(areas);
         return BAD_VALUE;
     }
 
@@ -4140,7 +4152,7 @@
         af_roi_value.roi[i].width = (int32_t)(areas[i].width * previewWidth / 2000.0f);
         af_roi_value.roi[i].height = (int32_t)(areas[i].height * previewHeight / 2000.0f);
     }
-    delete areas;
+    free(areas);
     return AddSetParmEntryToBatch(m_pParamBuf,
                                   CAM_INTF_PARM_AF_ROI,
                                   sizeof(af_roi_value),
@@ -4295,38 +4307,41 @@
  *==========================================================================*/
 int32_t QCameraParameters::setAEBracket(const char *aecBracketStr)
 {
+    if (aecBracketStr == NULL) {
+        ALOGI("%s: setAEBracket with NULL value", __func__);
+        return NO_ERROR;
+    }
+
     cam_exp_bracketing_t expBracket;
     memset(&expBracket, 0, sizeof(expBracket));
 
-    if (aecBracketStr != NULL) {
-        int value = lookupAttr(BRACKETING_MODES_MAP,
-                               sizeof(BRACKETING_MODES_MAP)/sizeof(QCameraMap),
-                               aecBracketStr);
-        switch (value) {
-        case CAM_EXP_BRACKETING_ON:
-            {
-                ALOGV("%s, EXP_BRACKETING_ON", __func__);
-                const char *str_val = get(KEY_QC_CAPTURE_BURST_EXPOSURE);
-                if ((str_val != NULL) && (strlen(str_val)>0)) {
-                    expBracket.mode = CAM_EXP_BRACKETING_ON;
-                    strlcpy(expBracket.values, str_val, MAX_EXP_BRACKETING_LENGTH);
-                    ALOGI("%s: setting Exposure Bracketing value of %s",
-                          __func__, expBracket.values);
-                }
-                else {
-                    /* Apps not set capture-burst-exposures, error case fall into bracketing off mode */
-                    ALOGI("%s: capture-burst-exposures not set, back to HDR OFF mode", __func__);
-                    expBracket.mode = CAM_EXP_BRACKETING_OFF;
-                }
+    int value = lookupAttr(BRACKETING_MODES_MAP,
+                           sizeof(BRACKETING_MODES_MAP)/sizeof(QCameraMap),
+                           aecBracketStr);
+    switch (value) {
+    case CAM_EXP_BRACKETING_ON:
+        {
+            ALOGV("%s, EXP_BRACKETING_ON", __func__);
+            const char *str_val = get(KEY_QC_CAPTURE_BURST_EXPOSURE);
+            if ((str_val != NULL) && (strlen(str_val)>0)) {
+                expBracket.mode = CAM_EXP_BRACKETING_ON;
+                strlcpy(expBracket.values, str_val, MAX_EXP_BRACKETING_LENGTH);
+                ALOGI("%s: setting Exposure Bracketing value of %s",
+                      __func__, expBracket.values);
             }
-            break;
-        default:
-            {
-                ALOGD("%s, EXP_BRACKETING_OFF", __func__);
+            else {
+                /* Apps not set capture-burst-exposures, error case fall into bracketing off mode */
+                ALOGI("%s: capture-burst-exposures not set, back to HDR OFF mode", __func__);
                 expBracket.mode = CAM_EXP_BRACKETING_OFF;
             }
-            break;
         }
+        break;
+    default:
+        {
+            ALOGD("%s, EXP_BRACKETING_OFF", __func__);
+            expBracket.mode = CAM_EXP_BRACKETING_OFF;
+        }
+        break;
     }
 
     /* save the value*/
@@ -4791,7 +4806,7 @@
     if (qdepth < 0) {
         qdepth = 2;
     }
-    return qdepth + MM_CAMERA_BUNDLE_HISTORY_SIZE;
+    return qdepth;
 }
 
 /*===========================================================================
@@ -4813,6 +4828,20 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : getZSLMaxUnmatchedFrames
+ *
+ * DESCRIPTION: get allowed ZSL max unmatched frames number
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : ZSL backlook count value
+ *==========================================================================*/
+int QCameraParameters::getMaxUnmatchedFramesInQueue()
+{
+    return m_pCapability->min_num_pp_bufs;
+}
+
+/*===========================================================================
  * FUNCTION   : setRecordingHintValue
  *
  * DESCRIPTION: set recording hint
@@ -4873,6 +4902,33 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : getNumOfHDRBufsIfNeeded
+ *
+ * DESCRIPTION: get number of buffers needed by HDR if HDR is enabled
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : number of buffer needed by HDR; 0 if not HDR enabled
+ *==========================================================================*/
+uint8_t QCameraParameters::getNumOfHDRBufsIfNeeded()
+{
+    uint8_t numOfBufs = 0;
+    const char *scene_mode = get(KEY_SCENE_MODE);
+    if (scene_mode != NULL && strcmp(scene_mode, SCENE_MODE_HDR) == 0) {
+        // HDR mode
+        const char *need_hdr_1x = get(KEY_QC_HDR_NEED_1X);
+        if (need_hdr_1x != NULL && strcmp(need_hdr_1x, VALUE_TRUE) == 0) {
+            numOfBufs = 2; // HDR needs both 1X and processed img
+        } else {
+            numOfBufs = 1; // HDR only needs processed img
+        }
+
+        numOfBufs += m_pCapability->min_num_hdr_bufs;
+    }
+    return numOfBufs;
+}
+
+/*===========================================================================
  * FUNCTION   : getBurstNum
  *
  * DESCRIPTION: get burst number of snapshot
@@ -5530,7 +5586,7 @@
     char area_str[32];
     const char *start, *end, *p;
     start = str; end = NULL;
-    int values[4], index=0;
+    int values[5], index=0;
     num_areas_found = 0;
 
     while(start != NULL) {
diff --git a/QCamera2/HAL/QCameraParameters.h b/QCamera2/HAL/QCameraParameters.h
index b088390..163209d 100644
--- a/QCamera2/HAL/QCameraParameters.h
+++ b/QCamera2/HAL/QCameraParameters.h
@@ -367,11 +367,13 @@
     int getZSLBurstInterval();
     int getZSLQueueDepth();
     int getZSLBackLookCount();
+    int getMaxUnmatchedFramesInQueue();
     bool isZSLMode() {return m_bZslMode;};
     bool isNoDisplayMode() {return m_bNoDisplayMode;};
     bool isWNREnabled() {return m_bWNROn;};
     uint8_t getNumOfSnapshots();
     uint8_t getNumOfExtraHDRBufsIfNeeded();
+    uint8_t getNumOfHDRBufsIfNeeded();
     int getBurstNum();
     bool getRecordingHintValue() {return m_bRecordingHint;}; // return local copy of video hint
     int setRecordingHintValue(int32_t value); // set local copy of video hint and send to server
diff --git a/QCamera2/HAL/QCameraPostProc.cpp b/QCamera2/HAL/QCameraPostProc.cpp
index 31d55f3..deca968 100644
--- a/QCamera2/HAL/QCameraPostProc.cpp
+++ b/QCamera2/HAL/QCameraPostProc.cpp
@@ -536,7 +536,7 @@
     }
 
     if (m_parent->mDataCb == NULL ||
-        m_parent->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE) == 0 ) {
+        m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) == 0 ) {
         ALOGD("%s: No dataCB or CAMERA_MSG_COMPRESSED_IMAGE not enabled",
               __func__);
         rc = NO_ERROR;
@@ -964,7 +964,7 @@
     // send upperlayer callback for raw image
     camera_memory_t *mem = memObj->getMemory(main_frame->buf_idx, false);
     if (NULL != m_parent->mDataCb &&
-        m_parent->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) > 0) {
+        m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
         qcamera_callback_argm_t cbArg;
         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
         cbArg.cb_type = QCAMERA_DATA_CALLBACK;
@@ -974,7 +974,7 @@
         m_parent->m_cbNotifier.notifyCallback(cbArg);
     }
     if (NULL != m_parent->mNotifyCb &&
-        m_parent->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
+        m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
         qcamera_callback_argm_t cbArg;
         memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
         cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
@@ -1083,7 +1083,11 @@
 
     mm_camera_buf_def_t *frame = recvd_frame->bufs[0];
     QCameraMemory *rawMemObj = (QCameraMemory *)frame->mem_info;
-    camera_memory_t *raw_mem = rawMemObj->getMemory(frame->buf_idx, false);
+    camera_memory_t *raw_mem = NULL;
+
+    if (rawMemObj != NULL) {
+        raw_mem = rawMemObj->getMemory(frame->buf_idx, false);
+    }
 
     if (NULL != rawMemObj && NULL != raw_mem) {
         // send data callback for COMPRESSED_IMAGE
@@ -1091,11 +1095,11 @@
 
         // dump frame into file
         m_parent->dumpFrameToFile(frame->buffer, frame->frame_len,
-                                  frame->buf_idx, QCAMERA_DUMP_FRM_RAW);
+                                  frame->frame_idx, QCAMERA_DUMP_FRM_RAW);
 
         // send data callback / notify for RAW_IMAGE
         if (NULL != m_parent->mDataCb &&
-            m_parent->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE) > 0) {
+            m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE) > 0) {
             qcamera_callback_argm_t cbArg;
             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
             cbArg.cb_type = QCAMERA_DATA_CALLBACK;
@@ -1105,7 +1109,7 @@
             m_parent->m_cbNotifier.notifyCallback(cbArg);
         }
         if (NULL != m_parent->mNotifyCb &&
-            m_parent->msgTypeEnabled(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
+            m_parent->msgTypeEnabledWithLock(CAMERA_MSG_RAW_IMAGE_NOTIFY) > 0) {
             qcamera_callback_argm_t cbArg;
             memset(&cbArg, 0, sizeof(qcamera_callback_argm_t));
             cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
@@ -1116,7 +1120,7 @@
         }
 
         if ((m_parent->mDataCb != NULL) &&
-            m_parent->msgTypeEnabled(CAMERA_MSG_COMPRESSED_IMAGE) > 0) {
+            m_parent->msgTypeEnabledWithLock(CAMERA_MSG_COMPRESSED_IMAGE) > 0) {
             qcamera_release_data_t release_data;
             memset(&release_data, 0, sizeof(qcamera_release_data_t));
             release_data.frame = recvd_frame;
@@ -1307,6 +1311,10 @@
                         }
 
                         if (0 != ret) {
+                            // free pp_job
+                            if (pp_job != NULL) {
+                                free(pp_job);
+                            }
                             // free frame
                             if (pp_frame != NULL) {
                                 pme->releaseSuperBuf(pp_frame);
diff --git a/QCamera2/HAL/QCameraStream.cpp b/QCamera2/HAL/QCameraStream.cpp
index fb95475..9ca6d2c 100644
--- a/QCamera2/HAL/QCameraStream.cpp
+++ b/QCamera2/HAL/QCameraStream.cpp
@@ -95,6 +95,29 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : invalidate_buf
+ *
+ * DESCRIPTION: static function entry to invalidate a specific stream buffer
+ *
+ * PARAMETERS :
+ *   @index      : index of the stream buffer to invalidate
+ *   @user_data  : user data ptr of ops_tbl
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::invalidate_buf(int index, void *user_data)
+{
+    QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
+    if (!stream) {
+        ALOGE("invalid stream pointer");
+        return NO_MEMORY;
+    }
+    return stream->invalidateBuf(index);
+}
+
+/*===========================================================================
  * FUNCTION   : QCameraStream
  *
  * DESCRIPTION: constructor of QCameraStream
@@ -128,6 +151,7 @@
     mMemVtbl.user_data = this;
     mMemVtbl.get_bufs = get_bufs;
     mMemVtbl.put_bufs = put_bufs;
+    mMemVtbl.invalidate_buf = invalidate_buf;
     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
     memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
     memset(&mCropInfo, 0, sizeof(cam_rect_t));
@@ -455,7 +479,6 @@
     if (rc < 0)
         return rc;
 
-    mStreamBufs->invalidateCache(index);
     return rc;
 }
 
@@ -565,6 +588,8 @@
         mStreamBufs->deallocate();
         delete mStreamBufs;
         mStreamBufs = NULL;
+        free(regFlags);
+        regFlags = NULL;
         return INVALID_OPERATION;
     }
     for (int i = 0; i < mNumBufs; i++) {
@@ -582,6 +607,8 @@
         mStreamBufs = NULL;
         free(mBufDefs);
         mBufDefs = NULL;
+        free(regFlags);
+        regFlags = NULL;
         return INVALID_OPERATION;
     }
 
@@ -622,6 +649,23 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : invalidateBuf
+ *
+ * DESCRIPTION: invalidate a specific stream buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer to invalidate
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::invalidateBuf(int index)
+{
+    return mStreamBufs->invalidateCache(index);
+}
+
+/*===========================================================================
  * FUNCTION   : isTypeOf
  *
  * DESCRIPTION: helper function to determine if the stream is of the queried type
diff --git a/QCamera2/HAL/QCameraStream.h b/QCamera2/HAL/QCameraStream.h
index 09484b3..f61fb3b 100644
--- a/QCamera2/HAL/QCameraStream.h
+++ b/QCamera2/HAL/QCameraStream.h
@@ -116,6 +116,7 @@
     static int32_t put_bufs(
                      mm_camera_map_unmap_ops_tbl_t *ops_tbl,
                      void *user_data);
+    static int32_t invalidate_buf(int index, void *user_data);
 
     int32_t getBufs(cam_frame_len_offset_t *offset,
                      uint8_t *num_bufs,
@@ -123,6 +124,7 @@
                      mm_camera_buf_def_t **bufs,
                      mm_camera_map_unmap_ops_tbl_t *ops_tbl);
     int32_t putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl);
+    int32_t invalidateBuf(int index);
 
 };
 
diff --git a/QCamera2/HAL/test/qcamera_test.cpp b/QCamera2/HAL/test/qcamera_test.cpp
index 73ca2cb..52c5415 100644
--- a/QCamera2/HAL/test/qcamera_test.cpp
+++ b/QCamera2/HAL/test/qcamera_test.cpp
@@ -257,40 +257,51 @@
 void CameraContext::printSupportedParams()
 {
     printf("\n\r\tSupported Cameras: %s",
-           mParams.get("camera-indexes"));
+           mParams.get("camera-indexes")? mParams.get("camera-indexes") : "NULL");
     printf("\n\r\tSupported Picture Sizes: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES));
+           mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES) : "NULL");
     printf("\n\r\tSupported Picture Formats: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
+           mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS) : "NULL");
     printf("\n\r\tSupported Preview Sizes: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES));
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES) : "NULL");
     printf("\n\r\tSupported Preview Formats: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS));
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS) : "NULL");
     printf("\n\r\tSupported Preview Frame Rates: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES) : "NULL");
     printf("\n\r\tSupported Thumbnail Sizes: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES));
+           mParams.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES) : "NULL");
     printf("\n\r\tSupported Whitebalance Modes: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE));
+           mParams.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE) : "NULL");
     printf("\n\r\tSupported Effects: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_EFFECTS));
+           mParams.get(CameraParameters::KEY_SUPPORTED_EFFECTS)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_EFFECTS) : "NULL");
     printf("\n\r\tSupported Scene Modes: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES));
+           mParams.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_SCENE_MODES) : "NULL");
     printf("\n\r\tSupported Focus Modes: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES));
+           mParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES) : "NULL");
     printf("\n\r\tSupported Antibanding Options: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING));
+           mParams.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_ANTIBANDING) : "NULL");
     printf("\n\r\tSupported Flash Modes: %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES));
+           mParams.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES) : "NULL");
     printf("\n\r\tSupported Focus Areas: %d",
            mParams.getInt(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS));
     printf("\n\r\tSupported FPS ranges : %s",
-           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE));
-
-    if ( NULL != mParams.get(CameraParameters::KEY_FOCUS_DISTANCES) ) {
-        printf("\n\r\tFocus Distances: %s \n",
-               mParams.get(CameraParameters::KEY_FOCUS_DISTANCES));
-    }
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE)?
+           mParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE) : "NULL");
+    printf("\n\r\tFocus Distances: %s \n",
+           mParams.get(CameraParameters::KEY_FOCUS_DISTANCES)?
+           mParams.get(CameraParameters::KEY_FOCUS_DISTANCES) : "NULL");
 }
 
 /*===========================================================================
diff --git a/QCamera2/stack/common/cam_types.h b/QCamera2/stack/common/cam_types.h
index d166210..a4b46a7 100644
--- a/QCamera2/stack/common/cam_types.h
+++ b/QCamera2/stack/common/cam_types.h
@@ -35,6 +35,8 @@
 #include <inttypes.h>
 #include <media/msmb_camera.h>
 
+#define CAM_MAX_NUM_BUFS_PER_STREAM 24
+
 #define CEILING32(X) (((X) + 0x0001F) & 0xFFFFFFE0)
 #define CEILING16(X) (((X) + 0x000F) & 0xFFF0)
 #define CEILING4(X)  (((X) + 0x0003) & 0xFFFC)
diff --git a/QCamera2/stack/common/mm_camera_interface.h b/QCamera2/stack/common/mm_camera_interface.h
old mode 100755
new mode 100644
index 5481d08..fa8cd02
--- a/QCamera2/stack/common/mm_camera_interface.h
+++ b/QCamera2/stack/common/mm_camera_interface.h
@@ -36,12 +36,10 @@
 #include "cam_queue.h"
 
 #define MM_CAMERA_MAX_NUM_SENSORS MSM_MAX_CAMERA_SENSORS
-#define MM_CAMERA_MAX_NUM_FRAMES 16
+#define MM_CAMERA_MAX_NUM_FRAMES CAM_MAX_NUM_BUFS_PER_STREAM
 /* num of channels allowed in a camera obj */
 #define MM_CAMERA_CHANNEL_MAX 16
 
-#define MM_CAMERA_BUNDLE_HISTORY_SIZE 2
-
 #define PAD_TO_SIZE(size, padding) ((size + padding - 1) & ~(padding - 1))
 
 /** mm_camera_buf_def_t: structure for stream frame buf
@@ -183,6 +181,7 @@
                        void *user_data);
   int32_t (*put_bufs) (mm_camera_map_unmap_ops_tbl_t *ops_tbl,
                        void *user_data);
+  int32_t (*invalidate_buf)(int index, void *user_data);
 } mm_camera_stream_mem_vtbl_t;
 
 /** mm_camera_stream_config_t: structure for stream
@@ -243,6 +242,8 @@
 *    @post_frame_skip : after send first frame to HAL, how many
 *                     frames needing to be skipped for next
 *                     delivery. Only valid for burst mode
+*    @max_unmatched_frames : max number of unmatched frames in
+*                     queue
 *    @priority : save matched priority frames only
 **/
 typedef struct {
@@ -250,6 +251,7 @@
     uint8_t water_mark;
     uint8_t look_back;
     uint8_t post_frame_skip;
+    uint8_t max_unmatched_frames;
     mm_camera_super_buf_priority_t priority;
 } mm_camera_channel_attr_t;
 
diff --git a/QCamera2/stack/common/mm_jpeg_interface.h b/QCamera2/stack/common/mm_jpeg_interface.h
index 64b2984..3388a4d 100644
--- a/QCamera2/stack/common/mm_jpeg_interface.h
+++ b/QCamera2/stack/common/mm_jpeg_interface.h
@@ -33,7 +33,7 @@
 #include "cam_intf.h"
 
 #define MM_JPEG_MAX_PLANES 3
-#define MM_JPEG_MAX_BUF 10
+#define MM_JPEG_MAX_BUF CAM_MAX_NUM_BUFS_PER_STREAM
 
 typedef enum {
   MM_JPEG_FMT_YUV,
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera.c b/QCamera2/stack/mm-camera-interface/src/mm_camera.c
old mode 100755
new mode 100644
index c95beb6..7d96521
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera.c
@@ -274,8 +274,8 @@
         }
         CDBG("%s:failed with I/O error retrying after %d milli-seconds",
              __func__, sleep_msec);
-        usleep(sleep_msec*1000);
-    }while(n_try>0);
+        usleep(sleep_msec * 1000);
+    }while (n_try > 0);
 
     if (my_obj->ctrl_fd <= 0) {
         CDBG_ERROR("%s: cannot open control fd of '%s' (%s)\n",
@@ -369,11 +369,11 @@
 
     if(my_obj->ctrl_fd > 0) {
         close(my_obj->ctrl_fd);
-        my_obj->ctrl_fd = -1;
+        my_obj->ctrl_fd = 0;
     }
     if(my_obj->ds_fd > 0) {
         mm_camera_socket_close(my_obj->ds_fd);
-        my_obj->ds_fd = -1;
+        my_obj->ds_fd = 0;
     }
 
     pthread_mutex_destroy(&my_obj->cb_lock);
@@ -743,9 +743,9 @@
         ch_obj->state = MM_CHANNEL_STATE_STOPPED;
         ch_obj->cam_obj = my_obj;
         pthread_mutex_init(&ch_obj->ch_lock, NULL);
+        mm_channel_init(ch_obj, attr, channel_cb, userdata);
     }
 
-    mm_channel_init(ch_obj, attr, channel_cb, userdata);
     pthread_mutex_unlock(&my_obj->cam_lock);
 
     return ch_hdl;
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
index f84377a..58a9254 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
@@ -1617,12 +1617,12 @@
                 }
             }
     } else {
-        if (  ( MM_CAMERA_BUNDLE_HISTORY_SIZE < unmatched_bundles ) &&
+        if (  ( queue->attr.max_unmatched_frames < unmatched_bundles ) &&
               ( NULL == last_buf ) ) {
             /* incoming frame is older than the last bundled one */
             mm_channel_qbuf(ch_obj, buf_info->buf);
         } else {
-            if ( MM_CAMERA_BUNDLE_HISTORY_SIZE < unmatched_bundles ) {
+            if ( queue->attr.max_unmatched_frames < unmatched_bundles ) {
                 /* release the oldest bundled superbuf */
                 node = member_of(last_buf, cam_node_t, list);
                 super_buf = (mm_channel_queue_node_t*)node->data;
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
index 7dc736b..3b91f78 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
@@ -102,7 +102,9 @@
 {
     char *dev_name = NULL;
     uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handle);
-    dev_name = g_cam_ctrl.video_dev_name[cam_idx];
+    if(cam_idx < MM_CAMERA_MAX_NUM_SENSORS) {
+        dev_name = g_cam_ctrl.video_dev_name[cam_idx];
+    }
     return dev_name;
 }
 
@@ -122,7 +124,8 @@
     mm_camera_obj_t *cam_obj = NULL;
     uint8_t cam_idx = mm_camera_util_get_index_by_handler(cam_handle);
 
-    if ((NULL != g_cam_ctrl.cam_obj[cam_idx]) &&
+    if (cam_idx < MM_CAMERA_MAX_NUM_SENSORS &&
+        (NULL != g_cam_ctrl.cam_obj[cam_idx]) &&
         (cam_handle == g_cam_ctrl.cam_obj[cam_idx]->my_hdl)) {
         cam_obj = g_cam_ctrl.cam_obj[cam_idx];
     }
@@ -1218,7 +1221,7 @@
         int num_entities;
         snprintf(dev_name, sizeof(dev_name), "/dev/media%d", num_media_devices);
         dev_fd = open(dev_name, O_RDWR | O_NONBLOCK);
-        if (dev_fd < 0) {
+        if (dev_fd <= 0) {
             CDBG("Done discovering media devices\n");
             break;
         }
@@ -1227,12 +1230,14 @@
         if (rc < 0) {
             CDBG_ERROR("Error: ioctl media_dev failed: %s\n", strerror(errno));
             close(dev_fd);
+            dev_fd = 0;
             num_cameras = 0;
             break;
         }
 
         if(strncmp(mdev_info.model, MSM_CAMERA_NAME, sizeof(mdev_info.model)) != 0) {
             close(dev_fd);
+            dev_fd = 0;
             continue;
         }
 
@@ -1258,9 +1263,8 @@
             __func__, num_cameras, g_cam_ctrl.video_dev_name[num_cameras]);
 
         num_cameras++;
-        if (dev_fd > 0) {
-            close(dev_fd);
-        }
+        close(dev_fd);
+        dev_fd = 0;
     }
     g_cam_ctrl.num_cam = num_cameras;
 
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
index 7667036..93f1f8c 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -419,10 +419,8 @@
         } else {
             /* failed setting ext_mode
              * close fd */
-            if(my_obj->fd > 0) {
-                close(my_obj->fd);
-                my_obj->fd = 0;
-            }
+            close(my_obj->fd);
+            my_obj->fd = 0;
             break;
         }
         break;
@@ -2218,7 +2216,7 @@
     buf_planes->plane_info.mp[0].len =
         PAD_TO_SIZE(dim->width * dim->height, padding->plane_padding);
     buf_planes->plane_info.frame_len =
-        PAD_TO_SIZE(buf_planes->plane_info.mp[0].len, CAM_PAD_TO_4K);
+        buf_planes->plane_info.mp[0].len;
 
     buf_planes->plane_info.mp[0].offset_x =0;
     buf_planes->plane_info.mp[0].offset_y = 0;
@@ -2398,6 +2396,8 @@
         my_obj->buf_status[frame->buf_idx].buf_refcnt--;
         if (0 == my_obj->buf_status[frame->buf_idx].buf_refcnt) {
             CDBG("<DEBUG> : Buf done for buffer:%d", frame->buf_idx);
+            my_obj->mem_vtbl.invalidate_buf(frame->buf_idx,
+                                            my_obj->mem_vtbl.user_data);
             rc = mm_stream_qbuf(my_obj, frame);
             if(rc < 0) {
                 CDBG_ERROR("%s: mm_camera_stream_qbuf(idx=%d) err=%d\n",
diff --git a/QCamera2/stack/mm-camera-test/Android.mk b/QCamera2/stack/mm-camera-test/Android.mk
index 54549e9..e50ca7c 100644
--- a/QCamera2/stack/mm-camera-test/Android.mk
+++ b/QCamera2/stack/mm-camera-test/Android.mk
@@ -34,15 +34,15 @@
 LOCAL_C_INCLUDES+= $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
 LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
 
-LOCAL_CFLAGS += -DCAMERA_ION_HEAP_ID=ION_CP_MM_HEAP_ID
+LOCAL_CFLAGS += -DCAMERA_ION_HEAP_ID=ION_IOMMU_HEAP_ID
 ifeq ($(call is-board-platform,msm8974),true)
-        LOCAL_CFLAGS += -DCAMERA_GRALLOC_HEAP_ID=GRALLOC_USAGE_PRIVATE_MM_HEAP
+        LOCAL_CFLAGS += -DCAMERA_GRALLOC_HEAP_ID=GRALLOC_USAGE_PRIVATE_IOMMU_HEAP
         LOCAL_CFLAGS += -DCAMERA_GRALLOC_FALLBACK_HEAP_ID=GRALLOC_USAGE_PRIVATE_IOMMU_HEAP
         LOCAL_CFLAGS += -DCAMERA_ION_FALLBACK_HEAP_ID=ION_IOMMU_HEAP_ID
         LOCAL_CFLAGS += -DCAMERA_GRALLOC_CACHING_ID=0
         LOCAL_CFLAGS += -DNUM_RECORDING_BUFFERS=9
 else ifeq ($(call is-board-platform,msm8960),true)
-        LOCAL_CFLAGS += -DCAMERA_GRALLOC_HEAP_ID=GRALLOC_USAGE_PRIVATE_MM_HEAP
+        LOCAL_CFLAGS += -DCAMERA_GRALLOC_HEAP_ID=GRALLOC_USAGE_PRIVATE_IOMMU_HEAP
         LOCAL_CFLAGS += -DCAMERA_GRALLOC_FALLBACK_HEAP_ID=GRALLOC_USAGE_PRIVATE_IOMMU_HEAP
         LOCAL_CFLAGS += -DCAMERA_ION_FALLBACK_HEAP_ID=ION_IOMMU_HEAP_ID
         LOCAL_CFLAGS += -DCAMERA_GRALLOC_CACHING_ID=0
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
old mode 100755
new mode 100644
index bea2622..7107ce6
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
@@ -84,7 +84,7 @@
     memset(&my_cam_app->hal_lib, 0, sizeof(hal_interface_lib_t));
     my_cam_app->hal_lib.ptr = dlopen("libmmcamera_interface.so", RTLD_NOW);
     my_cam_app->hal_lib.ptr_jpeg = dlopen("libmmjpeg_interface.so", RTLD_NOW);
-    if (!my_cam_app->hal_lib.ptr) {
+    if (!my_cam_app->hal_lib.ptr || !my_cam_app->hal_lib.ptr_jpeg) {
         CDBG_ERROR("%s Error opening HAL library %s\n", __func__, dlerror());
         return -MM_CAMERA_E_GENERAL;
     }
@@ -95,6 +95,13 @@
     *(void **)&(my_cam_app->hal_lib.jpeg_open) =
         dlsym(my_cam_app->hal_lib.ptr_jpeg, "jpeg_open");
 
+    if (my_cam_app->hal_lib.get_num_of_cameras == NULL ||
+        my_cam_app->hal_lib.mm_camera_open == NULL ||
+        my_cam_app->hal_lib.jpeg_open == NULL) {
+        CDBG_ERROR("%s Error loading HAL sym %s\n", __func__, dlerror());
+        return -MM_CAMERA_E_GENERAL;
+    }
+
     my_cam_app->num_cameras = my_cam_app->hal_lib.get_num_of_cameras();
     CDBG("%s: num_cameras = %d\n", __func__, my_cam_app->num_cameras);
 
@@ -385,6 +392,7 @@
         mm_app_release_bufs(stream->num_of_bufs, &stream->s_bufs[0]);
         free(pBufs);
         free(reg_flags);
+        return rc;
     }
 
     *num_bufs = stream->num_of_bufs;
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
index cb29576..b87aa8e 100644
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
@@ -118,6 +118,11 @@
         }
     }
 
+    if (!m_frame || !p_frame) {
+        CDBG_ERROR("%s: cannot find preview/snapshot frame", __func__);
+        return;
+    }
+
     mm_app_dump_frame(p_frame, "zsl_preview", "yuv", p_frame->frame_idx);
     mm_app_dump_frame(m_frame, "zsl_main", "yuv", m_frame->frame_idx);
 
@@ -341,6 +346,7 @@
     attr.look_back = 2;
     attr.post_frame_skip = 0;
     attr.water_mark = 2;
+    attr.max_unmatched_frames = 3;
     channel = mm_app_add_channel(test_obj,
                                  MM_CHANNEL_TYPE_ZSL,
                                  &attr,
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c
index 2354ef1..503bb42 100644
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c
@@ -263,7 +263,6 @@
 {
     int rc = MM_CAMERA_OK;
     mm_camera_channel_t *channel = NULL;
-    mm_camera_stream_t *stream = NULL;
 
     channel = mm_app_add_rdi_channel(test_obj, num_burst);
     if (NULL == channel) {
@@ -274,7 +273,6 @@
     rc = mm_app_start_channel(test_obj, channel);
     if (MM_CAMERA_OK != rc) {
         CDBG_ERROR("%s:start rdi failed rc=%d\n", __func__, rc);
-        mm_app_del_stream(test_obj, channel, stream);
         mm_app_del_channel(test_obj, channel);
         return rc;
     }
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c
index 0da359c..28cccd8 100644
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c
@@ -349,6 +349,7 @@
 
     memset(&attr, 0, sizeof(mm_camera_channel_attr_t));
     attr.notify_mode = MM_CAMERA_SUPER_BUF_NOTIFY_CONTINUOUS;
+    attr.max_unmatched_frames = 3;
     channel = mm_app_add_channel(test_obj,
                                  MM_CHANNEL_TYPE_CAPTURE,
                                  &attr,
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c
index 5b56b07..d63c651 100644
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c
@@ -144,7 +144,7 @@
     }
 
     s_ch = mm_app_add_snapshot_channel(test_obj);
-    if (NULL == v_ch) {
+    if (NULL == s_ch) {
         CDBG_ERROR("%s: add snapshot channel failed", __func__);
         mm_app_del_channel(test_obj, p_ch);
         mm_app_del_channel(test_obj, v_ch);
diff --git a/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c b/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
index cb92607..6f79b67 100644
--- a/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
+++ b/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
@@ -353,10 +353,25 @@
   mm_jpeg_transition_func_t p_exec)
 {
   OMX_ERRORTYPE ret = OMX_ErrorNone;
+  OMX_STATETYPE current_state;
   CDBG("%s:%d] new_state %d p_exec %p", __func__, __LINE__,
     new_state, p_exec);
 
+
   pthread_mutex_lock(&p_session->lock);
+
+  ret = OMX_GetState(p_session->omx_handle, &current_state);
+
+  if (ret) {
+    pthread_mutex_unlock(&p_session->lock);
+    return ret;
+  }
+
+  if (current_state == new_state) {
+    pthread_mutex_unlock(&p_session->lock);
+    return OMX_ErrorNone;
+  }
+
   p_session->state_change_pending = OMX_TRUE;
   ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
     new_state, NULL);
@@ -661,6 +676,7 @@
   mm_jpeg_encode_params_t *p_params = &p_session->params;
   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   mm_jpeg_dim_t *p_thumb_dim = &p_jobparams->thumb_dim;
+  mm_jpeg_dim_t *p_main_dim = &p_jobparams->main_dim;
 
   CDBG_HIGH("%s:%d] encode_thumbnail %d", __func__, __LINE__,
     p_params->encode_thumbnail);
@@ -708,7 +724,7 @@
     return ret;
   }
 
-  /* fill thumbnail info*/
+  /* fill thumbnail info */
   thumbnail_info.scaling_enabled = 1;
   thumbnail_info.input_width = p_thumb_dim->src_dim.width;
   thumbnail_info.input_height = p_thumb_dim->src_dim.height;
@@ -716,6 +732,26 @@
   thumbnail_info.crop_info.nHeight = p_thumb_dim->crop.height;
   thumbnail_info.crop_info.nLeft = p_thumb_dim->crop.left;
   thumbnail_info.crop_info.nTop = p_thumb_dim->crop.top;
+
+  if ((p_main_dim->src_dim.width < p_thumb_dim->src_dim.width) ||
+    (p_main_dim->src_dim.height < p_thumb_dim->src_dim.height)) {
+    CDBG_ERROR("%s:%d] Improper thumbnail dim %dx%d resetting to %dx%d",
+      __func__, __LINE__,
+      p_thumb_dim->src_dim.width,
+      p_thumb_dim->src_dim.height,
+      p_main_dim->src_dim.width,
+      p_main_dim->src_dim.height);
+    thumbnail_info.input_width = p_main_dim->src_dim.width;
+    thumbnail_info.input_height = p_main_dim->src_dim.height;
+    if ((thumbnail_info.crop_info.nWidth > thumbnail_info.input_width)
+      || (thumbnail_info.crop_info.nHeight > thumbnail_info.input_height)) {
+      thumbnail_info.crop_info.nLeft = 0;
+      thumbnail_info.crop_info.nTop = 0;
+      thumbnail_info.crop_info.nWidth = thumbnail_info.input_width;
+      thumbnail_info.crop_info.nHeight = thumbnail_info.input_height;
+    }
+  }
+
   if ((p_thumb_dim->dst_dim.width > p_thumb_dim->src_dim.width)
     || (p_thumb_dim->dst_dim.height > p_thumb_dim->src_dim.height)) {
     CDBG_ERROR("%s:%d] Incorrect thumbnail dim %dx%d resetting to %dx%d",
@@ -951,10 +987,30 @@
  **/
 OMX_BOOL mm_jpeg_session_abort(mm_jpeg_job_session_t *p_session)
 {
+  OMX_ERRORTYPE ret = OMX_ErrorNone;
+
   CDBG("%s:%d] E", __func__, __LINE__);
   pthread_mutex_lock(&p_session->lock);
+  if (OMX_TRUE == p_session->abort_flag) {
+    pthread_mutex_unlock(&p_session->lock);
+    CDBG("%s:%d] **** ALREADY ABORTED", __func__, __LINE__);
+    return 0;
+  }
   p_session->abort_flag = OMX_TRUE;
   if (OMX_TRUE == p_session->encoding) {
+    p_session->state_change_pending = OMX_TRUE;
+
+    CDBG("%s:%d] **** ABORTING", __func__, __LINE__);
+
+    ret = OMX_SendCommand(p_session->omx_handle, OMX_CommandStateSet,
+    OMX_StateIdle, NULL);
+
+    if (ret != OMX_ErrorNone) {
+      CDBG("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret);
+      pthread_mutex_unlock(&p_session->lock);
+      return 1;
+    }
+
     CDBG("%s:%d] before wait", __func__, __LINE__);
     pthread_cond_wait(&p_session->cond, &p_session->lock);
     CDBG("%s:%d] after wait", __func__, __LINE__);
@@ -2005,6 +2061,19 @@
     p_session->error_flag = OMX_ErrorHardware;
     if (p_session->encoding == OMX_TRUE) {
       CDBG("%s:%d] Error during encoding", __func__, __LINE__);
+
+      /* send jpeg callback */
+      if (NULL != p_session->params.jpeg_cb) {
+        p_session->job_status = JPEG_JOB_STATUS_ERROR;
+        CDBG("%s:%d] send jpeg error callback %d", __func__, __LINE__,
+          p_session->job_status);
+        p_session->params.jpeg_cb(p_session->job_status,
+          p_session->client_hdl,
+          p_session->jobId,
+          NULL,
+          p_session->params.userdata);
+      }
+
       /* remove from ready queue */
       mm_jpeg_job_done(p_session);
     }
diff --git a/QCamera2/stack/mm-jpeg-interface/test/Android.mk b/QCamera2/stack/mm-jpeg-interface/test/Android.mk
index 78ef16f..1e73331 100644
--- a/QCamera2/stack/mm-jpeg-interface/test/Android.mk
+++ b/QCamera2/stack/mm-jpeg-interface/test/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_PATH := $(MM_JPEG_TEST_PATH)
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_CFLAGS := -DCAMERA_ION_HEAP_ID=ION_CP_MM_HEAP_ID
+LOCAL_CFLAGS := -DCAMERA_ION_HEAP_ID=ION_IOMMU_HEAP_ID
 LOCAL_CFLAGS += -Werror
 LOCAL_CFLAGS += -D_ANDROID_
 LOCAL_CFLAGS += -include mm_jpeg_dbg.h
diff --git a/QCamera2/stack/mm-jpeg-interface/test/mm_jpeg_ionbuf.c b/QCamera2/stack/mm-jpeg-interface/test/mm_jpeg_ionbuf.c
index 1284153..fbfcd6a 100644
--- a/QCamera2/stack/mm-jpeg-interface/test/mm_jpeg_ionbuf.c
+++ b/QCamera2/stack/mm-jpeg-interface/test/mm_jpeg_ionbuf.c
@@ -52,8 +52,7 @@
    p_buffer->alloc.len = p_buffer->size;
    p_buffer->alloc.align = 4096;
    p_buffer->alloc.flags = ION_FLAG_CACHED;
-   p_buffer->alloc.heap_mask =
-     (0x1 << ION_CP_MM_HEAP_ID | 0x1 << ION_IOMMU_HEAP_ID);
+   p_buffer->alloc.heap_mask = 0x1 << ION_IOMMU_HEAP_ID;
 
    p_buffer->ion_fd = open("/dev/ion", O_RDONLY);
    if(p_buffer->ion_fd < 0) {