msmcobalt: Update to 07.00.00.253.039

msmcobalt: from hardware/qcom/camera
  6a95727 HAL1: check buffer index range before enqueue buffer
  5b5d6ce Promotion of camera.lnx.1.0-00140.
  c7d9cff Merge "QCamera2: mm-qcamera app changes inline with cache interface" into camera.lnx.1.0-dev.1.0
  2c35c4d Merge "QCamera2: Add cache flags to frame buffer" into camera.lnx.1.0-dev.1.0
  dac1c86 Merge "QCamera2: mm-jpeg-interface: Fix Jpeg lib2d rotation bugs" into camera.lnx.1.0-dev.1.0
  5453029 Merge "QCamera2: Changes to enahance dual camera events." into camera.lnx.1.0-dev.1.0
  8ecc5a8 Merge "QCamera2: Changes to support dual bayer sensor" into camera.lnx.1.0-dev.1.0
  0ba0000 Merge "QCamera2: Make change to add SHDR mode to mm-qcamera-app" into camera.lnx.1.0-dev.1.0
  c3dbcbf QCamera2: mm-qcamera app changes inline with cache interface
  768b6b1 QCamera2:test: Add Support for 3A Debug
  1b49e79 QCamera2: Add cache flags to frame buffer
  f032013 Promotion of camera.lnx.1.0-00137.
  2ee7556 QCamera2: mm-jpeg-interface: Fix Jpeg lib2d rotation bugs
  420452a Merge "QCamera2: mm-jpeg-interface: Pass fd of final jpeg buffer" into camera.lnx.1.0-dev.1.0
  73f3108 Merge "QCamera2: Changes to compile using SDLLVM compiler" into camera.lnx.1.0-dev.1.0
  007c6f5 Merge "QCamera2: HAL3: Changes for instant AEC with HAL3" into camera.lnx.1.0-dev.1.0
  260e481 Merge "QCamera2: HAL1: Bug fix in dequeuing the deferred preview buffers" into camera.lnx.1.0-dev.1.0
  04cde8a Merge "QCamera2:HAL1: Adding safety check while updating MaxPicSize." into camera.lnx.1.0-dev.1.0
  7e204e3 Merge "Clear the power module handle when the lib loading fails" into camera.lnx.1.0-dev.1.0
  8370293 QCamera2: Changes to enahance dual camera events.
  3679e1d QCamera2: Make change to add SHDR mode to mm-qcamera-app
  345b87d Merge "QCamera2: HAL3: Fix Postview Corruption" into camera.lnx.1.0-dev.1.0
  0fb17f5 Merge "QCamera2/HAL3: Check if the key exists before accessing the value" into camera.lnx.1.0-dev.1.0
  8491671 Merge "QCamera2/HAL3: Mutex lock mBatchSize in captureResultCb" into camera.lnx.1.0-dev.1.0
  57440f8 Merge "QCamera2/HAL3: Report ERROR_RESULT when metadata is dropped" into camera.lnx.1.0-dev.1.0
  8deff8a Merge "QCamera2:HAL1: Setting Quadra CFA format." into camera.lnx.1.0-dev.1.0
  57e40c1 Merge "QCamera2:HAL3: Fixing a bug during flush." into camera.lnx.1.0-dev.1.0
  a19ac7d Merge "QCamera2: HAL3: Vendor tag support for metering modes" into camera.lnx.1.0-dev.1.0
  b9a8c91 Merge "QCamera2: HAL3: Vendor tag support for ISO priority, Exposure Time priority and Saturation." into camera.lnx.1.0-dev.1.0
  17aa8a9 QCamera2: Changes to support dual bayer sensor
  bbcf84e QCamera2: HAL3: Changes for instant AEC with HAL3
  b363947 QCamera2: Changes to compile using SDLLVM compiler
  97a0d74 QCamera2:HAL1: Adding safety check while updating MaxPicSize.
  7b41e24 Clear the power module handle when the lib loading fails
  d3e62d8 QCamera2: HAL3: Fix Postview Corruption
  1da3b08 QCamera2: HAL3: Vendor tag support for metering modes
  c9da640 QCamera2: HAL3: Vendor tag support for ISO priority, Exposure Time priority and Saturation.
  851eb4e QCamera2: mm-jpeg-interface: Pass fd of final jpeg buffer
  5570d69 QCamera2:HAL1: Setting Quadra CFA format.
  d84a158 QCamera2:HAL3: Fixing a bug during flush.
  365a514 QCamera2/HAL3: Check if the key exists before accessing the value
  83777f9 QCamera2/HAL3: Report ERROR_RESULT when metadata is dropped
  78164b5 QCamera2/HAL3: Mutex lock mBatchSize in captureResultCb
  8cf0572 QCamera2: HAL1: Bug fix in dequeuing the deferred preview buffers

Change-Id: I67a63e79208da5741e9d12aec281b5ce11585980
Signed-off-by: Thierry Strudel <tstrudel@google.com>
diff --git a/msmcobalt/QCamera2/Android.mk b/msmcobalt/QCamera2/Android.mk
index 1bb6e8f..c0a1912 100644
--- a/msmcobalt/QCamera2/Android.mk
+++ b/msmcobalt/QCamera2/Android.mk
@@ -1,3 +1,11 @@
+# Enable SDLLVM compiler option for build flavour >= N flavour
+PLATFORM_SDK_NPDK = 24
+ENABLE_CAM_SDLLVM  := $(shell if [ $(PLATFORM_SDK_VERSION) -ge $(PLATFORM_SDK_NPDK) ] ; then echo true ; else echo false ; fi)
+ifeq ($(ENABLE_CAM_SDLLVM),true)
+SDCLANGSAVE := $(SDCLANG)
+SDCLANG := true
+endif
+
 ifneq (,$(filter $(TARGET_ARCH), arm arm64))
 
 LOCAL_PATH:= $(call my-dir)
@@ -134,3 +142,7 @@
 
 include $(call first-makefiles-under,$(LOCAL_PATH))
 endif
+ifeq ($(ENABLE_CAM_SDLLVM),true)
+SDCLANG := $(SDCLANGSAVE)
+endif
+
diff --git a/msmcobalt/QCamera2/HAL/QCamera2HWI.cpp b/msmcobalt/QCamera2/HAL/QCamera2HWI.cpp
index f0eaf5e..8be48cd 100644
--- a/msmcobalt/QCamera2/HAL/QCamera2HWI.cpp
+++ b/msmcobalt/QCamera2/HAL/QCamera2HWI.cpp
@@ -1991,6 +1991,10 @@
     property_get("persist.camera.depth.focus.cb", value, "1");
     bDepthAFCallbacks = atoi(value);
 
+    memset(value, 0, sizeof(value));
+    property_get("persist.camera.cache.optimize", value, "1");
+    m_bOptimizeCacheOps = atoi(value);
+
     return NO_ERROR;
 
 error_exit3:
@@ -2014,19 +2018,14 @@
  *
  * PARAMETERS :
  *   @sync        :indicates whether syncing is On or Off
- *   @sessionid  :session id for other camera session
  *
  * RETURN     : int32_t type of status
  *              NO_ERROR  -- success
  *              none-zero failure code
  *==========================================================================*/
-int QCamera2HardwareInterface::bundleRelatedCameras(bool syncOn,
-            uint32_t sessionid)
+int QCamera2HardwareInterface::bundleRelatedCameras(bool syncOn)
 {
-    LOGD("bundleRelatedCameras sync %d with sessionid %d",
-            syncOn, sessionid);
-
-    int32_t rc = mParameters.bundleRelatedCameras(syncOn, sessionid);
+    int32_t rc = mParameters.bundleRelatedCameras(syncOn);
     if (rc != NO_ERROR) {
         LOGE("bundleRelatedCameras failed %d", rc);
         return rc;
@@ -2443,6 +2442,7 @@
         goto failed_op;
     }
 
+    gCamCapability[cameraId]->camera_index = cameraId;
     if (is_dual_camera_by_idx(cameraId)) {
         handle = get_aux_camera_handle(cameraHandle->camera_handle);
         gCamCapability[cameraId]->aux_cam_cap =
@@ -3110,8 +3110,8 @@
         }
         bufferCnt = mem->getCnt();
     }
-    LOGH("rc = %d type = %d count = %d size = %d cache = %d, pool = %d",
-            rc, stream_type, bufferCnt, size, bCachedMem, bPoolMem);
+    LOGH("rc = %d type = %d count = %d size = %d cache = %d, pool = %d mEnqueuedBuffers = %d",
+            rc, stream_type, bufferCnt, size, bCachedMem, bPoolMem, mEnqueuedBuffers);
     return mem;
 }
 
@@ -3223,6 +3223,12 @@
     streamInfo->buf_cnt = streamInfo->num_bufs;
     streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
     streamInfo->is_secure = NON_SECURE;
+    // Initialize cache ops
+    if (!m_bOptimizeCacheOps) {
+        streamInfo->cache_ops = CAM_STREAM_CACHE_OPS_DISABLED;
+    } else {
+        streamInfo->cache_ops = CAM_STREAM_CACHE_OPS_HONOUR_FLAGS;
+    }
 
     switch (stream_type) {
     case CAM_STREAM_TYPE_SNAPSHOT:
@@ -3316,6 +3322,9 @@
     case CAM_STREAM_TYPE_ANALYSIS:
         streamInfo->noFrameExpected = 1;
         break;
+    case CAM_STREAM_TYPE_METADATA:
+        streamInfo->cache_ops = CAM_STREAM_CACHE_OPS_CLEAR_FLAGS;
+        break;
     default:
         break;
     }
@@ -6087,6 +6096,8 @@
         return NO_MEMORY;
     }
     memcpy(pBufPtr, img_ptr, config->input_buf_planes.plane_info.frame_len);
+    //Do cache ops before sending for reprocess
+    imgBuf->cacheOps(0, ION_IOC_CLEAN_INV_CACHES);
 
     cam_pp_feature_config_t pp_feature;
     memset(&pp_feature, 0, sizeof(cam_pp_feature_config_t));
@@ -6987,7 +6998,7 @@
     int32_t ret = NO_ERROR;
 
     //Set camera controls to parameter and back-end
-    ret = mParameters.setCameraControls(camState, TRUE);
+    ret = mParameters.setCameraControls(camState);
 
     //Update camera status to internal channel
     for (int i = 0; i < QCAMERA_CH_TYPE_MAX; i++) {
@@ -7035,7 +7046,12 @@
             }
         }
     }
+
     if (ret == NO_ERROR && mActiveCamera == MM_CAMERA_DUAL_CAM) {
+        //Trigger Event to modules to update Master info
+        mParameters.setSwitchCamera();
+
+        //Change active handle
         if (get_aux_camera_handle(mCameraHandle->camera_handle)
                 == m_ActiveHandle) {
             m_ActiveHandle = get_main_camera_handle(mCameraHandle->camera_handle);
@@ -7283,7 +7299,7 @@
     } else {
         padding_info =
                 gCamCapability[mCameraId]->padding_info;
-        if (streamType == CAM_STREAM_TYPE_PREVIEW) {
+        if (streamType == CAM_STREAM_TYPE_PREVIEW || streamType == CAM_STREAM_TYPE_POSTVIEW) {
             padding_info.width_padding = mSurfaceStridePadding;
             padding_info.height_padding = CAM_PAD_TO_2;
         }
diff --git a/msmcobalt/QCamera2/HAL/QCamera2HWI.h b/msmcobalt/QCamera2/HAL/QCamera2HWI.h
index c5d0985..985738f 100644
--- a/msmcobalt/QCamera2/HAL/QCamera2HWI.h
+++ b/msmcobalt/QCamera2/HAL/QCamera2HWI.h
@@ -192,7 +192,6 @@
 public:
     /* static variable and functions accessed by camera service */
     static camera_device_ops_t mCameraOps;
-
     static int set_preview_window(struct camera_device *,
         struct preview_stream_ops *window);
     static void set_CallBacks(struct camera_device *,
@@ -251,8 +250,7 @@
     int openCamera(struct hw_device_t **hw_device);
 
     // Dual camera specific oprations
-    int bundleRelatedCameras(bool syncOn,
-            uint32_t related_sensor_session_id);
+    int bundleRelatedCameras(bool syncOn);
     int getCameraSessionId(uint32_t* session_id);
     const cam_sync_related_sensors_event_info_t* getRelatedCamSyncInfo(
             void);
@@ -810,6 +808,7 @@
     nsecs_t mBootToMonoTimestampOffset;
     bool bDepthAFCallbacks;
     int32_t prev_zoomLevel;
+    bool m_bOptimizeCacheOps;
 };
 
 }; // namespace qcamera
diff --git a/msmcobalt/QCamera2/HAL/QCamera2HWICallbacks.cpp b/msmcobalt/QCamera2/HAL/QCamera2HWICallbacks.cpp
index a117b1a..69a47f7 100644
--- a/msmcobalt/QCamera2/HAL/QCamera2HWICallbacks.cpp
+++ b/msmcobalt/QCamera2/HAL/QCamera2HWICallbacks.cpp
@@ -342,6 +342,7 @@
             if (preview_frame) {
                 QCameraGrallocMemory *memory = (QCameraGrallocMemory *)preview_frame->mem_info;
                 uint32_t idx = preview_frame->buf_idx;
+                preview_frame->cache_flags |= CPU_HAS_READ;
                 rc = sendPreviewCallback(pStream, memory, idx);
                 if (NO_ERROR != rc) {
                     LOGE("Error triggering scene select preview callback");
@@ -884,9 +885,11 @@
     // Display the buffer.
     LOGD("%p displayBuffer %d E", pme, idx);
     uint8_t numMapped = memory->getMappable();
+    LOGD("EnqueuedCnt %d numMapped %d", dequeueCnt, numMapped);
 
     for (uint8_t i = 0; i < dequeueCnt; i++) {
         int dequeuedIdx = memory->dequeueBuffer();
+        LOGD("dequeuedIdx %d numMapped %d Loop running for %d", dequeuedIdx, numMapped, i);
         if (dequeuedIdx < 0 || dequeuedIdx >= memory->getCnt()) {
             LOGE("Invalid dequeued buffer index %d from display",
                    dequeuedIdx);
@@ -909,7 +912,8 @@
                 }
             }
         }
-
+        // Get the updated mappable buffer count since it's modified in dequeueBuffer()
+        numMapped = memory->getMappable();
         if (err < 0) {
             LOGE("buffer mapping failed %d", err);
         } else {
@@ -925,6 +929,7 @@
     if (pme->m_channels[QCAMERA_CH_TYPE_CALLBACK] == NULL) {
         if (pme->needSendPreviewCallback() &&
                 (!pme->mParameters.isSceneSelectionEnabled())) {
+            frame->cache_flags |= CPU_HAS_READ;
             int32_t rc = pme->sendPreviewCallback(stream, memory, idx);
             if (NO_ERROR != rc) {
                 LOGW("Preview callback was not sent succesfully");
@@ -1186,6 +1191,8 @@
             cbArg.user_data = (void *) &frame->buf_idx;
             cbArg.cookie = stream;
             cbArg.release_cb = returnStreamBuffer;
+            // Preset cache flags to be handled when the buffer comes back
+            frame->cache_flags |= CPU_HAS_READ;
             int32_t rc = pme->m_cbNotifier.notifyCallback(cbArg);
             if (rc != NO_ERROR) {
                 LOGE ("fail sending data notify");
@@ -1269,6 +1276,8 @@
                 cbArg.user_data = (void *) &frame->buf_idx;
                 cbArg.cookie     = stream;
                 cbArg.release_cb = returnStreamBuffer;
+                // Preset cache flags to be handled when the buffer comes back
+                frame->cache_flags |= CPU_HAS_READ;
                 pme->m_cbNotifier.notifyCallback(cbArg);
             } else {
                 LOGE("preview_mem is NULL");
@@ -1306,6 +1315,8 @@
             cbArg.user_data  = (void *) &frame->buf_idx;
             cbArg.cookie     = stream;
             cbArg.release_cb = returnStreamBuffer;
+            // Preset cache flags to be handled when the buffer comes back
+            frame->cache_flags |= CPU_HAS_READ;
             pme->m_cbNotifier.notifyCallback(cbArg);
         } else {
             LOGH("No need to process preview frame, return buffer");
@@ -2562,6 +2573,8 @@
     if (pme->mDataCb != NULL &&
             (pme->msgTypeEnabledWithLock(CAMERA_MSG_PREVIEW_FRAME) > 0) &&
             (!pme->mParameters.isSceneSelectionEnabled())) {
+        // Preset cache flags to be handled when the buffer comes back
+        frame->cache_flags |= CPU_HAS_READ;
         int32_t rc = pme->sendPreviewCallback(stream, previewMemObj, frame->buf_idx);
         if (NO_ERROR != rc) {
             LOGE("Preview callback was not sent succesfully");
@@ -2909,6 +2922,7 @@
                         LOGH("written number of bytes %ld\n",
                              written_len);
                         close(file_fd);
+                        frame->cache_flags |= CPU_HAS_READ;
                     } else {
                         LOGE("fail to open file for image dumping");
                     }
diff --git a/msmcobalt/QCamera2/HAL/QCameraChannel.cpp b/msmcobalt/QCamera2/HAL/QCameraChannel.cpp
index 1ca121b..b693904 100644
--- a/msmcobalt/QCamera2/HAL/QCameraChannel.cpp
+++ b/msmcobalt/QCamera2/HAL/QCameraChannel.cpp
@@ -1606,6 +1606,14 @@
                 LOGE("Metadata NULL");
             }
 
+            if (mParameter.getofflineRAW()) {
+                //For offline RAW reprocessing, make sure cache is clean & invalidated
+                frame->bufs[i]->cache_flags |= CPU_HAS_READ_WRITTEN;
+            }
+            //Do Cache ops before sending to reprocess
+            if (frame->bufs[i] != NULL) {
+                pStream->handleCacheOps(frame->bufs[i]);
+            }
             rc = doReprocessOffline (frame->bufs[i], meta_buf, pStream);
         }
     }
@@ -1664,6 +1672,11 @@
                 continue;
             }
 
+            //Do Cache ops before sending to reprocess
+            if (frame->bufs[i] != NULL) {
+                pStream->handleCacheOps(frame->bufs[i]);
+            }
+
             cam_stream_parm_buffer_t param;
             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
             param.type = CAM_STREAM_PARAM_TYPE_DO_REPROCESS;
diff --git a/msmcobalt/QCamera2/HAL/QCameraMem.cpp b/msmcobalt/QCamera2/HAL/QCameraMem.cpp
index 29bdc92..ea3a9af 100644
--- a/msmcobalt/QCamera2/HAL/QCameraMem.cpp
+++ b/msmcobalt/QCamera2/HAL/QCameraMem.cpp
@@ -1953,6 +1953,17 @@
 {
     int32_t err = NO_ERROR;
 
+    if ((mWindow == NULL) || (index >= MM_CAMERA_MAX_NUM_FRAMES))
+    {
+        LOGE("buffer index is invalid");
+        return INVALID_OPERATION;
+    }
+    else if(mBufferHandle[index] == NULL)
+    {
+        LOGE("buffer is NULL");
+        return INVALID_OPERATION;
+    }
+
     if (BUFFER_NOT_OWNED == mLocalFlag[index]) {
         LOGE("buffer to be enqueued is not owned");
         return INVALID_OPERATION;
diff --git a/msmcobalt/QCamera2/HAL/QCameraMuxer.cpp b/msmcobalt/QCamera2/HAL/QCameraMuxer.cpp
index 65c066f..ddbb268 100644
--- a/msmcobalt/QCamera2/HAL/QCameraMuxer.cpp
+++ b/msmcobalt/QCamera2/HAL/QCameraMuxer.cpp
@@ -576,7 +576,7 @@
                     LOGH("Related cam id: %d, server id: %d sync ON"
                             " related session_id %d",
                             cam->pId[i], cam->sId[i], sessionId);
-                    rc = hwi->bundleRelatedCameras(true, sessionId);
+                    rc = hwi->bundleRelatedCameras(true);
                     if (rc != NO_ERROR) {
                         LOGE("Error Bundling physical cameras !! ");
                         return rc;
@@ -590,7 +590,7 @@
                 LOGH("Related cam id: %d, server id: %d sync ON"
                         " related session_id %d",
                         cam->pId[i], cam->sId[i], sessionId);
-                rc = hwi->bundleRelatedCameras(true, sessionId);
+                rc = hwi->bundleRelatedCameras(true);
                 if (rc != NO_ERROR) {
                     LOGE("Error Bundling physical cameras !! ");
                     return rc;
@@ -1690,7 +1690,7 @@
                         LOGH("Related cam id: %d, server id: %d sync OFF"
                                 " related session_id %d",
                                 cam->pId[i], cam->sId[i], sessionId);
-                        rc = hwi->bundleRelatedCameras(false, sessionId);
+                        rc = hwi->bundleRelatedCameras(false);
                         if (rc != NO_ERROR) {
                             LOGE("Error Bundling physical cameras !! ");
                             break;
@@ -1704,7 +1704,7 @@
                     LOGH("Related cam id: %d, server id: %d sync OFF"
                             " related session_id %d",
                             cam->pId[i], cam->sId[i], sessionId);
-                    rc = hwi->bundleRelatedCameras(false, sessionId);
+                    rc = hwi->bundleRelatedCameras(false);
                     if (rc != NO_ERROR) {
                         LOGE("Error Bundling physical cameras !! ");
                         break;
diff --git a/msmcobalt/QCamera2/HAL/QCameraParameters.cpp b/msmcobalt/QCamera2/HAL/QCameraParameters.cpp
index 0c756c3..dfc1a31 100644
--- a/msmcobalt/QCamera2/HAL/QCameraParameters.cpp
+++ b/msmcobalt/QCamera2/HAL/QCameraParameters.cpp
@@ -863,6 +863,9 @@
 #define TOTAL_RAM_SIZE_512MB 536870912
 #define PARAM_MAP_SIZE(MAP) (sizeof(MAP)/sizeof(MAP[0]))
 
+// initialise to some default value
+uint32_t QCameraParameters::sessionId[] = {0};
+
 /*===========================================================================
  * FUNCTION   : isOEMFeat1PropEnabled
  *
@@ -898,8 +901,7 @@
       m_pParamHeap(NULL),
       m_pParamBuf(NULL),
       m_pParamBufAux(NULL),
-      m_pRelCamSyncHeap(NULL),
-      m_pRelCamSyncBuf(NULL),
+      m_pDualCamCmdHeap(NULL),
       m_bFrameSyncEnabled(false),
       mIsTypeVideo(IS_TYPE_NONE),
       mIsTypePreview(IS_TYPE_NONE),
@@ -1009,6 +1011,7 @@
     memset(&m_stillmore_config, 0, sizeof(cam_still_more_t));
     memset(&m_captureFrameConfig, 0, sizeof(cam_capture_frame_config_t));
     memset(&m_relCamSyncInfo, 0, sizeof(cam_sync_related_sensors_event_info_t));
+    memset(m_pDualCamCmdPtr, 0, sizeof(m_pDualCamCmdPtr));
     mTotalPPCount = 1;
     mZoomLevel = 0;
     mParmZoomLevel = 0;
@@ -1039,8 +1042,7 @@
     m_pParamHeap(NULL),
     m_pParamBuf(NULL),
     m_pParamBufAux(NULL),
-    m_pRelCamSyncHeap(NULL),
-    m_pRelCamSyncBuf(NULL),
+    m_pDualCamCmdHeap(NULL),
     m_bFrameSyncEnabled(false),
     m_bZslMode(false),
     m_bZslMode_new(false),
@@ -1119,6 +1121,7 @@
     memset(&m_hfrFpsRange, 0, sizeof(m_hfrFpsRange));
     memset(&m_stillmore_config, 0, sizeof(cam_still_more_t));
     memset(&m_relCamSyncInfo, 0, sizeof(cam_sync_related_sensors_event_info_t));
+    memset(m_pDualCamCmdPtr, 0, sizeof(m_pDualCamCmdPtr));
     mTotalPPCount = 0;
     mZoomLevel = 0;
     mParmZoomLevel = 0;
@@ -6184,21 +6187,25 @@
     pic_dim.width = 0;
     pic_dim.height = 0;
 
-    for(uint32_t i = 0;
-            i < (m_pCapability->picture_sizes_tbl_cnt - 1);
-            i++) {
-        if ((pic_dim.width * pic_dim.height) <
-                (int32_t)(m_pCapability->picture_sizes_tbl[i].width *
-                m_pCapability->picture_sizes_tbl[i].height)) {
-            pic_dim.width =
-                    m_pCapability->picture_sizes_tbl[i].width;
-            pic_dim.height =
-                    m_pCapability->picture_sizes_tbl[i].height;
+    if (m_pCapability->picture_sizes_tbl_cnt > 0 &&
+        m_pCapability->picture_sizes_tbl_cnt <= MAX_SIZES_CNT) {
+        for(uint32_t i = 0;
+                i < m_pCapability->picture_sizes_tbl_cnt; i++) {
+            if ((pic_dim.width * pic_dim.height) <
+                    (int32_t)(m_pCapability->picture_sizes_tbl[i].width *
+                    m_pCapability->picture_sizes_tbl[i].height)) {
+                pic_dim.width =
+                        m_pCapability->picture_sizes_tbl[i].width;
+                pic_dim.height =
+                        m_pCapability->picture_sizes_tbl[i].height;
+            }
         }
+        LOGD("max pic size = %d %d", pic_dim.width,
+                pic_dim.height);
+        setMaxPicSize(pic_dim);
+    } else {
+        LOGW("supported picture sizes cnt is 0 or exceeds max!!!");
     }
-    LOGD("max pic size = %d %d", pic_dim.width,
-            pic_dim.height);
-    setMaxPicSize(pic_dim);
 
     setManualCaptureMode(CAM_MANUAL_CAPTURE_TYPE_OFF);
     return rc;
@@ -6258,6 +6265,7 @@
         mm_camera_vtbl_t *mmOps, QCameraAdjustFPS *adjustFPS)
 {
     int32_t rc = NO_ERROR;
+    uint8_t buf_cnt = 1;
 
     m_pCapability = capabilities;
     m_pCamOpsTbl = mmOps;
@@ -6307,34 +6315,54 @@
         m_pParamBufAux = (parm_buffer_t*)DATA_PTR(m_pParamHeap, 1);
     }
 
-    // Check if it is dual camera mode
-    if(m_relCamSyncInfo.sync_control == CAM_SYNC_RELATED_SENSORS_ON) {
-        //Allocate related cam sync buffer
-        //this is needed for the payload that goes along with bundling cmd for related
-        //camera use cases
-        m_pRelCamSyncHeap = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE);
-        rc = m_pRelCamSyncHeap->allocate(1,
-                sizeof(cam_sync_related_sensors_event_info_t), NON_SECURE);
-        if(rc != OK) {
-            rc = NO_MEMORY;
-            LOGE("Failed to allocate Related cam sync Heap memory");
-            goto TRANS_INIT_ERROR3;
-        }
+    //Handle Dual camera cmd buffer
+    if (m_bDualCamera) {
+        buf_cnt = MM_CAMERA_MAX_CAM_CNT;
+    }
 
-        //Map memory for related cam sync buffer
-        rc = m_pCamOpsTbl->ops->map_buf(m_pCamOpsTbl->camera_handle,
-                CAM_MAPPING_BUF_TYPE_SYNC_RELATED_SENSORS_BUF,
-                m_pRelCamSyncHeap->getFd(0),
-                sizeof(cam_sync_related_sensors_event_info_t),
-                (cam_sync_related_sensors_event_info_t*)DATA_PTR(m_pRelCamSyncHeap,0));
+    m_pDualCamCmdHeap = new QCameraHeapMemory(QCAMERA_ION_USE_CACHE);
+    rc = m_pDualCamCmdHeap->allocate(buf_cnt,
+            sizeof(cam_dual_camera_cmd_info_t), NON_SECURE);
+    if(rc != OK) {
+        rc = NO_MEMORY;
+        LOGE("Failed to allocate dual cam Heap memory");
+        goto TRANS_INIT_ERROR3;
+    }
+
+    for (int i = 0; i < buf_cnt; i++) {
+        m_pDualCamCmdPtr[i] = (cam_dual_camera_cmd_info_t *)
+                DATA_PTR(m_pDualCamCmdHeap, i);
+    }
+
+    //Map memory for related cam sync buffer
+    rc = m_pCamOpsTbl->ops->map_buf(
+            get_main_camera_handle(m_pCamOpsTbl->camera_handle),
+            CAM_MAPPING_BUF_TYPE_DUAL_CAM_CMD_BUF,
+            m_pDualCamCmdHeap->getFd(0),
+            sizeof(cam_dual_camera_cmd_info_t),
+            m_pDualCamCmdPtr[0]);
+    if(rc < 0) {
+        LOGE("failed to map Related cam sync buffer");
+        rc = FAILED_TRANSACTION;
+        goto TRANS_INIT_ERROR4;
+    }
+
+    if (m_bDualCamera) {
+        rc = m_pCamOpsTbl->ops->map_buf(
+                get_aux_camera_handle(m_pCamOpsTbl->camera_handle),
+                CAM_MAPPING_BUF_TYPE_DUAL_CAM_CMD_BUF,
+                m_pDualCamCmdHeap->getFd(1),
+                sizeof(cam_dual_camera_cmd_info_t),
+                m_pDualCamCmdPtr[1]);
         if(rc < 0) {
             LOGE("failed to map Related cam sync buffer");
             rc = FAILED_TRANSACTION;
             goto TRANS_INIT_ERROR4;
         }
-        m_pRelCamSyncBuf =
-                (cam_sync_related_sensors_event_info_t*) DATA_PTR(m_pRelCamSyncHeap,0);
     }
+    rc = m_pCamOpsTbl->ops->get_session_id(m_pCamOpsTbl->camera_handle,
+            &sessionId[m_pCapability->camera_index]);
+
     initDefaultParameters();
     mCommon.init(capabilities);
     m_bInited = true;
@@ -6342,11 +6370,11 @@
     goto TRANS_INIT_DONE;
 
 TRANS_INIT_ERROR4:
-    m_pRelCamSyncHeap->deallocate();
+    m_pDualCamCmdHeap->deallocate();
 
 TRANS_INIT_ERROR3:
-    delete m_pRelCamSyncHeap;
-    m_pRelCamSyncHeap = NULL;
+    delete m_pDualCamCmdHeap;
+    m_pDualCamCmdHeap = NULL;
 
 TRANS_INIT_ERROR2:
     m_pParamHeap->deallocate();
@@ -6393,19 +6421,22 @@
         m_pCamOpsTbl->ops->unmap_buf(
                              m_pCamOpsTbl->camera_handle,
                              CAM_MAPPING_BUF_TYPE_PARM_BUF);
-        if (m_relCamSyncInfo.sync_control == CAM_SYNC_RELATED_SENSORS_ON) {
+        m_pCamOpsTbl->ops->unmap_buf(
+                get_main_camera_handle(m_pCamOpsTbl->camera_handle),
+                CAM_MAPPING_BUF_TYPE_DUAL_CAM_CMD_BUF);
+        if (isDualCamera()) {
             m_pCamOpsTbl->ops->unmap_buf(
-                    m_pCamOpsTbl->camera_handle,
-                    CAM_MAPPING_BUF_TYPE_SYNC_RELATED_SENSORS_BUF);
+                    get_aux_camera_handle(m_pCamOpsTbl->camera_handle),
+                    CAM_MAPPING_BUF_TYPE_DUAL_CAM_CMD_BUF);
         }
     }
 
     m_pCapability = NULL;
-    if (NULL != m_pRelCamSyncHeap) {
-        m_pRelCamSyncHeap->deallocate();
-        delete m_pRelCamSyncHeap;
-        m_pRelCamSyncHeap = NULL;
-        m_pRelCamSyncBuf = NULL;
+    if (NULL != m_pDualCamCmdHeap) {
+        m_pDualCamCmdHeap->deallocate();
+        delete m_pDualCamCmdHeap;
+        m_pDualCamCmdHeap = NULL;
+        memset(m_pDualCamCmdPtr, 0, sizeof(m_pDualCamCmdPtr));
     }
 
     m_tempMap.clear();
@@ -10227,7 +10258,18 @@
         break;
     case CAM_STREAM_TYPE_OFFLINE_PROC:
         if (getQuadraCfa()) {
-            format = m_pCapability->quadra_cfa_format;
+            if (m_pCapability->color_arrangement == CAM_FILTER_ARRANGEMENT_BGGR) {
+                format = CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_BGGR;
+            } else if (m_pCapability->color_arrangement == CAM_FILTER_ARRANGEMENT_GBRG) {
+                format = CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GBRG;
+            } else if (m_pCapability->color_arrangement == CAM_FILTER_ARRANGEMENT_GRBG) {
+                format = CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_GRBG;
+            } else if (m_pCapability->color_arrangement == CAM_FILTER_ARRANGEMENT_RGGB) {
+                format = CAM_FORMAT_BAYER_IDEAL_RAW_PLAIN16_10BPP_RGGB;
+            } else {
+                LOGW("Unrecognized format set by sensor, setting default");
+                format = m_pCapability->quadra_cfa_format;
+            }
         }
         break;
     case CAM_STREAM_TYPE_METADATA:
@@ -12089,6 +12131,160 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : sendDualCamBundle
+ *
+ * DESCRIPTION: send trigger for bundling related camera sessions in the server
+ *
+ * PARAMETERS :
+ *   @sync_enable :indicates whether syncing is On or Off
+ *   @sessionid   :session id for other camera session
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *NOTE: This bundle info needs to called only once per session.
+ * Should be called after open and before start stream.
+ * Application can trigger this function to enable module SYNC in dual camera case
+ *==========================================================================*/
+int32_t QCameraParameters::setDualCamBundleInfo(bool enable_sync,
+        uint8_t bundle_cam_idx)
+{
+    int32_t rc = NO_ERROR;
+    cam_dual_camera_bundle_info_t bundle_info;
+    uint8_t num_cam = 0;
+    int32_t sync = 0;
+    uint32_t mode, type, role = 0;
+    cam_3a_sync_mode_t sync_3a_mode = CAM_3A_SYNC_FOLLOW;
+    char prop[PROPERTY_VALUE_MAX];
+    memset(prop, 0, sizeof(prop));
+
+    if(enable_sync) {
+        sync = (int32_t)CAM_SYNC_RELATED_SENSORS_ON;
+    } else {
+        sync = (int32_t)CAM_SYNC_RELATED_SENSORS_OFF;
+    }
+
+    property_get("persist.camera.stats.test.2outs", prop, "0");
+    sync_3a_mode = (atoi(prop) > 0) ? CAM_3A_SYNC_ALGO_CTRL : sync_3a_mode;
+
+    if (m_pCapability->position == CAM_POSITION_BACK_AUX) {
+        mode = CAM_MODE_SECONDARY;
+        type = CAM_TYPE_AUX;
+    } else {
+        mode = CAM_MODE_PRIMARY;
+        type = CAM_TYPE_MAIN;
+    }
+
+    if (m_pCapability->lens_type == CAM_LENS_WIDE) {
+        role = CAM_ROLE_WIDE;
+    } else if (m_pCapability->lens_type == CAM_LENS_TELE) {
+        role = CAM_ROLE_TELE;
+    }
+    bundle_info.sync_control =
+            (cam_sync_related_sensors_control_t)sync;
+    bundle_info.mode = (cam_sync_mode_t)mode;
+    bundle_info.type = (cam_sync_type_t)type;
+    bundle_info.cam_role = (cam_dual_camera_role_t)role;
+    bundle_info.related_sensor_session_id = sessionId[bundle_cam_idx];
+    num_cam++;
+
+    rc = sendDualCamCmd(CAM_DUAL_CAMERA_BUNDLE_INFO,
+            num_cam, &bundle_info);
+    return rc;
+}
+
+/*===========================================================================
+ * FUNCTION   : sendDualCamCmd
+ *
+ * DESCRIPTION: send dual camera related commands
+ *
+ * PARAMETERS :
+ *   @sync_enable        :indicates whether syncing is On or Off
+ *   @sessionid  :session id for other camera session
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *NOTE: This bundle info needs to called only once per session.
+ * Should be called after open and before start stream.
+ *==========================================================================*/
+int32_t QCameraParameters::sendDualCamCmd(cam_dual_camera_cmd_type type,
+        uint8_t num_cam, void *cmd_value)
+{
+    int32_t rc = NO_ERROR;
+    if (NULL == m_pCamOpsTbl) {
+        LOGE("Ops not initialized");
+        return NO_INIT;
+    }
+
+    if (cmd_value == NULL || num_cam > MM_CAMERA_MAX_CAM_CNT
+            || m_pDualCamCmdPtr[0] == NULL) {
+        LOGE("Invalid argument = %d, %p", num_cam, cmd_value);
+        return BAD_VALUE;
+    }
+
+    for (int i = 0; i < MM_CAMERA_MAX_CAM_CNT; i++) {
+        memset(m_pDualCamCmdPtr[i], 0,
+                sizeof(cam_dual_camera_cmd_info_t));
+    }
+
+    switch(type) {
+        case CAM_DUAL_CAMERA_BUNDLE_INFO: {
+            for (int i = 0; i < num_cam; i++) {
+                cam_dual_camera_bundle_info_t *info =
+                        (cam_dual_camera_bundle_info_t *)cmd_value;
+                m_pDualCamCmdPtr[i]->cmd_type = type;
+                memcpy(&m_pDualCamCmdPtr[i]->bundle_info,
+                        &info[i],
+                        sizeof(cam_dual_camera_bundle_info_t));
+                LOGH("SYNC CMD %d: cmd %d mode %d type %d session - %d", i,
+                        m_pDualCamCmdPtr[i]->cmd_type,
+                        m_pDualCamCmdPtr[i]->bundle_info.mode,
+                        m_pDualCamCmdPtr[i]->bundle_info.type,
+                        m_pDualCamCmdPtr[i]->bundle_info.related_sensor_session_id);
+            }
+        }
+        break;
+
+        case CAM_DUAL_CAMERA_LOW_POWER_MODE: {
+            for (int i = 0; i < num_cam; i++) {
+                cam_dual_camera_perf_control_t *info =
+                        (cam_dual_camera_perf_control_t *)cmd_value;
+                m_pDualCamCmdPtr[i]->cmd_type = type;
+                memcpy(&m_pDualCamCmdPtr[i]->value,
+                        &info[i],
+                        sizeof(cam_dual_camera_perf_control_t));
+                LOGH("LPM CMD %d: cmd %d LPM Enable - %d fps = %d", i,
+                        m_pDualCamCmdPtr[i]->cmd_type,
+                        m_pDualCamCmdPtr[i]->value.enable,
+                        m_pDualCamCmdPtr[i]->value.low_fps);
+            }
+        }
+        break;
+
+        case CAM_DUAL_CAMERA_MASTER_INFO: {
+            for (int i = 0; i < num_cam; i++) {
+                cam_dual_camera_master_info_t *info =
+                        (cam_dual_camera_master_info_t *)cmd_value;
+                m_pDualCamCmdPtr[i]->cmd_type = type;
+                memcpy(&m_pDualCamCmdPtr[i]->mode,
+                        &info[i],
+                        sizeof(cam_dual_camera_master_info_t));
+                LOGH("MASTER INFO CMD %d: cmd %d value %d", i,
+                        m_pDualCamCmdPtr[i]->cmd_type,
+                        m_pDualCamCmdPtr[i]->mode);
+            }
+        }
+        break;
+        default :
+        break;
+    }
+
+    rc = m_pCamOpsTbl->ops->set_dual_cam_cmd(m_pCamOpsTbl->camera_handle);
+    return rc;
+}
+
+/*===========================================================================
  * FUNCTION   : bundleRelatedCameras
  *
  * DESCRIPTION: send trigger for bundling related camera sessions in the server
@@ -12101,36 +12297,10 @@
  *              NO_ERROR  -- success
  *              none-zero failure code
  *==========================================================================*/
-int32_t QCameraParameters::bundleRelatedCameras(bool sync,
-        uint32_t sessionid)
+int32_t QCameraParameters::bundleRelatedCameras(bool sync)
 {
     int32_t rc = NO_ERROR;
-
-    if (NULL == m_pCamOpsTbl) {
-        LOGE("Ops not initialized");
-        return NO_INIT;
-    }
-
-    LOGD("Sending Bundling cmd sync %d, SessionId %d ",
-            sync, sessionid);
-
-    if(m_pRelCamSyncBuf) {
-        if(sync) {
-            m_pRelCamSyncBuf->sync_control = CAM_SYNC_RELATED_SENSORS_ON;
-        }
-        else {
-            m_pRelCamSyncBuf->sync_control = CAM_SYNC_RELATED_SENSORS_OFF;
-        }
-        m_pRelCamSyncBuf->mode = m_relCamSyncInfo.mode;
-        m_pRelCamSyncBuf->type = m_relCamSyncInfo.type;
-        m_pRelCamSyncBuf->related_sensor_session_id = sessionid;
-        rc = m_pCamOpsTbl->ops->sync_related_sensors(
-                m_pCamOpsTbl->camera_handle, m_pRelCamSyncBuf);
-    } else {
-        LOGE("Related Cam SyncBuffer not allocated", rc);
-        return NO_INIT;
-    }
-
+    setDualCamBundleInfo(sync, m_pCapability->camera_index);
     return rc;
 }
 
@@ -13119,6 +13289,34 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : setAuxParameter
+ *
+ * DESCRIPTION: Parameter only required for auxillary camera is set.
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *NOTE: We can use this function configure auxillary camera related parameters.
+ *==========================================================================*/
+int32_t QCameraParameters::setAuxParameter(uint32_t meta_id, void *value)
+{
+    int32_t rc = NO_ERROR;
+
+    switch (meta_id) {
+        case CAM_INTF_META_STREAM_INFO: {
+            cam_stream_size_info_t *info = (cam_stream_size_info_t *)value;
+            info->sync_type = CAM_TYPE_AUX;
+        }
+        break;
+        default :
+        break;
+    }
+    return rc;
+}
+
+/*===========================================================================
  * FUNCTION   : commitSetBatchAux
  *
  * DESCRIPTION: commit all Aux set parameters in the batch work to backend
@@ -13153,6 +13351,7 @@
                 param_length = getSizeofParam((cam_intf_parm_type_t)i);
                 if (param_length) {
                     memcpy(aux_param, main_param, getSizeofParam((cam_intf_parm_type_t)i));
+                    setAuxParameter(i, aux_param);
                     m_pParamBufAux->is_valid[i] = 1;
                 }
             }
@@ -14227,6 +14426,9 @@
         stream_config_info.num_streams++;
     }
 
+    //For dual camera.
+    stream_config_info.sync_type = CAM_TYPE_MAIN;
+
     for (uint32_t k = 0; k < stream_config_info.num_streams; k++) {
         LOGI("STREAM INFO : type %d, wxh: %d x %d, pp_mask: 0x%llx \
                 Format = %d, dt =%d cid =%d subformat =%d, is_type %d",
@@ -14242,6 +14444,42 @@
     }
 
     rc = sendStreamConfigInfo(stream_config_info);
+
+    if (rc == NO_ERROR && isDualCamera()) {
+        cam_3a_sync_mode_t sync_3a_mode = CAM_3A_SYNC_FOLLOW;
+        char prop[PROPERTY_VALUE_MAX];
+        memset(prop, 0, sizeof(prop));
+        cam_dual_camera_bundle_info_t bundle_info[MM_CAMERA_MAX_CAM_CNT];
+        uint8_t num_cam = 0;
+        uint32_t sessionID = 0;
+
+        property_get("persist.camera.stats.test.2outs", prop, "0");
+        sync_3a_mode = (atoi(prop) > 0) ? CAM_3A_SYNC_ALGO_CTRL : sync_3a_mode;
+
+        bundle_info[num_cam].sync_control = CAM_SYNC_RELATED_SENSORS_ON;
+        bundle_info[num_cam].type = CAM_TYPE_MAIN;
+        bundle_info[num_cam].mode = CAM_MODE_PRIMARY;
+        bundle_info[num_cam].cam_role = CAM_ROLE_WIDE;
+        bundle_info[num_cam].sync_3a_mode = sync_3a_mode;
+        m_pCamOpsTbl->ops->get_session_id(
+                get_aux_camera_handle(m_pCamOpsTbl->camera_handle),
+                &sessionID);
+        bundle_info[num_cam].related_sensor_session_id = sessionID;
+        num_cam++;
+        bundle_info[num_cam].sync_control = CAM_SYNC_RELATED_SENSORS_ON;
+        bundle_info[num_cam].type = CAM_TYPE_AUX;
+        bundle_info[num_cam].mode = CAM_MODE_SECONDARY;
+        bundle_info[num_cam].cam_role = CAM_ROLE_TELE;
+        bundle_info[num_cam].sync_3a_mode = sync_3a_mode;
+        m_pCamOpsTbl->ops->get_session_id(
+                get_main_camera_handle(m_pCamOpsTbl->camera_handle),
+                &sessionID);
+        bundle_info[num_cam].related_sensor_session_id = sessionID;
+        num_cam++;
+        rc = sendDualCamCmd(CAM_DUAL_CAMERA_BUNDLE_INFO,
+                num_cam, &bundle_info[0]);
+    }
+
     return rc;
 }
 
@@ -15827,49 +16065,95 @@
 }
 
 /*===========================================================================
- * FUNCTION   : setCameraControls
+ * FUNCTION   : setSwitchCamera
  *
- * DESCRIPTION: activate or deactive camera's
+ * DESCRIPTION: Trigger event to inform about camera role switch
  *
- * PARAMETERS : bool dual camera value
+ * PARAMETERS :
+ *         @controls : Flag with camera bit field set in case of dual camera
  *
  * RETURN     : NO_ERROR  -- success
  *              none-zero failure code
  *==========================================================================*/
-int32_t QCameraParameters::setCameraControls(int32_t controls, bool initCommit)
+int32_t QCameraParameters::setSwitchCamera()
+{
+    int32_t rc = NO_ERROR;
+
+    if (mActiveState != MM_CAMERA_DUAL_CAM) {
+        LOGW("Both cameras are not active. Cannot switch");
+        return rc;
+    }
+
+    cam_dual_camera_master_info_t camState[MM_CAMERA_MAX_CAM_CNT];
+    uint8_t num_cam = 0;
+
+    if (mActiveCamera == MM_CAMERA_TYPE_MAIN) {
+        camState[0].mode = CAM_MODE_SECONDARY;
+        camState[1].mode = CAM_MODE_PRIMARY;
+        mActiveCamera = MM_CAMERA_TYPE_AUX;
+    } else if (mActiveCamera == MM_CAMERA_TYPE_AUX) {
+        camState[0].mode = CAM_MODE_PRIMARY;
+        camState[1].mode = CAM_MODE_SECONDARY;
+        mActiveCamera = MM_CAMERA_TYPE_MAIN;
+    } else {
+        LOGW("Invalid state");
+        return rc;
+    }
+
+    num_cam = MM_CAMERA_MAX_CAM_CNT;
+    rc = sendDualCamCmd(CAM_DUAL_CAMERA_MASTER_INFO,
+              num_cam, &camState[0]);
+    return rc;
+}
+
+/*===========================================================================
+ * FUNCTION   : setCameraControls
+ *
+ * DESCRIPTION: activate or deactive camera's
+ *
+ * PARAMETERS :
+ *         @controls : Flag with camera bit field set in case of dual camera
+ *
+ * RETURN     : NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraParameters::setCameraControls(int32_t state)
 {
     int32_t rc = NO_ERROR;
     int32_t cameraControl[MM_CAMERA_MAX_CAM_CNT] = {0};
+    char prop[PROPERTY_VALUE_MAX];
+    int value = 0;
 
-    if (initCommit) {
-        if (initBatchUpdate() < 0) {
-            LOGE("Failed to initialize group update table");
-            return FAILED_TRANSACTION;
-        }
-    }
-
-    if (controls & MM_CAMERA_TYPE_MAIN) {
+    if (state & MM_CAMERA_TYPE_MAIN) {
         cameraControl[0] = 1;
     } else {
         cameraControl[0] = 0;
     }
-    if (controls & MM_CAMERA_TYPE_AUX) {
+    if (state & MM_CAMERA_TYPE_AUX) {
         cameraControl[1] = 1;
     } else {
         cameraControl[1] = 0;
     }
-    if (ADD_SET_PARAM_ENTRY_TO_BATCH(m_pParamBuf, CAM_INTF_PARM_SUSPEND_RESUME_CAMERAS,
-            *cameraControl)) {
-        LOGE("Failed to instant aec value");
-        return BAD_VALUE;
-    }
 
-    if (initCommit) {
-        rc = commitSetBatch();
-        if (NO_ERROR != rc) {
-            LOGE("Failed to instant aec value");
-            return rc;
-        }
+    cam_dual_camera_perf_control_t perf_value[MM_CAMERA_MAX_CAM_CNT];
+    uint8_t num_cam = 0;
+
+    property_get("persist.dualcam.lpm.fps", prop, "0");
+    value = atoi(prop);
+
+    perf_value[num_cam].low_fps = value;
+    perf_value[num_cam].enable = cameraControl[0] ? 0 : 1;
+    num_cam++;
+    perf_value[num_cam].low_fps = value;
+    perf_value[num_cam].enable = cameraControl[1] ? 0 : 1;
+    num_cam++;
+
+    rc = sendDualCamCmd(CAM_DUAL_CAMERA_LOW_POWER_MODE,
+          num_cam, &perf_value[0]);
+    mActiveState = state;
+
+    if (state != MM_CAMERA_DUAL_CAM) {
+        mActiveCamera = state;
     }
 
 #ifdef DUAL_CAM_TEST //Temporary macro. Added to simulate B+B snapshot. Will be removed
@@ -15880,7 +16164,7 @@
     }
 #endif
 
-    return NO_ERROR;
+    return rc;
 }
 
 }; // namespace qcamera
diff --git a/msmcobalt/QCamera2/HAL/QCameraParameters.h b/msmcobalt/QCamera2/HAL/QCameraParameters.h
index f873f51..75ae5c5 100644
--- a/msmcobalt/QCamera2/HAL/QCameraParameters.h
+++ b/msmcobalt/QCamera2/HAL/QCameraParameters.h
@@ -846,6 +846,10 @@
     bool getLowLightCapture() { return m_LLCaptureEnabled; };
 
     /* Dual camera specific */
+    int32_t sendDualCamCmd(cam_dual_camera_cmd_type type,
+            uint8_t num_cam, void *info);
+    int32_t setDualCamBundleInfo(bool enable_sync,
+            uint8_t bundle_cam_idx);
     bool getDcrf() { return m_bDcrfEnabled; }
     int32_t setRelatedCamSyncInfo(
             cam_sync_related_sensors_event_info_t* info);
@@ -855,7 +859,7 @@
     bool isFrameSyncEnabled(void);
     int32_t getRelatedCamCalibration(
             cam_related_system_calibration_data_t* calib);
-    int32_t bundleRelatedCameras(bool sync, uint32_t sessionid);
+    int32_t bundleRelatedCameras(bool sync);
     uint8_t fdModeInVideo();
     bool isOEMFeatEnabled() { return m_bOEMFeatEnabled; }
 
@@ -881,7 +885,8 @@
 
     int32_t SetDualCamera(bool value);
     bool isDualCamera() {return m_bDualCamera;};
-    int32_t setCameraControls(int32_t controls, bool initCommit= true);
+    int32_t setCameraControls(int32_t controls);
+    int32_t setSwitchCamera();
 private:
     int32_t setPreviewSize(const QCameraParameters& );
     int32_t setVideoSize(const QCameraParameters& );
@@ -1079,6 +1084,7 @@
     int32_t commitGetBatch();
     int32_t commitSetBatchAux();
     int32_t commitGetBatchAux();
+    int32_t setAuxParameter(uint32_t meta_id, void *value);
 
     void * getPointerofParam(cam_intf_parm_type_t meta_id,
             metadata_buffer_t* metadata);
@@ -1126,6 +1132,9 @@
     static const QCameraMap<int> STILL_MORE_MODES_MAP[];
     static const QCameraMap<int> NOISE_REDUCTION_MODES_MAP[];
 
+    /*Common for all objects*/
+    static uint32_t sessionId[MM_CAMERA_MAX_NUM_SENSORS];
+
     QCameraReprocScaleParam m_reprocScaleParam;
     QCameraCommon           mCommon;
 
@@ -1135,9 +1144,8 @@
     parm_buffer_t     *m_pParamBuf;  // ptr to param buf in m_pParamHeap
     parm_buffer_t     *m_pParamBufAux;  // ptr to Aux param buf in m_pParamHeap
     /* heap for mapping dual cam event info */
-    QCameraHeapMemory *m_pRelCamSyncHeap;
-    /* ptr to sync buffer in m_pRelCamSyncHeap */
-    cam_sync_related_sensors_event_info_t *m_pRelCamSyncBuf;
+    QCameraHeapMemory *m_pDualCamCmdHeap;
+    cam_dual_camera_cmd_info_t *m_pDualCamCmdPtr[MM_CAMERA_MAX_CAM_CNT];
     cam_sync_related_sensors_event_info_t m_relCamSyncInfo;
     bool m_bFrameSyncEnabled;
     cam_is_type_t mIsTypeVideo;
@@ -1252,6 +1260,8 @@
     uint8_t mAecSkipDisplayFrameBound;
     bool m_bQuadraCfa;
     bool m_bDualCamera;
+    uint32_t mActiveState;
+    uint32_t mActiveCamera;
 };
 
 }; // namespace qcamera
diff --git a/msmcobalt/QCamera2/HAL/QCameraParametersIntf.cpp b/msmcobalt/QCamera2/HAL/QCameraParametersIntf.cpp
index 992cdf2..ecefd1a 100644
--- a/msmcobalt/QCamera2/HAL/QCameraParametersIntf.cpp
+++ b/msmcobalt/QCamera2/HAL/QCameraParametersIntf.cpp
@@ -1361,11 +1361,11 @@
     return mImpl->getRelatedCamCalibration(calib);
 }
 
-int32_t QCameraParametersIntf::bundleRelatedCameras(bool sync, uint32_t sessionid)
+int32_t QCameraParametersIntf::bundleRelatedCameras(bool sync)
 {
     Mutex::Autolock lock(mLock);
     CHECK_PARAM_INTF(mImpl);
-    return mImpl->bundleRelatedCameras(sync, sessionid);
+    return mImpl->bundleRelatedCameras(sync);
 }
 
 uint8_t QCameraParametersIntf::fdModeInVideo()
@@ -1455,11 +1455,18 @@
     return mImpl->SetDualCamera(value);
 }
 
-int32_t QCameraParametersIntf::setCameraControls(int32_t controls, bool initCommit)
+int32_t QCameraParametersIntf::setCameraControls(int32_t controls)
 {
     Mutex::Autolock lock(mLock);
     CHECK_PARAM_INTF(mImpl);
-    return mImpl->setCameraControls(controls, initCommit);
+    return mImpl->setCameraControls(controls);
+}
+
+int32_t QCameraParametersIntf::setSwitchCamera()
+{
+    Mutex::Autolock lock(mLock);
+    CHECK_PARAM_INTF(mImpl);
+    return mImpl->setSwitchCamera();
 }
 
 }; // namespace qcamera
diff --git a/msmcobalt/QCamera2/HAL/QCameraParametersIntf.h b/msmcobalt/QCamera2/HAL/QCameraParametersIntf.h
index 9efa263..99e1467 100644
--- a/msmcobalt/QCamera2/HAL/QCameraParametersIntf.h
+++ b/msmcobalt/QCamera2/HAL/QCameraParametersIntf.h
@@ -288,7 +288,7 @@
     bool isFrameSyncEnabled(void);
     int32_t getRelatedCamCalibration(
             cam_related_system_calibration_data_t* calib);
-    int32_t bundleRelatedCameras(bool sync, uint32_t sessionid);
+    int32_t bundleRelatedCameras(bool sync);
     uint8_t fdModeInVideo();
     bool isOEMFeatEnabled();
 
@@ -309,7 +309,8 @@
         cam_analysis_info_t *pAnalysisInfo);
     int32_t updateDtVc(int32_t *dt, int32_t *vc);
     int32_t SetDualCamera(bool value);
-    int32_t setCameraControls(int32_t controls, bool initCommit = true);
+    int32_t setCameraControls(int32_t controls);
+    int32_t setSwitchCamera();
 
 private:
     QCameraParameters *mImpl;
diff --git a/msmcobalt/QCamera2/HAL/QCameraPostProc.cpp b/msmcobalt/QCamera2/HAL/QCameraPostProc.cpp
index 1119c42..753021d 100644
--- a/msmcobalt/QCamera2/HAL/QCameraPostProc.cpp
+++ b/msmcobalt/QCamera2/HAL/QCameraPostProc.cpp
@@ -2157,6 +2157,8 @@
         cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
         cbArg.data = mem;
         cbArg.index = 0;
+        // Data callback, set read/write flags
+        main_frame->cache_flags |= CPU_HAS_READ;
         m_parent->m_cbNotifier.notifyCallback(cbArg);
     }
     if (NULL != m_parent->mNotifyCb &&
@@ -2530,6 +2532,13 @@
         jpg_job.encode_job.multi_image_info.is_primary = FALSE;
         jpg_job.encode_job.multi_image_info.num_of_images = 1;
     }
+    //Do Cache ops before sending to encode
+    if (main_frame != NULL) {
+        main_stream->handleCacheOps(main_frame);
+    }
+    if (thumb_frame != NULL) {
+        thumb_stream->handleCacheOps(thumb_frame);
+    }
 
     LOGI("[KPI Perf] : PROFILE_JPEG_JOB_START");
     ret = mJpegHandle.start_job(&jpg_job, &jobId);
@@ -2652,6 +2661,7 @@
             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE;
             cbArg.data = raw_mem;
             cbArg.index = 0;
+            frame->cache_flags |= CPU_HAS_READ;
             m_parent->m_cbNotifier.notifyCallback(cbArg);
         }
         if (NULL != m_parent->mNotifyCb &&
@@ -2662,6 +2672,7 @@
             cbArg.msg_type = CAMERA_MSG_RAW_IMAGE_NOTIFY;
             cbArg.ext1 = 0;
             cbArg.ext2 = 0;
+            frame->cache_flags |= CPU_HAS_READ;
             m_parent->m_cbNotifier.notifyCallback(cbArg);
         }
 
diff --git a/msmcobalt/QCamera2/HAL/QCameraStream.cpp b/msmcobalt/QCamera2/HAL/QCameraStream.cpp
index ad8a945..adb3e02 100644
--- a/msmcobalt/QCamera2/HAL/QCameraStream.cpp
+++ b/msmcobalt/QCamera2/HAL/QCameraStream.cpp
@@ -262,6 +262,44 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : clean_buf
+ *
+ * DESCRIPTION: static function entry to clean a specific stream buffer
+ *
+ * PARAMETERS :
+ *   @index      : index of the stream buffer to clean 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::clean_buf(uint32_t index, void *user_data)
+{
+    QCameraStream *stream = reinterpret_cast<QCameraStream *>(user_data);
+    if (!stream) {
+        LOGE("invalid stream pointer");
+        return NO_MEMORY;
+    }
+
+    if (stream->mStreamInfo->is_secure == SECURE){
+        return 0;
+    }
+
+    if (stream->mStreamInfo->streaming_mode == CAM_STREAMING_MODE_BATCH) {
+        for (int i = 0; i < stream->mBufDefs[index].user_buf.bufs_used; i++) {
+            uint32_t buf_idx = stream->mBufDefs[index].user_buf.buf_idx[i];
+            stream->cleanBuf(buf_idx);
+        }
+    } else {
+        return stream->cleanBuf(index);
+    }
+
+    return 0;
+}
+
+
+/*===========================================================================
  * FUNCTION   : set_config_ops
  *
  * DESCRIPTION: static function update mm-interface ops functions
@@ -354,6 +392,7 @@
     }
     mMemVtbl.invalidate_buf = invalidate_buf;
     mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
+    mMemVtbl.clean_buf = clean_buf;
     mMemVtbl.set_config_ops = set_config_ops;
     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
     memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
@@ -818,8 +857,9 @@
                 &streamInfo->buf_planes);
         break;
     case CAM_STREAM_TYPE_POSTVIEW:
-        rc = mm_stream_calc_offset_post_view(streamInfo->fmt,
+        rc = mm_stream_calc_offset_post_view(streamInfo,
                 &dim,
+                &mPaddingInfo,
                 &streamInfo->buf_planes);
         break;
     case CAM_STREAM_TYPE_SNAPSHOT:
@@ -2250,6 +2290,27 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : cleanBuf
+ *
+ * DESCRIPTION: clean a specific stream buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer to clean
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::cleanBuf(uint32_t index)
+{
+    if (mStreamBufs == NULL) {
+        LOGE("Invalid Operation");
+        return INVALID_OPERATION;
+    }
+    return mStreamBufs->cleanCache(index);
+}
+
+/*===========================================================================
  * FUNCTION   : isTypeOf
  *
  * DESCRIPTION: helper function to determine if the stream is of the queried type
@@ -2876,5 +2937,58 @@
     return ret;
 }
 
+/*===========================================================================
+ * FUNCTION   : handleCacheOps
+ *
+ * DESCRIPTION: handle cache ops for this stream buffer
+ *
+ * PARAMETERS :
+       @buf   : stream buffer
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              non-zero failure code
+ *==========================================================================*/
+int32_t QCameraStream::handleCacheOps(mm_camera_buf_def_t* buf)
+{
+    int32_t rc = 0;
+    if( !buf) {
+        LOGE("Error!! buf_info: %p", buf);
+        rc = -1;
+        return rc;
+    }
+    if ((mMemVtbl.clean_invalidate_buf  == NULL) ||
+            (mMemVtbl.invalidate_buf  == NULL) ||
+            (mMemVtbl.clean_buf  == NULL)) {
+        LOGI("Clean/Invalidate cache ops not supported");
+        rc = -1;
+        return rc;
+    }
+
+    LOGH("[CACHE_OPS] Stream type: %d buf index: %d cache ops flags: 0x%x",
+            buf->stream_type, buf->buf_idx, buf->cache_flags);
+
+    if ((buf->cache_flags & CPU_HAS_READ_WRITTEN) ==
+        CPU_HAS_READ_WRITTEN) {
+        rc = mMemVtbl.clean_invalidate_buf(
+                buf->buf_idx, mMemVtbl.user_data);
+    } else if ((buf->cache_flags & CPU_HAS_READ) ==
+        CPU_HAS_READ) {
+        rc = mMemVtbl.invalidate_buf(
+                buf->buf_idx, mMemVtbl.user_data);
+    } else if ((buf->cache_flags & CPU_HAS_WRITTEN) ==
+        CPU_HAS_WRITTEN) {
+        rc = mMemVtbl.clean_buf(
+                buf->buf_idx, mMemVtbl.user_data);
+    }
+    if (rc != 0) {
+        LOGW("Warning!! Clean/Invalidate cache failed on buffer index: %d",
+                buf->buf_idx);
+    }
+    // Reset buffer cache flags after cache ops
+    buf->cache_flags = 0;
+    return rc;
+}
+
 
 }; // namespace qcamera
diff --git a/msmcobalt/QCamera2/HAL/QCameraStream.h b/msmcobalt/QCamera2/HAL/QCameraStream.h
index ed7b1d1..ea65112 100644
--- a/msmcobalt/QCamera2/HAL/QCameraStream.h
+++ b/msmcobalt/QCamera2/HAL/QCameraStream.h
@@ -153,6 +153,7 @@
         uint8_t buf_index[CAMERA_MAX_CONSUMER_BATCH_BUFFER_SIZE];
     } MetaMemory;
     MetaMemory mStreamMetaMemory[CAMERA_MIN_VIDEO_BATCH_BUFFERS];
+    int32_t handleCacheOps(mm_camera_buf_def_t* buf);
 
 private:
     uint32_t mCamHandle;
@@ -225,6 +226,7 @@
 
     static int32_t invalidate_buf(uint32_t index, void *user_data);
     static int32_t clean_invalidate_buf(uint32_t index, void *user_data);
+    static int32_t clean_buf(uint32_t index, void *user_data);
 
     static int32_t backgroundAllocate(void* data);
     static int32_t backgroundMap(void* data);
@@ -251,6 +253,7 @@
 
     int32_t invalidateBuf(uint32_t index);
     int32_t cleanInvalidateBuf(uint32_t index);
+    int32_t cleanBuf(uint32_t index);
     int32_t calcOffset(cam_stream_info_t *streamInfo);
     int32_t unmapStreamInfoBuf();
     int32_t releaseStreamInfoBuf();
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3Channel.cpp b/msmcobalt/QCamera2/HAL3/QCamera3Channel.cpp
index 1b02b86..2aa70b2 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3Channel.cpp
+++ b/msmcobalt/QCamera2/HAL3/QCamera3Channel.cpp
@@ -372,11 +372,12 @@
     memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
     param.type = CAM_STREAM_PARAM_TYPE_SET_BUNDLE_INFO;
     param.bundleInfo = bundleInfo;
-    rc = mStreams[0]->setParameter(param);
-    if (rc != NO_ERROR) {
-        LOGE("stream setParameter for set bundle failed");
+    if (m_numStreams > 0 && mStreams[0]) {
+        rc = mStreams[0]->setParameter(param);
+        if (rc != NO_ERROR) {
+            LOGE("stream setParameter for set bundle failed");
+        }
     }
-
     return rc;
 }
 
@@ -575,6 +576,7 @@
                     }
                     LOGH("written number of bytes %ld\n", written_len);
                     mDumpFrmCnt++;
+                    frame->cache_flags |= CPU_HAS_READ;
                     close(file_fd);
                 } else {
                     LOGE("failed to open file to dump image");
@@ -2135,6 +2137,7 @@
        if (file_fd >= 0) {
           ssize_t written_len = write(file_fd, frame->buffer, frame->frame_len);
           LOGD("written number of bytes %zd", written_len);
+          frame->cache_flags |= CPU_HAS_READ;
           close(file_fd);
        } else {
           LOGE("failed to open file to dump image");
@@ -2348,6 +2351,7 @@
                 ssize_t written_len =
                         write(file_fd, frame->buffer, offset.frame_len);
                 LOGD("written number of bytes %zd", written_len);
+                frame->cache_flags |= CPU_HAS_READ;
                 close(file_fd);
             } else {
                 LOGE("failed to open file to dump image");
@@ -4493,6 +4497,12 @@
        mOfflineBuffersIndex = -1;
     }
     uint32_t buf_idx = (uint32_t)(mOfflineBuffersIndex + 1);
+
+    //Do cache ops before sending for reprocess
+    if (mMemory != NULL) {
+        mMemory->cleanInvalidateCache(buf_idx);
+    }
+
     rc = pStream->mapBuf(
             CAM_MAPPING_BUF_TYPE_OFFLINE_INPUT_BUF,
             buf_idx, -1,
@@ -4613,6 +4623,11 @@
                                  buf_idx, -1,
                                  buf_fd, buffer, buf_length);
 
+        //Do cache ops before sending for reprocess
+        if (mMemory != NULL) {
+            mMemory->cleanInvalidateCache(buf_idx);
+        }
+
         if (rc == NO_ERROR) {
             cam_stream_parm_buffer_t param;
             memset(&param, 0, sizeof(cam_stream_parm_buffer_t));
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3HWI.cpp b/msmcobalt/QCamera2/HAL3/QCamera3HWI.cpp
index db53b59..3438b62 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/msmcobalt/QCamera2/HAL3/QCamera3HWI.cpp
@@ -325,6 +325,13 @@
     { 480, CAM_HFR_MODE_480FPS},
 };
 
+const QCamera3HardwareInterface::QCameraMap<
+        qcamera3_ext_instant_aec_mode_t,
+        cam_aec_convergence_type> QCamera3HardwareInterface::INSTANT_AEC_MODES_MAP[] = {
+    { QCAMERA3_INSTANT_AEC_NORMAL_CONVERGENCE, CAM_AEC_NORMAL_CONVERGENCE},
+    { QCAMERA3_INSTANT_AEC_AGGRESSIVE_CONVERGENCE, CAM_AEC_AGGRESSIVE_CONVERGENCE},
+    { QCAMERA3_INSTANT_AEC_FAST_CONVERGENCE, CAM_AEC_FAST_CONVERGENCE},
+};
 camera3_device_ops_t QCamera3HardwareInterface::mCameraOps = {
     .initialize                         = QCamera3HardwareInterface::initialize,
     .configure_streams                  = QCamera3HardwareInterface::configure_streams,
@@ -393,6 +400,11 @@
       mNeedSensorRestart(false),
       mMinInFlightRequests(MIN_INFLIGHT_REQUESTS),
       mMaxInFlightRequests(MAX_INFLIGHT_REQUESTS),
+      mInstantAEC(false),
+      mResetInstantAEC(false),
+      mInstantAECSettledFrameNumber(0),
+      mAecSkipDisplayFrameBound(0),
+      mInstantAecFrameIdxCount(0),
       mLdafCalibExist(false),
       mPowerHintEnabled(false),
       mLastCustIntentFrmNum(-1),
@@ -400,8 +412,8 @@
       mIsDeviceLinked(false),
       mIsMainCamera(true),
       mLinkedCameraId(0),
-      m_pRelCamSyncHeap(NULL),
-      m_pRelCamSyncBuf(NULL)
+      m_pDualCamCmdHeap(NULL),
+      m_pDualCamCmdPtr(NULL)
 {
     getLogLevel();
     m_perfLock.lock_init();
@@ -797,8 +809,8 @@
         //Allocate related cam sync buffer
         //this is needed for the payload that goes along with bundling cmd for related
         //camera use cases
-        m_pRelCamSyncHeap = new QCamera3HeapMemory(1);
-        rc = m_pRelCamSyncHeap->allocate(sizeof(cam_sync_related_sensors_event_info_t));
+        m_pDualCamCmdHeap = new QCamera3HeapMemory(1);
+        rc = m_pDualCamCmdHeap->allocate(sizeof(cam_dual_camera_cmd_info_t));
         if(rc != OK) {
             rc = NO_MEMORY;
             LOGE("Dualcam: Failed to allocate Related cam sync Heap memory");
@@ -807,17 +819,17 @@
 
         //Map memory for related cam sync buffer
         rc = mCameraHandle->ops->map_buf(mCameraHandle->camera_handle,
-                CAM_MAPPING_BUF_TYPE_SYNC_RELATED_SENSORS_BUF,
-                m_pRelCamSyncHeap->getFd(0),
-                sizeof(cam_sync_related_sensors_event_info_t),
-                m_pRelCamSyncHeap->getPtr(0));
+                CAM_MAPPING_BUF_TYPE_DUAL_CAM_CMD_BUF,
+                m_pDualCamCmdHeap->getFd(0),
+                sizeof(cam_dual_camera_cmd_info_t),
+                m_pDualCamCmdHeap->getPtr(0));
         if(rc < 0) {
             LOGE("Dualcam: failed to map Related cam sync buffer");
             rc = FAILED_TRANSACTION;
             return NO_MEMORY;
         }
-        m_pRelCamSyncBuf =
-                (cam_sync_related_sensors_event_info_t*) DATA_PTR(m_pRelCamSyncHeap,0);
+        m_pDualCamCmdPtr =
+                (cam_dual_camera_cmd_info_t*) DATA_PTR(m_pDualCamCmdHeap,0);
     }
 
     LOGH("mCameraId=%d",mCameraId);
@@ -848,11 +860,11 @@
     // unmap memory for related cam sync buffer
     mCameraHandle->ops->unmap_buf(mCameraHandle->camera_handle,
             CAM_MAPPING_BUF_TYPE_SYNC_RELATED_SENSORS_BUF);
-    if (NULL != m_pRelCamSyncHeap) {
-        m_pRelCamSyncHeap->deallocate();
-        delete m_pRelCamSyncHeap;
-        m_pRelCamSyncHeap = NULL;
-        m_pRelCamSyncBuf = NULL;
+    if (NULL != m_pDualCamCmdHeap) {
+        m_pDualCamCmdHeap->deallocate();
+        delete m_pDualCamCmdHeap;
+        m_pDualCamCmdHeap = NULL;
+        m_pDualCamCmdPtr = NULL;
     }
 
     rc = mCameraHandle->ops->close_camera(mCameraHandle->camera_handle);
@@ -1495,6 +1507,13 @@
     uint32_t maxEisWidth = 0;
     uint32_t maxEisHeight = 0;
 
+    // Initialize all instant AEC related variables
+    mInstantAEC = false;
+    mResetInstantAEC = false;
+    mInstantAECSettledFrameNumber = 0;
+    mAecSkipDisplayFrameBound = 0;
+    mInstantAecFrameIdxCount = 0;
+
     memset(&mInputStreamInfo, 0, sizeof(mInputStreamInfo));
 
     size_t count = IS_TYPE_MAX;
@@ -2761,8 +2780,15 @@
      * corresponding frame numbers and time stamps */
     pthread_mutex_lock(&mMutex);
     if (urgent_frame_number_valid) {
-        first_urgent_frame_number =
-                mPendingBatchMap.valueFor(last_urgent_frame_number);
+        ssize_t idx = mPendingBatchMap.indexOfKey(last_urgent_frame_number);
+        if(idx < 0) {
+            LOGE("Invalid urgent frame number received: %d. Irrecoverable error",
+                last_urgent_frame_number);
+            mState = ERROR;
+            pthread_mutex_unlock(&mMutex);
+            return;
+        }
+        first_urgent_frame_number = mPendingBatchMap.valueAt(idx);
         urgentFrameNumDiff = last_urgent_frame_number + 1 -
                 first_urgent_frame_number;
 
@@ -2772,7 +2798,15 @@
     }
 
     if (frame_number_valid) {
-        first_frame_number = mPendingBatchMap.valueFor(last_frame_number);
+        ssize_t idx = mPendingBatchMap.indexOfKey(last_frame_number);
+        if(idx < 0) {
+            LOGE("Invalid frame number received: %d. Irrecoverable error",
+                last_frame_number);
+            mState = ERROR;
+            pthread_mutex_unlock(&mMutex);
+            return;
+        }
+        first_frame_number = mPendingBatchMap.valueAt(idx);
         frameNumDiff = last_frame_number + 1 -
                 first_frame_number;
         mPendingBatchMap.removeItem(last_frame_number);
@@ -2985,6 +3019,11 @@
                 mCallbackOps->process_capture_result(mCallbackOps, &result);
                 LOGD("urgent frame_number = %u, capture_time = %lld",
                       result.frame_number, capture_time);
+                if (mResetInstantAEC && mInstantAECSettledFrameNumber == 0) {
+                    // Instant AEC settled for this frame.
+                    LOGH("instant AEC settled for frame number %d", urgent_frame_number);
+                    mInstantAECSettledFrameNumber = urgent_frame_number;
+                }
                 free_camera_metadata((camera_metadata_t *)result.result);
                 break;
             }
@@ -3015,33 +3054,63 @@
 
         // Check whether any stream buffer corresponding to this is dropped or not
         // If dropped, then send the ERROR_BUFFER for the corresponding stream
-        if (p_cam_frame_drop) {
+        // OR check if instant AEC is enabled, then need to drop frames untill AEC is settled.
+        if (p_cam_frame_drop ||
+                (mInstantAEC || i->frame_number < mInstantAECSettledFrameNumber)) {
             /* Clear notify_msg structure */
             camera3_notify_msg_t notify_msg;
             memset(&notify_msg, 0, sizeof(camera3_notify_msg_t));
             for (List<RequestedBufferInfo>::iterator j = i->buffers.begin();
                     j != i->buffers.end(); j++) {
+                bool dropFrame = false;
                 QCamera3ProcessingChannel *channel = (QCamera3ProcessingChannel *)j->stream->priv;
                 uint32_t streamID = channel->getStreamID(channel->getStreamTypeMask());
-                for (uint32_t k = 0; k < p_cam_frame_drop->num_streams; k++) {
-                    if (streamID == p_cam_frame_drop->streamID[k]) {
-                        // Send Error notify to frameworks with CAMERA3_MSG_ERROR_BUFFER
+                if (p_cam_frame_drop) {
+                    for (uint32_t k = 0; k < p_cam_frame_drop->num_streams; k++) {
+                        if (streamID == p_cam_frame_drop->streamID[k]) {
+                            // Got the stream ID for drop frame.
+                            dropFrame = true;
+                            break;
+                        }
+                    }
+                } else {
+                    // This is instant AEC case.
+                    // For instant AEC drop the stream untill AEC is settled.
+                    dropFrame = true;
+                }
+                if (dropFrame) {
+                    // Send Error notify to frameworks with CAMERA3_MSG_ERROR_BUFFER
+                    if (p_cam_frame_drop) {
+                        // Treat msg as error for system buffer drops
                         LOGE("Start of reporting error frame#=%u, streamID=%u",
                                  i->frame_number, streamID);
-                        notify_msg.type = CAMERA3_MSG_ERROR;
-                        notify_msg.message.error.frame_number = i->frame_number;
-                        notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER ;
-                        notify_msg.message.error.error_stream = j->stream;
-                        mCallbackOps->notify(mCallbackOps, &notify_msg);
+                    } else {
+                        // For instant AEC, inform frame drop and frame number
+                        LOGH("Start of reporting error frame#=%u for instant AEC, streamID=%u, "
+                                "AEC settled frame number = %u",
+                                i->frame_number, streamID, mInstantAECSettledFrameNumber);
+                    }
+                    notify_msg.type = CAMERA3_MSG_ERROR;
+                    notify_msg.message.error.frame_number = i->frame_number;
+                    notify_msg.message.error.error_code = CAMERA3_MSG_ERROR_BUFFER ;
+                    notify_msg.message.error.error_stream = j->stream;
+                    mCallbackOps->notify(mCallbackOps, &notify_msg);
+                    if (p_cam_frame_drop) {
+                        // Treat msg as error for system buffer drops
                         LOGE("End of reporting error frame#=%u, streamID=%u",
                                 i->frame_number, streamID);
-                        PendingFrameDropInfo PendingFrameDrop;
-                        PendingFrameDrop.frame_number=i->frame_number;
-                        PendingFrameDrop.stream_ID = streamID;
-                        // Add the Frame drop info to mPendingFrameDropList
-                        mPendingFrameDropList.push_back(PendingFrameDrop);
-                   }
-                }
+                    } else {
+                        // For instant AEC, inform frame drop and frame number
+                        LOGH("End of reporting error frame#=%u for instant AEC, streamID=%u, "
+                                "AEC settled frame number = %u",
+                                i->frame_number, streamID, mInstantAECSettledFrameNumber);
+                    }
+                    PendingFrameDropInfo PendingFrameDrop;
+                    PendingFrameDrop.frame_number=i->frame_number;
+                    PendingFrameDrop.stream_ID = streamID;
+                    // Add the Frame drop info to mPendingFrameDropList
+                    mPendingFrameDropList.push_back(PendingFrameDrop);
+               }
             }
         }
 
@@ -3055,7 +3124,7 @@
                 /* this will be handled in handleInputBufferWithLock */
                 i++;
                 continue;
-            } else if (mBatchSize) {
+            } else {
 
                 mPendingLiveRequest--;
 
@@ -3064,14 +3133,6 @@
                 result.result = dummyMetadata.release();
 
                 notifyError(i->frame_number, CAMERA3_MSG_ERROR_RESULT);
-            } else {
-                LOGE("Fatal: Missing metadata buffer for frame number %d", i->frame_number);
-                if (free_and_bufdone_meta_buf) {
-                    mMetadataChannel->bufDone(metadata_buf);
-                    free(metadata_buf);
-                }
-                mState = ERROR;
-                goto done_metadata;
             }
         } else {
             mPendingLiveRequest--;
@@ -3570,7 +3631,13 @@
             ADD_SET_PARAM_ENTRY_TO_BATCH(mParameters, CAM_INTF_PARM_HAL_VERSION, hal_version);
             ADD_SET_PARAM_ENTRY_TO_BATCH(mParameters, CAM_INTF_META_CAPTURE_INTENT, captureIntent);
         }
-
+        if (mFirstConfiguration) {
+            // configure instant AEC
+            // Instant AEC is a session based parameter and it is needed only
+            // once per complete session after open camera.
+            // i.e. This is set only once for the first capture request, after open camera.
+            setInstantAEC(meta);
+        }
         uint8_t fwkVideoStabMode=0;
         if (meta.exists(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE)) {
             fwkVideoStabMode = meta.find(ANDROID_CONTROL_VIDEO_STABILIZATION_MODE).data.u8[0];
@@ -3845,6 +3912,9 @@
         // add bundle related cameras
         LOGH("%s: Dualcam: id =%d, mIsDeviceLinked=%d", __func__,mCameraId, mIsDeviceLinked);
         if (meta.exists(QCAMERA3_DUALCAM_LINK_ENABLE)) {
+            cam_dual_camera_bundle_info_t *m_pRelCamSyncBuf =
+                    &m_pDualCamCmdPtr->bundle_info;
+            m_pDualCamCmdPtr->cmd_type = CAM_DUAL_CAMERA_BUNDLE_INFO;
             if (mIsDeviceLinked)
                 m_pRelCamSyncBuf->sync_control = CAM_SYNC_RELATED_SENSORS_ON;
             else
@@ -3863,18 +3933,20 @@
                 m_pRelCamSyncBuf->mode = CAM_MODE_PRIMARY;
                 m_pRelCamSyncBuf->type = CAM_TYPE_MAIN;
                 m_pRelCamSyncBuf->sync_3a_mode = CAM_3A_SYNC_FOLLOW;
+                m_pRelCamSyncBuf->cam_role = CAM_ROLE_BAYER;
                 // related session id should be session id of linked session
                 m_pRelCamSyncBuf->related_sensor_session_id = sessionId[mLinkedCameraId];
             } else {
                 m_pRelCamSyncBuf->mode = CAM_MODE_SECONDARY;
                 m_pRelCamSyncBuf->type = CAM_TYPE_AUX;
                 m_pRelCamSyncBuf->sync_3a_mode = CAM_3A_SYNC_FOLLOW;
+                m_pRelCamSyncBuf->cam_role = CAM_ROLE_MONO;
                 m_pRelCamSyncBuf->related_sensor_session_id = sessionId[mLinkedCameraId];
             }
             pthread_mutex_unlock(&gCamLock);
 
-            rc = mCameraHandle->ops->sync_related_sensors(
-                    mCameraHandle->camera_handle, m_pRelCamSyncBuf);
+            rc = mCameraHandle->ops->set_dual_cam_cmd(
+                    mCameraHandle->camera_handle);
             if (rc < 0) {
                 LOGE("Dualcam: link failed");
                 pthread_mutex_unlock(&mMutex);
@@ -4095,6 +4167,11 @@
             mNeedSensorRestart = false;
             pthread_mutex_lock(&mMutex);
         }
+        if(mResetInstantAEC) {
+            ADD_SET_PARAM_ENTRY_TO_BATCH(mParameters,
+                    CAM_INTF_PARM_INSTANT_AEC, (uint8_t)CAM_AEC_NORMAL_CONVERGENCE);
+            mResetInstantAEC = false;
+        }
     } else {
 
         if (request->input_buffer->acquire_fence != -1) {
@@ -4439,6 +4516,9 @@
     rc = stopAllChannels();
     // unlink of dualcam
     if (mIsDeviceLinked) {
+        cam_dual_camera_bundle_info_t *m_pRelCamSyncBuf =
+                &m_pDualCamCmdPtr->bundle_info;
+        m_pDualCamCmdPtr->cmd_type = CAM_DUAL_CAMERA_BUNDLE_INFO;
         m_pRelCamSyncBuf->sync_control = CAM_SYNC_RELATED_SENSORS_OFF;
         pthread_mutex_lock(&gCamLock);
 
@@ -4456,8 +4536,8 @@
         }
         pthread_mutex_unlock(&gCamLock);
 
-        rc = mCameraHandle->ops->sync_related_sensors(
-                mCameraHandle->camera_handle, m_pRelCamSyncBuf);
+        rc = mCameraHandle->ops->set_dual_cam_cmd(
+                mCameraHandle->camera_handle);
         if (rc < 0) {
             LOGE("Dualcam: Unlink failed, but still proceed to close");
         }
@@ -4694,7 +4774,10 @@
                 camera3_stream_buffer_t *buffer, uint32_t frame_number, bool isInputBuffer)
 {
     if (metadata_buf) {
-        if (mBatchSize) {
+        pthread_mutex_lock(&mMutex);
+        uint8_t batchSize = mBatchSize;
+        pthread_mutex_unlock(&mMutex);
+        if (batchSize) {
             handleBatchMetadata(metadata_buf,
                     true /* free_and_bufdone_meta_buf */);
         } else { /* mBatchSize = 0 */
@@ -5442,6 +5525,11 @@
                 MAX_METADATA_PRIVATE_PAYLOAD_SIZE_IN_BYTES / sizeof(int32_t));
     }
 
+    IF_META_AVAILABLE(int32_t, meteringMode, CAM_INTF_PARM_AEC_ALGO_TYPE, metadata) {
+        camMetadata.update(QCAMERA3_EXPOSURE_METERING_MODE,
+                meteringMode, 1);
+    }
+
     if (metadata->is_tuning_params_valid) {
         uint8_t tuning_meta_data_blob[sizeof(tuning_params_t)];
         uint8_t *data = (uint8_t *)&tuning_meta_data_blob[0];
@@ -5819,6 +5907,12 @@
     camMetadata.update(QCAMERA3_HAL_PRIVATEDATA_REPROCESS_DATA_BLOB,
         (uint8_t *)&repro_info, sizeof(cam_reprocess_info_t));
 
+    // INSTANT AEC MODE
+    IF_META_AVAILABLE(uint8_t, instant_aec_mode,
+            CAM_INTF_PARM_INSTANT_AEC, metadata) {
+        camMetadata.update(QCAMERA3_INSTANT_AEC_MODE, instant_aec_mode, 1);
+    }
+
     /* In batch mode, cache the first metadata in the batch */
     if (mBatchSize && firstMetadataInBatch) {
         mCachedMetadata.clear();
@@ -6029,7 +6123,23 @@
               "flashMode:%d, aeMode:%u!!!",
                  redeye, flashMode, aeMode);
     }
-
+    if (mInstantAEC) {
+        // Increment frame Idx count untill a bound reached for instant AEC.
+        mInstantAecFrameIdxCount++;
+        IF_META_AVAILABLE(cam_3a_params_t, ae_params,
+                CAM_INTF_META_AEC_INFO, metadata) {
+            LOGH("ae_params->settled = %d",ae_params->settled);
+            // If AEC settled, or if number of frames reached bound value,
+            // should reset instant AEC.
+            if (ae_params->settled ||
+                    (mInstantAecFrameIdxCount > mAecSkipDisplayFrameBound)) {
+                LOGH("AEC settled or Frames reached instantAEC bound, resetting instantAEC");
+                mInstantAEC = false;
+                mResetInstantAEC = true;
+                mInstantAecFrameIdxCount = 0;
+            }
+        }
+    }
     resultMetadata = camMetadata.release();
     return resultMetadata;
 }
@@ -6556,6 +6666,7 @@
         goto failed_op;
     }
 
+    gCamCapability[cameraId]->camera_index = cameraId;
     if (is_dual_camera_by_idx(cameraId)) {
         handle = get_aux_camera_handle(cameraHandle->camera_handle);
         gCamCapability[cameraId]->aux_cam_cap =
@@ -7966,6 +8077,23 @@
                 avail_ir_modes, size);
     }
 
+    if (gCamCapability[cameraId]->supported_instant_aec_modes_cnt > 0) {
+        int32_t available_instant_aec_modes[CAM_AEC_CONVERGENCE_MAX];
+        size = 0;
+        count = CAM_AEC_CONVERGENCE_MAX;
+        count = MIN(gCamCapability[cameraId]->supported_instant_aec_modes_cnt, count);
+        for (size_t i = 0; i < count; i++) {
+            int val = lookupFwkName(INSTANT_AEC_MODES_MAP, METADATA_MAP_SIZE(INSTANT_AEC_MODES_MAP),
+                    gCamCapability[cameraId]->supported_instant_aec_modes[i]);
+            if (NAME_NOT_FOUND != val) {
+                available_instant_aec_modes[size] = (int32_t)val;
+                size++;
+            }
+        }
+        staticInfo.update(QCAMERA3_INSTANT_AEC_AVAILABLE_MODES,
+                available_instant_aec_modes, size);
+    }
+
     gStaticMetadata[cameraId] = staticInfo.release();
     return rc;
 }
@@ -8697,6 +8825,10 @@
     float default_awb_speed = 0;
     settings.update(QCAMERA3_AWB_CONVERGENCE_SPEED, &default_awb_speed, 1);
 
+    // Set instant AEC to normal convergence by default
+    int32_t instant_aec_mode = (int32_t)QCAMERA3_INSTANT_AEC_NORMAL_CONVERGENCE;
+    settings.update(QCAMERA3_INSTANT_AEC_MODE, &instant_aec_mode, 1);
+
     mDefaultMetadata[type] = settings.release();
 
     return mDefaultMetadata[type];
@@ -9864,6 +9996,15 @@
         }
     }
 
+    if (frame_settings.exists(QCAMERA3_EXPOSURE_METERING_MODE)) {
+        int32_t* exposure_metering_mode =
+                frame_settings.find(QCAMERA3_EXPOSURE_METERING_MODE).data.i32;
+        if (ADD_SET_PARAM_ENTRY_TO_BATCH(hal_metadata, CAM_INTF_PARM_AEC_ALGO_TYPE,
+                *exposure_metering_mode)) {
+            rc = BAD_VALUE;
+        }
+    }
+
     if (frame_settings.exists(ANDROID_SENSOR_TEST_PATTERN_MODE)) {
         int32_t fwk_testPatternMode =
                 frame_settings.find(ANDROID_SENSOR_TEST_PATTERN_MODE).data.i32[0];
@@ -9994,6 +10135,41 @@
         }
     }
 
+    // ISO/Exposure Priority
+    if (frame_settings.exists(QCAMERA3_USE_ISO_EXP_PRIORITY) &&
+        frame_settings.exists(QCAMERA3_SELECT_PRIORITY)) {
+        cam_priority_mode_t mode =
+                (cam_priority_mode_t)frame_settings.find(QCAMERA3_SELECT_PRIORITY).data.i32[0];
+        if((CAM_ISO_PRIORITY == mode) || (CAM_EXP_PRIORITY == mode)) {
+            cam_intf_parm_manual_3a_t use_iso_exp_pty;
+            use_iso_exp_pty.previewOnly = FALSE;
+            uint64_t* ptr = (uint64_t*)frame_settings.find(QCAMERA3_USE_ISO_EXP_PRIORITY).data.i64;
+            use_iso_exp_pty.value = *ptr;
+
+            if(CAM_ISO_PRIORITY == mode) {
+                if (ADD_SET_PARAM_ENTRY_TO_BATCH(hal_metadata, CAM_INTF_PARM_ISO,
+                        use_iso_exp_pty)) {
+                    rc = BAD_VALUE;
+                }
+            }
+            else {
+                if (ADD_SET_PARAM_ENTRY_TO_BATCH(hal_metadata, CAM_INTF_PARM_EXPOSURE_TIME,
+                        use_iso_exp_pty)) {
+                    rc = BAD_VALUE;
+                }
+            }
+        }
+    }
+
+    // Saturation
+    if (frame_settings.exists(QCAMERA3_USE_SATURATION)) {
+        int32_t* use_saturation =
+                frame_settings.find(QCAMERA3_USE_SATURATION).data.i32;
+        if (ADD_SET_PARAM_ENTRY_TO_BATCH(hal_metadata, CAM_INTF_PARM_SATURATION, *use_saturation)) {
+            rc = BAD_VALUE;
+        }
+    }
+
     // EV step
     if (ADD_SET_PARAM_ENTRY_TO_BATCH(hal_metadata, CAM_INTF_PARM_EV_STEP,
             gCamCapability[mCameraId]->exp_compensation_step)) {
@@ -11124,6 +11300,60 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : setInstantAEC
+ *
+ * DESCRIPTION: Set Instant AEC related params.
+ *
+ * PARAMETERS :
+ *      @meta: CameraMetadata reference
+ *
+ * RETURN     : NO_ERROR on success
+ *              Error codes on failure
+ *==========================================================================*/
+int32_t QCamera3HardwareInterface::setInstantAEC(const CameraMetadata &meta)
+{
+    int32_t rc = NO_ERROR;
+    uint8_t val = 0;
+    char prop[PROPERTY_VALUE_MAX];
+
+    // First try to configure instant AEC from framework metadata
+    if (meta.exists(QCAMERA3_INSTANT_AEC_MODE)) {
+        val = (uint8_t)meta.find(QCAMERA3_INSTANT_AEC_MODE).data.i32[0];
+    }
+
+    // If framework did not set this value, try to read from set prop.
+    if (val == 0) {
+        memset(prop, 0, sizeof(prop));
+        property_get("persist.camera.instant.aec", prop, "0");
+        val = (uint8_t)atoi(prop);
+    }
+
+    if ((val >= (uint8_t)CAM_AEC_NORMAL_CONVERGENCE) &&
+           ( val < (uint8_t)CAM_AEC_CONVERGENCE_MAX)) {
+        ADD_SET_PARAM_ENTRY_TO_BATCH(mParameters, CAM_INTF_PARM_INSTANT_AEC, val);
+        mInstantAEC = val;
+        mInstantAECSettledFrameNumber = 0;
+        mInstantAecFrameIdxCount = 0;
+        LOGH("instantAEC value set %d",val);
+        if (mInstantAEC) {
+            memset(prop, 0, sizeof(prop));
+            property_get("persist.camera.ae.instant.bound", prop, "10");
+            int32_t aec_frame_skip_cnt = atoi(prop);
+            if (aec_frame_skip_cnt >= 0) {
+                mAecSkipDisplayFrameBound = (uint8_t)aec_frame_skip_cnt;
+            } else {
+                LOGE("Invalid prop for aec frame bound %d", aec_frame_skip_cnt);
+                rc = BAD_VALUE;
+            }
+        }
+    } else {
+        LOGE("Bad instant aec value set %d", val);
+        rc = BAD_VALUE;
+    }
+    return rc;
+}
+
+/*===========================================================================
  * FUNCTION   : get_num_overall_buffers
  *
  * DESCRIPTION: Estimate number of pending buffers across all requests.
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3HWI.h b/msmcobalt/QCamera2/HAL3/QCamera3HWI.h
old mode 100755
new mode 100644
index 62fe6db..3f94858
--- a/msmcobalt/QCamera2/HAL3/QCamera3HWI.h
+++ b/msmcobalt/QCamera2/HAL3/QCamera3HWI.h
@@ -342,6 +342,7 @@
 
     static bool supportBurstCapture(uint32_t cameraId);
     int32_t setBundleInfo();
+    int32_t setInstantAEC(const CameraMetadata &meta);
 
     static void convertLandmarks(cam_face_landmarks_info_t face, int32_t* landmarks);
     static void setInvalidLandmarks(int32_t* landmarks);
@@ -487,7 +488,16 @@
     bool mNeedSensorRestart;
     uint32_t mMinInFlightRequests;
     uint32_t mMaxInFlightRequests;
-
+    // Param to trigger instant AEC.
+    bool mInstantAEC;
+    // Param to know when to reset AEC
+    bool mResetInstantAEC;
+    // Frame number, untill which we need to drop the frames.
+    uint32_t mInstantAECSettledFrameNumber;
+    // Max number of frames, that HAL will hold without displaying, for instant AEC mode.
+    uint8_t mAecSkipDisplayFrameBound;
+    // Counter to keep track of number of frames that took for AEC convergence.
+    uint8_t mInstantAecFrameIdxCount;
     /* sensor output size with current stream configuration */
     QCamera3CropRegionMapper mCropRegionMapper;
 
@@ -530,6 +540,8 @@
             cam_hfr_mode_t> HFR_MODE_MAP[];
     static const QCameraMap<camera_metadata_enum_android_ir_mode_t,
             cam_ir_mode_type_t> IR_MODES_MAP[];
+    static const QCameraMap<qcamera3_ext_instant_aec_mode_t,
+            cam_aec_convergence_type> INSTANT_AEC_MODES_MAP[];
     static const QCameraPropMap CDS_MAP[];
 
     pendingRequestIterator erasePendingRequest(pendingRequestIterator i);
@@ -543,8 +555,8 @@
     bool mIsDeviceLinked;
     bool mIsMainCamera;
     uint8_t mLinkedCameraId;
-    QCamera3HeapMemory *m_pRelCamSyncHeap;
-    cam_sync_related_sensors_event_info_t *m_pRelCamSyncBuf;
+    QCamera3HeapMemory *m_pDualCamCmdHeap;
+    cam_dual_camera_cmd_info_t *m_pDualCamCmdPtr;
     cam_sync_related_sensors_event_info_t m_relCamSyncInfo;
 
 };
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3PostProc.cpp b/msmcobalt/QCamera2/HAL3/QCamera3PostProc.cpp
index 84538c7..37c5701 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3PostProc.cpp
+++ b/msmcobalt/QCamera2/HAL3/QCamera3PostProc.cpp
@@ -1201,7 +1201,7 @@
         return BAD_VALUE;
     }
 
-    if ((NULL != jpeg_job_data->src_frame) && (NULL != jpeg_job_data->src_frame)) {
+    if ((NULL != jpeg_job_data->fwk_frame) && (NULL != jpeg_job_data->src_frame)) {
         LOGE("Unsupported case both framework and camera source buffers are invalid!");
         return BAD_VALUE;
     }
@@ -1280,6 +1280,14 @@
         mm_jpeg_encode_params_t encodeParam;
         memset(&encodeParam, 0, sizeof(mm_jpeg_encode_params_t));
         getFWKJpegEncodeConfig(encodeParam, recvd_frame, jpeg_settings);
+        QCamera3StreamMem *memObj = (QCamera3StreamMem *)(recvd_frame->input_buffer.mem_info);
+        if (NULL == memObj) {
+            LOGE("Memeory Obj of main frame is NULL");
+            return NO_MEMORY;
+        }
+        // clean and invalidate cache ops through mem obj of the frame
+        memObj->cleanInvalidateCache(recvd_frame->input_buffer.buf_idx);
+
         LOGH("#src bufs:%d # tmb bufs:%d #dst_bufs:%d",
                      encodeParam.num_src_bufs,encodeParam.num_tmb_bufs,encodeParam.num_dst_bufs);
         if (!needJpegExifRotation &&
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3Stream.cpp b/msmcobalt/QCamera2/HAL3/QCamera3Stream.cpp
index 9e8957f..da483f3 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3Stream.cpp
+++ b/msmcobalt/QCamera2/HAL3/QCamera3Stream.cpp
@@ -32,6 +32,7 @@
 // Camera dependencies
 #include "QCamera3HWI.h"
 #include "QCamera3Stream.h"
+#include <cutils/properties.h>
 
 extern "C" {
 #include "mm_camera_dbg.h"
@@ -218,6 +219,47 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : clean_buf
+ *
+ * DESCRIPTION: static function entry to clean  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 QCamera3Stream::clean_buf(uint32_t index, void *user_data)
+{
+    int32_t rc = NO_ERROR;
+
+    QCamera3Stream *stream = reinterpret_cast<QCamera3Stream *>(user_data);
+    if (!stream) {
+        LOGE("invalid stream pointer");
+        return NO_MEMORY;
+    }
+    if (stream->mBatchSize) {
+        int32_t retVal = NO_ERROR;
+        for (size_t i = 0;
+                i < stream->mBatchBufDefs[index].user_buf.bufs_used; i++) {
+            uint32_t buf_idx = stream->mBatchBufDefs[index].user_buf.buf_idx[i];
+            retVal = stream->cleanBuf(buf_idx);
+            if (NO_ERROR != retVal) {
+                LOGE("invalidateBuf failed for buf_idx: %d err: %d",
+                    buf_idx, retVal);
+            }
+            rc |= retVal;
+        }
+    } else {
+        rc = stream->cleanBuf(index);
+    }
+    return rc;
+}
+
+
+/*===========================================================================
  * FUNCTION   : QCamera3Stream
  *
  * DESCRIPTION: constructor of QCamera3Stream
@@ -263,6 +305,7 @@
     mMemVtbl.put_bufs = put_bufs;
     mMemVtbl.invalidate_buf = invalidate_buf;
     mMemVtbl.clean_invalidate_buf = clean_invalidate_buf;
+    mMemVtbl.clean_buf = clean_buf;
     mMemVtbl.set_config_ops = NULL;
     memset(&mFrameLenOffset, 0, sizeof(mFrameLenOffset));
     memcpy(&mPaddingInfo, paddingInfo, sizeof(cam_padding_info_t));
@@ -332,6 +375,8 @@
 {
     int32_t rc = OK;
     ssize_t bufSize = BAD_INDEX;
+    char value[PROPERTY_VALUE_MAX];
+    uint32_t bOptimizeCacheOps = 0;
     mm_camera_stream_config_t stream_config;
     LOGD("batch size is %d", batchSize);
 
@@ -366,6 +411,16 @@
     mStreamInfo->pp_config.feature_mask = postprocess_mask;
     mStreamInfo->is_type = is_type;
     mStreamInfo->pp_config.rotation = streamRotation;
+
+    memset(value, 0, sizeof(value));
+    property_get("persist.camera.cache.optimize", value, "1");
+    bOptimizeCacheOps = atoi(value);
+
+    if (bOptimizeCacheOps) {
+        mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_HONOUR_FLAGS;
+    } else {
+        mStreamInfo->cache_ops = CAM_STREAM_CACHE_OPS_DISABLED;
+    }
     LOGD("stream_type is %d, feature_mask is %Ld",
            mStreamInfo->stream_type, mStreamInfo->pp_config.feature_mask);
 
@@ -681,6 +736,13 @@
     if (UNLIKELY(mBatchSize)) {
         rc = aggregateBufToBatch(mBufDefs[index]);
     } else {
+        // By default every buffer that goes to camera should be invalidated
+        // except Metadata/Preview/Video buffers
+        if ((getMyType() != CAM_STREAM_TYPE_METADATA) &&
+                (getMyType() != CAM_STREAM_TYPE_PREVIEW) &&
+                (getMyType() != CAM_STREAM_TYPE_VIDEO)) {
+            mBufDefs[index].cache_flags |= CPU_HAS_READ;
+        }
         rc = mCamOps->qbuf(mCamHandle, mChannelHandle, &mBufDefs[index]);
         if (rc < 0) {
             return FAILED_TRANSACTION;
@@ -944,6 +1006,27 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : cleanBuf
+ *
+ * DESCRIPTION: clean 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 QCamera3Stream::cleanBuf(uint32_t index)
+{
+    if (mStreamBufs == NULL) {
+        LOGE("putBufs already called");
+        return INVALID_OPERATION;
+    } else
+        return mStreamBufs->cleanCache(index);
+}
+
+/*===========================================================================
  * FUNCTION   : getFrameOffset
  *
  * DESCRIPTION: query stream buffer frame offset info
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3Stream.h b/msmcobalt/QCamera2/HAL3/QCamera3Stream.h
index 1e2be49..4aa9dcd 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3Stream.h
+++ b/msmcobalt/QCamera2/HAL3/QCamera3Stream.h
@@ -142,6 +142,7 @@
                      void *user_data);
     static int32_t invalidate_buf(uint32_t index, void *user_data);
     static int32_t clean_invalidate_buf(uint32_t index, void *user_data);
+    static int32_t clean_buf(uint32_t index, void *user_data);
 
     int32_t getBufs(cam_frame_len_offset_t *offset,
                      uint8_t *num_bufs,
@@ -151,6 +152,7 @@
     int32_t putBufs(mm_camera_map_unmap_ops_tbl_t *ops_tbl);
     int32_t invalidateBuf(uint32_t index);
     int32_t cleanInvalidateBuf(uint32_t index);
+    int32_t cleanBuf(uint32_t index);
     int32_t getBatchBufs(
             uint8_t *num_bufs, uint8_t **initial_reg_flag,
             mm_camera_buf_def_t **bufs,
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.cpp b/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.cpp
index 3843afb..1b08c68 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.cpp
+++ b/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.cpp
@@ -191,6 +191,29 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : cleanCache
+ *
+ * DESCRIPTION: clean the cache of the indexed buffer
+ *
+ * PARAMETERS :
+ *   @index   : index of the buffer
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int QCamera3StreamMem::cleanCache(uint32_t index)
+{
+    Mutex::Autolock lock(mLock);
+
+    if (index < mMaxHeapBuffers)
+        return mHeapMem.cleanCache(index);
+    else
+        return mGrallocMem.cleanCache(index);
+}
+
+
+/*===========================================================================
  * FUNCTION   : getBufDef
  *
  * DESCRIPTION: query detailed buffer information
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.h b/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.h
index 74bab06..0a0679b 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.h
+++ b/msmcobalt/QCamera2/HAL3/QCamera3StreamMem.h
@@ -57,6 +57,7 @@
     ssize_t getSize(uint32_t index);
     int invalidateCache(uint32_t index);
     int cleanInvalidateCache(uint32_t index);
+    int cleanCache(uint32_t index);
     int32_t getBufDef(const cam_frame_len_offset_t &offset,
             mm_camera_buf_def_t &bufDef, uint32_t index);
     void *getPtr(uint32_t index);
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.cpp b/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.cpp
index 5b4d88e..9bd9ec7 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.cpp
+++ b/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.cpp
@@ -49,6 +49,9 @@
         QCAMERA3_CROP_END,
         QCAMERA3_TUNING_META_DATA_END,
         QCAMERA3_TEMPORAL_DENOISE_END,
+        QCAMERA3_ISO_EXP_PRIORITY_END,
+        QCAMERA3_SATURATION_END,
+        QCAMERA3_EXPOSURE_METER_END,
         QCAMERA3_AV_TIMER_END,
         QCAMERA3_SENSOR_META_DATA_END,
         QCAMERA3_DUALCAM_LINK_META_DATA_END,
@@ -58,8 +61,9 @@
         QCAMERA3_VIDEO_HDR_END,
         QCAMERA3_IR_END,
         QCAMERA3_AEC_CONVERGENCE_SPEED_END,
-        QCAMERA3_AWB_CONVERGENCE_SPEED_END
-} ;
+        QCAMERA3_AWB_CONVERGENCE_SPEED_END,
+        QCAMERA3_INSTANT_AEC_END
+};
 
 typedef struct vendor_tag_info {
     const char *tag_name;
@@ -74,6 +78,9 @@
     "org.codeaurora.qcamera3.crop",
     "org.codeaurora.qcamera3.tuning_meta_data",
     "org.codeaurora.qcamera3.temporal_denoise",
+    "org.codeaurora.qcamera3.iso_exp_priority",
+    "org.codeaurora.qcamera3.saturation",
+    "org.codeaurora.qcamera3.exposure_metering",
     "org.codeaurora.qcamera3.av_timer",
     "org.codeaurora.qcamera3.sensor_meta_data",
     "org.codeaurora.qcamera3.dualcam_link_meta_data",
@@ -83,7 +90,8 @@
     "org.codeaurora.qcamera3.video_hdr_mode",
     "org.codeaurora.qcamera3.ir",
     "org.codeaurora.qcamera3.aec_convergence_speed",
-    "org.codeaurora.qcamera3.awb_convergence_speed"
+    "org.codeaurora.qcamera3.awb_convergence_speed",
+    "org.codeaurora.qcamera3.instant_aec"
 };
 
 vendor_tag_info_t qcamera3_privatedata[QCAMERA3_PRIVATEDATA_END - QCAMERA3_PRIVATEDATA_START] = {
@@ -118,6 +126,22 @@
     { "process_type", TYPE_INT32 }
 };
 
+vendor_tag_info qcamera3_iso_exp_priority[QCAMERA3_ISO_EXP_PRIORITY_END -
+                                  QCAMERA3_ISO_EXP_PRIORITY_START] = {
+    { "use_iso_exp_priority", TYPE_INT64 },
+    { "select_priority", TYPE_INT32 }
+};
+
+vendor_tag_info qcamera3_saturation[QCAMERA3_SATURATION_END -
+                                  QCAMERA3_SATURATION_START] = {
+    { "use_saturation", TYPE_INT32 }
+};
+
+vendor_tag_info qcamera3_exposure_metering[QCAMERA3_EXPOSURE_METER_END -
+                                  QCAMERA3_EXPOSURE_METER_START] = {
+    { "exposure_metering_mode", TYPE_INT32}
+};
+
 vendor_tag_info qcamera3_av_timer[QCAMERA3_AV_TIMER_END -
                                   QCAMERA3_AV_TIMER_START] = {
    {"use_av_timer", TYPE_BYTE }
@@ -180,6 +204,13 @@
     {"awb_speed", TYPE_FLOAT }
 };
 
+vendor_tag_info_t
+        qcamera3_instant_aec[QCAMERA3_INSTANT_AEC_END -
+        QCAMERA3_INSTANT_AEC_START] = {
+    { "instant_aec_mode", TYPE_INT32 },
+    { "instant_aec_available_modes",   TYPE_INT32 }
+};
+
 vendor_tag_info_t *qcamera3_tag_info[QCAMERA3_SECTIONS_END -
         VENDOR_SECTION] = {
     qcamera3_privatedata,
@@ -188,6 +219,9 @@
     qcamera3_crop,
     qcamera3_tuning_meta_data,
     qcamera3_temporal_denoise,
+    qcamera3_iso_exp_priority,
+    qcamera3_saturation,
+    qcamera3_exposure_metering,
     qcamera3_av_timer,
     qcamera3_sensor_meta_data,
     qcamera3_dualcam_link_meta_data,
@@ -197,7 +231,8 @@
     qcamera3_video_hdr,
     qcamera3_ir,
     qcamera3_aec_speed,
-    qcamera3_awb_speed
+    qcamera3_awb_speed,
+    qcamera3_instant_aec
 };
 
 uint32_t qcamera3_all_tags[] = {
@@ -223,6 +258,17 @@
     // QCAMERA3_TEMPORAL_DENOISE
     (uint32_t)QCAMERA3_TEMPORAL_DENOISE_ENABLE,
     (uint32_t)QCAMERA3_TEMPORAL_DENOISE_PROCESS_TYPE,
+
+    // QCAMERA3_ISO_EXP_PRIORITY
+    (uint32_t)QCAMERA3_USE_ISO_EXP_PRIORITY,
+    (uint32_t)QCAMERA3_SELECT_PRIORITY,
+
+    // QCAMERA3_SATURATION
+    (uint32_t)QCAMERA3_USE_SATURATION,
+
+    // QCAMERA3_EXPOSURE_METERING
+    (uint32_t)QCAMERA3_EXPOSURE_METER,
+
     //QCAMERA3_AVTIMER
     (uint32_t)QCAMERA3_USE_AV_TIMER,
 
@@ -259,7 +305,11 @@
     (uint32_t)QCAMERA3_AEC_CONVERGENCE_SPEED,
 
     //QCAMERA3_AWB_CONVERGENCE_SPEED
-    (uint32_t)QCAMERA3_AWB_CONVERGENCE_SPEED
+    (uint32_t)QCAMERA3_AWB_CONVERGENCE_SPEED,
+
+    // QCAMERA3_INSTANT_AEC
+    (uint32_t)QCAMERA3_INSTANT_AEC_MODE,
+    (uint32_t)QCAMERA3_INSTANT_AEC_AVAILABLE_MODES
 };
 
 const vendor_tag_ops_t* QCamera3VendorTags::Ops = NULL;
diff --git a/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.h b/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.h
index fad5caa..2ec541c 100644
--- a/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.h
+++ b/msmcobalt/QCamera2/HAL3/QCamera3VendorTags.h
@@ -42,6 +42,9 @@
     QCAMERA3_CROP,
     QCAMERA3_TUNING_META_DATA,
     QCAMERA3_TEMPORAL_DENOISE,
+    QCAMERA3_ISO_EXP_PRIORITY,
+    QCAMERA3_SATURATION,
+    QCAMERA3_EXPOSURE_METERING_MODE,
     QCAMERA3_AV_TIMER,
     QCAMERA3_SENSOR_META_DATA,
     QCAMERA3_DUALCAM_LINK_META_DATA,
@@ -52,6 +55,7 @@
     QCAMERA3_IR,
     QCAMERA3_AEC_CONVERGENCE,
     QCAMERA3_AWB_CONVERGENCE,
+    QCAMERA3_INSTANT_AEC,
     QCAMERA3_SECTIONS_END
 };
 
@@ -62,6 +66,9 @@
     QCAMERA3_CROP_START = QCAMERA3_CROP << 16,
     QCAMERA3_TUNING_META_DATA_START = QCAMERA3_TUNING_META_DATA << 16,
     QCAMERA3_TEMPORAL_DENOISE_START = QCAMERA3_TEMPORAL_DENOISE << 16,
+    QCAMERA3_ISO_EXP_PRIORITY_START = QCAMERA3_ISO_EXP_PRIORITY << 16,
+    QCAMERA3_SATURATION_START = QCAMERA3_SATURATION << 16,
+    QCAMERA3_EXPOSURE_METER_START = QCAMERA3_EXPOSURE_METERING_MODE << 16,
     QCAMERA3_AV_TIMER_START = QCAMERA3_AV_TIMER << 16,
     QCAMERA3_SENSOR_META_DATA_START = QCAMERA3_SENSOR_META_DATA << 16,
     QCAMERA3_DUALCAM_LINK_META_DATA_START = QCAMERA3_DUALCAM_LINK_META_DATA << 16,
@@ -71,7 +78,8 @@
     QCAMERA3_VIDEO_HDR_START = QCAMERA3_VIDEO_HDR << 16,
     QCAMERA3_IR_START = QCAMERA3_IR << 16,
     QCAMERA3_AEC_CONVERGENCE_SPEED_START = QCAMERA3_AEC_CONVERGENCE << 16,
-    QCAMERA3_AWB_CONVERGENCE_SPEED_START = QCAMERA3_AWB_CONVERGENCE << 16
+    QCAMERA3_AWB_CONVERGENCE_SPEED_START = QCAMERA3_AWB_CONVERGENCE << 16,
+    QCAMERA3_INSTANT_AEC_START = QCAMERA3_INSTANT_AEC << 16
 };
 
 enum qcamera3_ext_tags {
@@ -145,6 +153,16 @@
     QCAMERA3_TEMPORAL_DENOISE_PROCESS_TYPE,
     QCAMERA3_TEMPORAL_DENOISE_END,
 
+    QCAMERA3_USE_ISO_EXP_PRIORITY = QCAMERA3_ISO_EXP_PRIORITY_START,
+    QCAMERA3_SELECT_PRIORITY,
+    QCAMERA3_ISO_EXP_PRIORITY_END,
+
+    QCAMERA3_USE_SATURATION = QCAMERA3_SATURATION_START,
+    QCAMERA3_SATURATION_END,
+
+    QCAMERA3_EXPOSURE_METER = QCAMERA3_EXPOSURE_METER_START,
+    QCAMERA3_EXPOSURE_METER_END,
+
     QCAMERA3_USE_AV_TIMER = QCAMERA3_AV_TIMER_START,
     QCAMERA3_AV_TIMER_END,
 
@@ -203,7 +221,11 @@
     QCAMERA3_AEC_CONVERGENCE_SPEED_END,
 
     QCAMERA3_AWB_CONVERGENCE_SPEED = QCAMERA3_AWB_CONVERGENCE_SPEED_START,
-    QCAMERA3_AWB_CONVERGENCE_SPEED_END
+    QCAMERA3_AWB_CONVERGENCE_SPEED_END,
+
+    QCAMERA3_INSTANT_AEC_MODE = QCAMERA3_INSTANT_AEC_START,
+    QCAMERA3_INSTANT_AEC_AVAILABLE_MODES,
+    QCAMERA3_INSTANT_AEC_END
 };
 
 // QCAMERA3_OPAQUE_RAW_FORMAT
@@ -226,6 +248,13 @@
     QCAMERA3_IR_MODE_AUTO
 } camera_metadata_enum_android_ir_mode_t;
 
+// QCAMERA3_INSTANCE_AEC_MODE
+typedef enum qcamera3_ext_instant_aec_mode {
+    QCAMERA3_INSTANT_AEC_NORMAL_CONVERGENCE,
+    QCAMERA3_INSTANT_AEC_AGGRESSIVE_CONVERGENCE,
+    QCAMERA3_INSTANT_AEC_FAST_CONVERGENCE
+} qcamera3_ext_instant_aec_mode_t;
+
 class QCamera3VendorTags {
 
 public:
diff --git a/msmcobalt/QCamera2/QCamera2Factory.cpp b/msmcobalt/QCamera2/QCamera2Factory.cpp
index 97e9eb7..cd1edd9 100644
--- a/msmcobalt/QCamera2/QCamera2Factory.cpp
+++ b/msmcobalt/QCamera2/QCamera2Factory.cpp
@@ -497,13 +497,6 @@
 {
     int rc = NO_ERROR;
 
-#ifdef DUAL_CAM_TEST
-    char prop[PROPERTY_VALUE_MAX];
-    memset(prop, 0, sizeof(prop));
-    property_get("persist.camera.id", prop, "0");
-    cameraId = atoi(prop);
-#endif
-
     LOGI("openLegacy halVersion: %d cameraId = %d", halVersion, cameraId);
     //Assumption: all cameras can support legacy API version
     if (cameraId < 0 || cameraId >= gQCamera2Factory->getNumberOfCameras())
diff --git a/msmcobalt/QCamera2/stack/common/cam_intf.h b/msmcobalt/QCamera2/stack/common/cam_intf.h
old mode 100755
new mode 100644
index 696a85d..30a2e53
--- a/msmcobalt/QCamera2/stack/common/cam_intf.h
+++ b/msmcobalt/QCamera2/stack/common/cam_intf.h
@@ -56,7 +56,7 @@
     /* stop ZSL snapshot.*/
     CAM_PRIV_STOP_ZSL_SNAPSHOT,
     /* event for related sensors synchronization. */
-    CAM_PRIV_SYNC_RELATED_SENSORS,
+    CAM_PRIV_DUAL_CAM_CMD,
     /* flush */
     CAM_PRIV_FLUSH
 } cam_private_ioctl_enum_t;
@@ -81,18 +81,52 @@
     CAM_MODE_SECONDARY
 } cam_sync_mode_t;
 
+/*Enum to inform about camera type in dual camera use-cases*/
+typedef enum {
+    CAM_ROLE_DEFAULT,
+    CAM_ROLE_BAYER,
+    CAM_ROLE_MONO,
+    CAM_ROLE_WIDE,
+    CAM_ROLE_TELE
+} cam_dual_camera_role_t;
+
 /* Payload for sending bundling info to backend */
 typedef struct {
     cam_sync_related_sensors_control_t sync_control;
     cam_sync_type_t type;
     cam_sync_mode_t mode;
     cam_3a_sync_mode_t sync_3a_mode;
+    cam_dual_camera_role_t cam_role;
     /* session Id of the other camera session
        Linking will be done with this session in the
        backend */
     uint32_t related_sensor_session_id;
     uint8_t is_frame_sync_enabled;
-}cam_sync_related_sensors_event_info_t;
+} cam_dual_camera_bundle_info_t;
+typedef cam_dual_camera_bundle_info_t cam_sync_related_sensors_event_info_t;
+
+/* Structrue to update master camera info in dual camera case*/
+typedef struct {
+    cam_sync_mode_t mode;
+} cam_dual_camera_master_info_t;
+
+/* Structrue to control performance info in dual camera case*/
+typedef struct {
+    uint8_t low_fps; /*Control perf using FPS if set*/
+    uint8_t enable;  /*Enable or diable Low power mode*/
+} cam_dual_camera_perf_control_t;
+
+/* dual camera event payload */
+typedef struct {
+    cam_dual_camera_cmd_type cmd_type; /*dual camera command type*/
+
+    /*Payload to carry command info*/
+    union {
+        cam_dual_camera_bundle_info_t  bundle_info;
+        cam_dual_camera_master_info_t  mode;
+        cam_dual_camera_perf_control_t value;
+    };
+} cam_dual_camera_cmd_info_t;
 
 /* Related camera sensor specific calibration data */
 // Align bytes according to API document.
@@ -265,6 +299,7 @@
     float focal_length;                                     /* focal length */
     float hor_view_angle;                                   /* horizontal view angle */
     float ver_view_angle;                                   /* vertical view angle */
+    cam_lens_type_t lens_type;                              /*Lens type info - Wide, Tele*/
 
     size_t preview_sizes_tbl_cnt;                           /* preview sizes table size */
     cam_dimension_t preview_sizes_tbl[MAX_SIZES_CNT];       /* preiew sizes table */
@@ -563,6 +598,9 @@
     size_t supported_ir_mode_cnt;
     cam_ir_mode_type_t supported_ir_modes[CAM_IR_MODE_MAX];
 
+    /*camera index*/
+    uint32_t camera_index;
+
     /*Slave capability*/
     struct cam_capability *aux_cam_cap;
     cam_sync_type_t cam_sensor_mode;
@@ -693,6 +731,9 @@
 
     /*Stream info for Slave Stream*/
     struct cam_stream_info *aux_str_info;
+
+    /* Cache ops for this stream */
+    cam_stream_cache_ops_t cache_ops;
 } cam_stream_info_t;
 
 /*****************************************************************************
@@ -1035,8 +1076,6 @@
     INCLUDE(CAM_INTF_PARM_JPEG_ENCODE_CROP,             cam_stream_crop_info_t,      1);
     INCLUDE(CAM_INTF_PARM_JPEG_SCALE_DIMENSION,         cam_dimension_t,             1);
     INCLUDE(CAM_INTF_META_FOCUS_DEPTH_INFO,             uint8_t,                     1);
-    INCLUDE(CAM_INTF_PARM_SUSPEND_RESUME_CAMERAS,       uint32_t,                    2);
-    INCLUDE(CAM_INTF_PARM_CAMERA_MASTER_INFO,           uint32_t,                    2);
 } metadata_data_t;
 
 /* Update clear_metadata_buffer() function when a new is_xxx_valid is added to
diff --git a/msmcobalt/QCamera2/stack/common/cam_types.h b/msmcobalt/QCamera2/stack/common/cam_types.h
index a6c91eb..3f63ae7 100644
--- a/msmcobalt/QCamera2/stack/common/cam_types.h
+++ b/msmcobalt/QCamera2/stack/common/cam_types.h
@@ -145,6 +145,10 @@
 /* Defines the number of columns in the color correction matrix (CCM) */
 #define AWB_NUM_CCM_COLS (3)
 
+#define CPU_HAS_READ  (1 << 0)
+#define CPU_HAS_WRITTEN  (1 << 1)
+#define CPU_HAS_READ_WRITTEN (CPU_HAS_READ |CPU_HAS_WRITTEN)
+
 typedef uint64_t cam_feature_mask_t;
 
 typedef enum {
@@ -174,6 +178,12 @@
 } cam_position_t;
 
 typedef enum {
+    CAM_LENS_NORMAL,
+    CAM_LENS_WIDE,
+    CAM_LENS_TELE
+} cam_lens_type_t;
+
+typedef enum {
     CAM_FLICKER_NONE,
     CAM_FLICKER_50_HZ,
     CAM_FLICKER_60_HZ
@@ -413,6 +423,7 @@
     CAM_MAPPING_BUF_TYPE_PARM_BUF,    /* mapping parameters buffer */
     /* this buffer is needed for the payload to be sent with bundling related cameras cmd */
     CAM_MAPPING_BUF_TYPE_SYNC_RELATED_SENSORS_BUF, /* mapping sync buffer.*/
+    CAM_MAPPING_BUF_TYPE_DUAL_CAM_CMD_BUF, /*Dual camera cmd ion memory*/
 
     /* followings are per stream */
     CAM_MAPPING_BUF_TYPE_STREAM_BUF,        /* mapping stream buffers */
@@ -559,6 +570,12 @@
 } cam_sensitivity_range_t;
 
 typedef enum {
+    CAM_ISO_PRIORITY,
+    CAM_EXP_PRIORITY,
+    CAM_DEFAULT_OFF,
+} cam_priority_mode_t;
+
+typedef enum {
     CAM_HFR_MODE_OFF,
     CAM_HFR_MODE_60FPS,
     CAM_HFR_MODE_90FPS,
@@ -1648,6 +1665,16 @@
    uint32_t max_buffers;
 } cam_buffer_info_t;
 
+
+typedef enum {
+    /* cmd to bundle cameras*/
+    CAM_DUAL_CAMERA_BUNDLE_INFO,
+    /*cmd to suspend or resume cameras*/
+    CAM_DUAL_CAMERA_LOW_POWER_MODE,
+    /*cmd to send information about role switch*/
+    CAM_DUAL_CAMERA_MASTER_INFO
+} cam_dual_camera_cmd_type;
+
 typedef enum {
     /* Standalone camera (won't be linked) */
     CAM_TYPE_STANDALONE=0,
@@ -2248,10 +2275,6 @@
     CAM_INTF_META_FOCUS_VALUE,
     /*Spot light detection result output from af core*/
     CAM_INTF_META_SPOT_LIGHT_DETECT,
-    /*parameter to control dual camera's from HAL*/
-    CAM_INTF_PARM_SUSPEND_RESUME_CAMERAS,
-    /*Camera module master info*/
-    CAM_INTF_PARM_CAMERA_MASTER_INFO,
     CAM_INTF_PARM_MAX
 } cam_intf_parm_type_t;
 
@@ -2846,4 +2869,10 @@
     CAM_CUSTOM_PARM_MAX,
 } cam_custom_parm_type;
 
+typedef enum {
+    CAM_STREAM_CACHE_OPS_CLEAR_FLAGS,
+    CAM_STREAM_CACHE_OPS_HONOUR_FLAGS,
+    CAM_STREAM_CACHE_OPS_DISABLED
+} cam_stream_cache_ops_t;
+
 #endif /* __QCAMERA_TYPES_H__ */
diff --git a/msmcobalt/QCamera2/stack/common/mm_camera_interface.h b/msmcobalt/QCamera2/stack/common/mm_camera_interface.h
index 25b48b4..1823a6b 100644
--- a/msmcobalt/QCamera2/stack/common/mm_camera_interface.h
+++ b/msmcobalt/QCamera2/stack/common/mm_camera_interface.h
@@ -133,6 +133,7 @@
 *               mem allocation
 *    @mem_info : user specific pointer to additional mem info
 *    @flags:  v4l2_buffer flags, used to report error in data buffers
+*    @cache_flags: Stores cache related read/write flags
 **/
 typedef struct mm_camera_buf_def {
     uint32_t stream_id;
@@ -151,6 +152,7 @@
     size_t frame_len;
     void *mem_info;
     uint32_t flags;
+    uint32_t cache_flags;
 } mm_camera_buf_def_t;
 
 /** mm_camera_super_buf_t: super buf structure for bundled
@@ -288,6 +290,7 @@
                        void *user_data);
   int32_t (*invalidate_buf)(uint32_t index, void *user_data);
   int32_t (*clean_invalidate_buf)(uint32_t index, void *user_data);
+  int32_t (*clean_buf)(uint32_t index, void *user_data);
 } mm_camera_stream_mem_vtbl_t;
 
 /** mm_camera_stream_config_t: structure for stream
@@ -855,16 +858,13 @@
     int32_t (*get_session_id) (uint32_t camera_handle,
             uint32_t* sessionid);
 
-    /** sync_related_sensors: sends sync cmd
+    /** set_dual_cam_cmd: sends sync cmd
       *    @camera_handle : camera handle
-      *    @related_cam_info : related cam info to be sent to server
       *     Return value: 0 -- success
       *                -1 -- failure
       *  Note: if this call succeeds, we will get linking established in back end
       **/
-     int32_t (*sync_related_sensors) (uint32_t camera_handle,
-            cam_sync_related_sensors_event_info_t*
-            related_cam_info);
+     int32_t (*set_dual_cam_cmd)(uint32_t camera_handle);
     /** flush: function definition for flush
      *  @camera_handle: camera handler
      *  Return value: 0 -- success
@@ -951,8 +951,9 @@
         cam_padding_info_t *padding,
         cam_stream_buf_plane_info_t *buf_planes);
 
-int32_t mm_stream_calc_offset_post_view(cam_format_t fmt,
+int32_t mm_stream_calc_offset_post_view(cam_stream_info_t *stream_info,
         cam_dimension_t *dim,
+        cam_padding_info_t *padding,
         cam_stream_buf_plane_info_t *buf_planes);
 
 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
diff --git a/msmcobalt/QCamera2/stack/common/mm_jpeg_interface.h b/msmcobalt/QCamera2/stack/common/mm_jpeg_interface.h
index 9f0ac7f..7687893 100644
--- a/msmcobalt/QCamera2/stack/common/mm_jpeg_interface.h
+++ b/msmcobalt/QCamera2/stack/common/mm_jpeg_interface.h
@@ -43,6 +43,10 @@
 #define QTABLE_MAX 2
 #define MM_JPEG_MAX_MPO_IMAGES 2
 
+/* bit mask for buffer usage*/
+#define MM_JPEG_HAS_READ_BUF CPU_HAS_READ
+#define MM_JPEG_HAS_WRITTEN_BUF CPU_HAS_WRITTEN
+
 typedef enum {
   MM_JPEG_FMT_YUV,
   MM_JPEG_FMT_BITSTREAM
@@ -240,6 +244,24 @@
 
 } mm_jpeg_decode_params_t;
 
+/* This structure is populated by HAL to notify buffer
+  usage like has read or has written. This info is then
+  used to perform cache ops in jpeg */
+typedef struct {
+  /* main image source buff usage */
+  uint8_t main_src_buf;
+
+  /* thumbnail source buff usage */
+  uint8_t thumb_src_buf;
+
+  /* destination buff usage */
+  uint8_t dest_buf;
+
+  /* work buff usage */
+  uint8_t work_buf;
+
+} mm_jpeg_buf_usage_t;
+
 typedef struct {
   /* active indices of the buffers for encoding */
   int32_t src_index;
@@ -288,6 +310,11 @@
 
   /* work buf */
   mm_jpeg_buf_t work_buf;
+
+  /* Input from HAL notifing the prior usage of buffers,
+  this info will be used to perform cache ops*/
+  mm_jpeg_buf_usage_t buf_usage;
+
 } mm_jpeg_encode_job_t;
 
 typedef struct {
diff --git a/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera.h b/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
index a1f0ecf..0e1692f 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
+++ b/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
@@ -802,8 +802,7 @@
                                           void *actions);
 extern int32_t mm_camera_get_session_id(mm_camera_obj_t *my_obj,
                                         uint32_t* sessionid);
-extern int32_t mm_camera_sync_related_sensors(mm_camera_obj_t *my_obj,
-                                   cam_sync_related_sensors_event_info_t *parms);
+extern int32_t mm_camera_set_dual_cam_cmd(mm_camera_obj_t *my_obj);
 extern int32_t mm_camera_reg_frame_sync(mm_camera_obj_t *my_obj,
         uint32_t ch_id, uint32_t stream_id,
         mm_camera_frame_sync_t *sync_attr);
diff --git a/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera_muxer.h b/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera_muxer.h
index 6e67276..6fb4d2a 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera_muxer.h
+++ b/msmcobalt/QCamera2/stack/mm-camera-interface/inc/mm_camera_muxer.h
@@ -162,6 +162,8 @@
 int32_t mm_camera_muxer_switch_stream(uint32_t camera_handle,
         uint32_t ch_id, uint32_t stream_id,
         mm_camera_obj_t *cam_obj);
+int32_t mm_camera_muxer_set_dual_cam_cmd(uint32_t camera_handle,
+        mm_camera_obj_t *cam_obj);
 
 /*Muxer internal functions*/
 void mm_camera_muxer_stream_frame_sync(mm_camera_super_buf_t *super_buf,
diff --git a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera.c b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera.c
index bbe405c..adf98f6 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera.c
@@ -2329,13 +2329,12 @@
 }
 
 /*===========================================================================
- * FUNCTION   : mm_camera_sync_related_sensors
+ * FUNCTION   : mm_camera_set_dual_cam_cmd
  *
  * DESCRIPTION: send sync cmd
  *
  * PARAMETERS :
  *   @my_obj       : camera object
- *   @parms        : ptr to the related cam info to be sent to server
  *
  * RETURN     : int32_t type of status
  *              0  -- success
@@ -2344,15 +2343,12 @@
  *              domain socket. Corresponding fields of parameters to be set
  *              are already filled in by upper layer caller.
  *==========================================================================*/
-int32_t mm_camera_sync_related_sensors(mm_camera_obj_t *my_obj,
-        cam_sync_related_sensors_event_info_t* parms)
+int32_t mm_camera_set_dual_cam_cmd(mm_camera_obj_t *my_obj)
 {
     int32_t rc = -1;
     int32_t value = 0;
-    if (parms !=  NULL) {
-        rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd,
-                CAM_PRIV_SYNC_RELATED_SENSORS, &value);
-    }
+    rc = mm_camera_util_s_ctrl(my_obj, 0, my_obj->ctrl_fd,
+            CAM_PRIV_DUAL_CAM_CMD, &value);
     pthread_mutex_unlock(&my_obj->cam_lock);
     return rc;
 }
diff --git a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
index 8537ac1..ae7648c 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_interface.c
@@ -2265,7 +2265,7 @@
 }
 
 /*===========================================================================
- * FUNCTION   : mm_camera_intf_sync_related_sensors
+ * FUNCTION   : mm_camera_intf_set_dual_cam_cmd
  *
  * DESCRIPTION: retrieve the session ID from the kernel for this HWI instance
  *
@@ -2278,21 +2278,37 @@
  *              -1 -- failure
  * NOTE       : if this call succeeds, we will get linking established in back end
  *==========================================================================*/
-static int32_t mm_camera_intf_sync_related_sensors(uint32_t camera_handle,
-                              cam_sync_related_sensors_event_info_t* related_cam_info)
+static int32_t mm_camera_intf_set_dual_cam_cmd(uint32_t camera_handle)
 {
     int32_t rc = -1;
     mm_camera_obj_t * my_obj = NULL;
+    uint32_t handle = get_main_camera_handle(camera_handle);
+    uint32_t aux_handle = get_aux_camera_handle(camera_handle);
 
-    pthread_mutex_lock(&g_intf_lock);
-    my_obj = mm_camera_util_get_camera_by_handler(camera_handle);
+    if (handle) {
+        pthread_mutex_lock(&g_intf_lock);
+        my_obj = mm_camera_util_get_camera_by_handler(handle);
 
-    if(my_obj) {
-        pthread_mutex_lock(&my_obj->cam_lock);
-        pthread_mutex_unlock(&g_intf_lock);
-        rc = mm_camera_sync_related_sensors(my_obj, related_cam_info);
-    } else {
-        pthread_mutex_unlock(&g_intf_lock);
+        if(my_obj) {
+            pthread_mutex_lock(&my_obj->cam_lock);
+            pthread_mutex_unlock(&g_intf_lock);
+            rc = mm_camera_set_dual_cam_cmd(my_obj);
+        } else {
+            pthread_mutex_unlock(&g_intf_lock);
+        }
+    }
+
+    if (aux_handle) {
+        pthread_mutex_lock(&g_intf_lock);
+        my_obj = mm_camera_util_get_camera_head(aux_handle);
+        if (my_obj) {
+            pthread_mutex_lock(&my_obj->muxer_lock);
+            pthread_mutex_unlock(&g_intf_lock);
+            rc = mm_camera_muxer_set_dual_cam_cmd(
+                    aux_handle, my_obj);
+        } else {
+            pthread_mutex_unlock(&g_intf_lock);
+        }
     }
     return rc;
 }
@@ -2364,10 +2380,7 @@
                 facing = ((entity.flags & CAM_SENSOR_FACING_MASK) ?
                         CAMERA_FACING_FRONT:CAMERA_FACING_BACK);
 
-                /* TODO: Need to revisit this logic if front AUX is available. */
-                if ((unsigned int)facing == CAMERA_FACING_FRONT) {
-                    type = CAM_TYPE_STANDALONE;
-                } else if (entity.flags & CAM_SENSOR_TYPE_MASK) {
+                if (entity.flags & CAM_SENSOR_TYPE_MASK) {
                     type = CAM_TYPE_AUX;
                 } else {
                     type = CAM_TYPE_MAIN;
@@ -2410,15 +2423,15 @@
 void sort_camera_info(int num_cam)
 {
     int idx = 0, i;
-    int8_t is_yuv_aux_cam_exposed = 0;
-    char prop[PROPERTY_VALUE_MAX];
     struct camera_info temp_info[MM_CAMERA_MAX_NUM_SENSORS];
     cam_sync_type_t temp_type[MM_CAMERA_MAX_NUM_SENSORS];
     cam_sync_mode_t temp_mode[MM_CAMERA_MAX_NUM_SENSORS];
     uint8_t temp_is_yuv[MM_CAMERA_MAX_NUM_SENSORS];
     char temp_dev_name[MM_CAMERA_MAX_NUM_SENSORS][MM_CAMERA_DEV_NAME_LEN];
     uint32_t cam_idx[MM_CAMERA_MAX_NUM_SENSORS] = {0};
-    uint8_t prime_cam_idx = 0, aux_cam_idx = 0;
+    uint8_t b_prime_idx = 0, b_aux_idx = 0, f_prime_idx = 0, f_aux_idx = 0;
+    int8_t expose_aux = 0;
+    char prop[PROPERTY_VALUE_MAX];
 
     memset(temp_info, 0, sizeof(temp_info));
     memset(temp_dev_name, 0, sizeof(temp_dev_name));
@@ -2426,138 +2439,119 @@
     memset(temp_mode, 0, sizeof(temp_mode));
     memset(temp_is_yuv, 0, sizeof(temp_is_yuv));
 
-    // Signifies whether YUV AUX camera has to be exposed as physical camera
     memset(prop, 0, sizeof(prop));
-    property_get("persist.camera.aux.yuv", prop, "0");
-    is_yuv_aux_cam_exposed = atoi(prop);
-    LOGI("YUV Aux camera exposed %d",is_yuv_aux_cam_exposed);
+    property_get("persist.camera.expose.aux", prop, "0");
+    expose_aux = atoi(prop);
 
     /* Order of the camera exposed is
-    Back main, Front main, Back Aux and then Front Aux.
-    It is because that lot of 3rd party cameras apps
-    blindly assume 0th is Back and 1st is front */
-
-    /* Firstly save the main back cameras info */
+        0  - Back Main Camera
+        1  - Front Main Camera
+        ++  - Back Aux Camera
+        ++  - Front Aux Camera
+        ++  - Back Main + Back Aux camera
+        ++  - Front Main + Front Aux camera
+        ++  - Secure Camera
+       */
     for (i = 0; i < num_cam; i++) {
         if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_BACK) &&
-            !(g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX)
-            && ((g_cam_ctrl.cam_type[i] & CAM_TYPE_MAIN)
-            || (g_cam_ctrl.cam_type[i] == CAM_TYPE_STANDALONE))) {
+            (g_cam_ctrl.cam_type[i] == CAM_TYPE_MAIN)) {
             temp_info[idx] = g_cam_ctrl.info[i];
             temp_type[idx] = CAM_TYPE_MAIN;
             temp_mode[idx] = g_cam_ctrl.cam_mode[i];
             temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
             cam_idx[idx] = idx;
-            prime_cam_idx = idx;
-            LOGD("Found Back Main Camera: i: %d idx: %d", i, idx);
-            memcpy(temp_dev_name[idx++],g_cam_ctrl.video_dev_name[i],
+            b_prime_idx = idx;
+            LOGH("Found Back Main Camera: i: %d idx: %d", i, idx);
+            memcpy(temp_dev_name[idx],g_cam_ctrl.video_dev_name[i],
                 MM_CAMERA_DEV_NAME_LEN);
-        }
-    }
-
-    /* Save the main front cameras info */
-    for (i = 0; i < num_cam; i++) {
-        if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_FRONT) &&
-            !(g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX)
-            && ((g_cam_ctrl.cam_type[i] & CAM_TYPE_MAIN)
-            || (g_cam_ctrl.cam_type[i] == CAM_TYPE_STANDALONE))) {
-            temp_info[idx] = g_cam_ctrl.info[i];
-            temp_type[idx] = CAM_TYPE_MAIN;
-            temp_mode[idx] = g_cam_ctrl.cam_mode[i];
-            temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
-            cam_idx[idx] = idx;
-            LOGD("Found Front Main Camera: i: %d idx: %d", i, idx);
-            memcpy(temp_dev_name[idx++],g_cam_ctrl.video_dev_name[i],
-                    MM_CAMERA_DEV_NAME_LEN);
-        }
-    }
-
-    /*Expose Bayer Aux as a valid sensor*/
-    for (i = 0; i < num_cam; i++) {
-        if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_BACK) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_MAIN)) {
-            temp_info[idx] = g_cam_ctrl.info[i];
-            temp_type[idx] = CAM_TYPE_MAIN;
-            temp_mode[idx] = g_cam_ctrl.cam_mode[i];
-            temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
-            cam_idx[idx] = idx;
-            LOGD("Found Bayer + Aux: i: %d idx: %d", i, idx);
-            memcpy(temp_dev_name[idx++],g_cam_ctrl.video_dev_name[i],
-                MM_CAMERA_DEV_NAME_LEN);
+            idx++;
         }
     }
 
     for (i = 0; i < num_cam; i++) {
         if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_FRONT) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_MAIN)) {
+            (g_cam_ctrl.cam_type[i] == CAM_TYPE_MAIN)) {
             temp_info[idx] = g_cam_ctrl.info[i];
             temp_type[idx] = CAM_TYPE_MAIN;
             temp_mode[idx] = g_cam_ctrl.cam_mode[i];
             temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
             cam_idx[idx] = idx;
-            aux_cam_idx = idx;
-            LOGD("Found Bayer + Aux: i: %d idx: %d", i, idx);
-            memcpy(temp_dev_name[idx++],g_cam_ctrl.video_dev_name[i],
+            f_prime_idx = idx;
+            LOGH("Found Front Main Camera: i: %d idx: %d", i, idx);
+            memcpy(temp_dev_name[idx],g_cam_ctrl.video_dev_name[i],
                 MM_CAMERA_DEV_NAME_LEN);
+            idx++;
         }
     }
 
-    /* Expose YUV AUX camera if persist.camera.aux.yuv is set to 1.
-    Otherwsie expose AUX camera if it is not YUV. */
     for (i = 0; i < num_cam; i++) {
         if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_BACK) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX) &&
-                !(g_cam_ctrl.cam_type[i] & CAM_TYPE_MAIN) &&
-                (is_yuv_aux_cam_exposed || !(g_cam_ctrl.is_yuv[i]))) {
+            (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX)
+            && expose_aux) {
             temp_info[idx] = g_cam_ctrl.info[i];
-            temp_type[idx] = CAM_TYPE_AUX;
+            temp_type[idx] = CAM_TYPE_MAIN;
             temp_mode[idx] = g_cam_ctrl.cam_mode[i];
             temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
             cam_idx[idx] = idx;
-            LOGD("Found back Aux Camera: i: %d idx: %d", i, idx);
-            memcpy(temp_dev_name[idx++],g_cam_ctrl.video_dev_name[i],
+            b_aux_idx = idx;
+            LOGH("Found Back Aux Camera: i: %d idx: %d", i, idx);
+            memcpy(temp_dev_name[idx],g_cam_ctrl.video_dev_name[i],
                 MM_CAMERA_DEV_NAME_LEN);
+            idx++;
         }
     }
 
-    /* Expose YUV AUX camera if persist.camera.aux.yuv is set to 1.
-    Otherwsie expose AUX camera if it is not YUV. */
     for (i = 0; i < num_cam; i++) {
         if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_FRONT) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX) &&
-                !(g_cam_ctrl.cam_type[i] & CAM_TYPE_MAIN) &&
-                (is_yuv_aux_cam_exposed || !(g_cam_ctrl.is_yuv[i]))) {
+            (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX)
+            && expose_aux) {
             temp_info[idx] = g_cam_ctrl.info[i];
-            temp_type[idx] = CAM_TYPE_AUX;
+            temp_type[idx] = CAM_TYPE_MAIN;
             temp_mode[idx] = g_cam_ctrl.cam_mode[i];
             temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
             cam_idx[idx] = idx;
-            LOGD("Found Front Aux Camera: i: %d idx: %d", i, idx);
-            memcpy(temp_dev_name[idx++],g_cam_ctrl.video_dev_name[i],
+            f_aux_idx = idx;
+            LOGH("Found front Aux Camera: i: %d idx: %d", i, idx);
+            memcpy(temp_dev_name[idx],g_cam_ctrl.video_dev_name[i],
                 MM_CAMERA_DEV_NAME_LEN);
+            idx++;
         }
     }
 
-    /*Expose AUX + MAIN camera*/
     for (i = 0; i < num_cam; i++) {
-        if (((g_cam_ctrl.info[i].facing == CAMERA_FACING_BACK) ||
-                (g_cam_ctrl.info[i].facing == CAMERA_FACING_FRONT)) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX) &&
-                (g_cam_ctrl.cam_type[i] & CAM_TYPE_MAIN)) {
+        if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_BACK) &&
+            (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX)
+            && expose_aux) { // Need Main check here after sensor change
             temp_info[idx] = g_cam_ctrl.info[i];
-            temp_type[idx] = CAM_TYPE_AUX | CAM_TYPE_MAIN;
+            temp_type[idx] = CAM_TYPE_MAIN | CAM_TYPE_AUX;
             temp_mode[idx] = g_cam_ctrl.cam_mode[i];
             temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
-            //Assuming primary is back
-            cam_idx[idx] = (aux_cam_idx << MM_CAMERA_HANDLE_SHIFT_MASK) | prime_cam_idx;
-            LOGD("Add additional Bayer + Aux: i: %d idx: %d", i, idx);
-            memcpy(temp_dev_name[idx++],g_cam_ctrl.video_dev_name[i],
+            cam_idx[idx] = (b_aux_idx << MM_CAMERA_HANDLE_SHIFT_MASK) | b_prime_idx;
+            LOGH("Found Back Main+AUX Camera: i: %d idx: %d", i, idx);
+            memcpy(temp_dev_name[idx],g_cam_ctrl.video_dev_name[i],
                 MM_CAMERA_DEV_NAME_LEN);
+            idx++;
         }
     }
 
+    for (i = 0; i < num_cam; i++) {
+        if ((g_cam_ctrl.info[i].facing == CAMERA_FACING_FRONT) &&
+            (g_cam_ctrl.cam_type[i] & CAM_TYPE_AUX)
+            &&expose_aux) { // Need Main check here after sensor change
+            temp_info[idx] = g_cam_ctrl.info[i];
+            temp_type[idx] = CAM_TYPE_MAIN | CAM_TYPE_AUX;
+            temp_mode[idx] = g_cam_ctrl.cam_mode[i];
+            temp_is_yuv[idx] = g_cam_ctrl.is_yuv[i];
+            cam_idx[idx] = (f_aux_idx << MM_CAMERA_HANDLE_SHIFT_MASK) | f_prime_idx;
+            LOGH("Found Back Main Camera: i: %d idx: %d", i, idx);
+            memcpy(temp_dev_name[idx],g_cam_ctrl.video_dev_name[i],
+                MM_CAMERA_DEV_NAME_LEN);
+            idx++;
+        }
+    }
+
+    /*NOTE: Add logic here to modify cameraID again here*/
+
     if (idx != 0) {
         memcpy(g_cam_ctrl.info, temp_info, sizeof(temp_info));
         memcpy(g_cam_ctrl.cam_type, temp_type, sizeof(temp_type));
@@ -3101,7 +3095,7 @@
     .configure_notify_mode = mm_camera_intf_configure_notify_mode,
     .process_advanced_capture = mm_camera_intf_process_advanced_capture,
     .get_session_id = mm_camera_intf_get_session_id,
-    .sync_related_sensors = mm_camera_intf_sync_related_sensors,
+    .set_dual_cam_cmd = mm_camera_intf_set_dual_cam_cmd,
     .flush = mm_camera_intf_flush,
     .register_stream_buf_cb = mm_camera_intf_register_stream_buf_cb,
     .register_frame_sync = mm_camera_intf_reg_frame_sync,
diff --git a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_muxer.c b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_muxer.c
index b9a05a2..dc74b11 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_muxer.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_muxer.c
@@ -1754,6 +1754,36 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : mm_camera_muxer_set_dual_cam_cmd
+ *
+ * DESCRIPTION: send event to trigger read on dual camera cmd buffer
+ *
+ * PARAMETERS :
+ *   @camera_handle: camera handle
+ *   @cam_obj        : header object
+ *
+ * RETURN     : int32_t type of status
+ *              0  -- success
+ *              1 -- failure
+ *==========================================================================*/
+int32_t mm_camera_muxer_set_dual_cam_cmd(uint32_t camera_handle,
+        mm_camera_obj_t *cam_obj)
+{
+    int32_t rc = 0;
+    mm_camera_obj_t * my_obj = NULL;
+    my_obj = mm_muxer_util_get_camera_by_obj(camera_handle, cam_obj);
+
+    if(my_obj) {
+        pthread_mutex_lock(&my_obj->cam_lock);
+        pthread_mutex_unlock(&cam_obj->muxer_lock);
+        rc = mm_camera_set_dual_cam_cmd(my_obj);
+    } else {
+        pthread_mutex_unlock(&cam_obj->muxer_lock);
+    }
+    return rc;
+}
+
+/*===========================================================================
  * FUNCTION   : mm_camera_muxer_stream_frame_sync
  *
  * DESCRIPTION: Handle stream buffers for frame sync
diff --git a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
index fb332ae..70da3c0 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -37,6 +37,7 @@
 #include TIME_H
 #define IOCTL_H <SYSTEM_HEADER_PREFIX/ioctl.h>
 #include IOCTL_H
+#include <cutils/properties.h>
 
 // Camera dependencies
 #include "cam_semaphore.h"
@@ -86,8 +87,9 @@
                                       cam_dimension_t *dim,
                                       cam_padding_info_t *padding,
                                       cam_stream_buf_plane_info_t *buf_planes);
-int32_t mm_stream_calc_offset_post_view(cam_format_t fmt,
+int32_t mm_stream_calc_offset_post_view(cam_stream_info_t *stream_info,
                                       cam_dimension_t *dim,
+                                      cam_padding_info_t *padding,
                                       cam_stream_buf_plane_info_t *buf_planes);
 
 int32_t mm_stream_calc_offset_snapshot(cam_format_t fmt,
@@ -140,6 +142,9 @@
         mm_evt_paylod_reg_frame_sync *sync);
 int32_t mm_stream_trigger_frame_sync(mm_stream_t *my_obj, uint8_t start_sync);
 int32_t mm_stream_switch_stream_callback(mm_stream_t *my_obj);
+int32_t mm_stream_handle_cache_ops(mm_stream_t* my_obj,
+        mm_camera_buf_def_t* buf, bool deque);
+
 
 /*===========================================================================
  * FUNCTION   : mm_stream_notify_channel
@@ -1692,6 +1697,9 @@
         buf_info->buf->ts.tv_sec  = vb.timestamp.tv_sec;
         buf_info->buf->ts.tv_nsec = vb.timestamp.tv_usec * 1000;
         buf_info->buf->flags = vb.flags;
+        // Buffers are cleaned/invalidated when received by HAL
+        // Cache ops not required on DQBUF
+        buf_info->buf->cache_flags = 0;
 
         LOGH("VIDIOC_DQBUF buf_index %d, frame_idx %d, stream type %d, rc %d,"
                 "queued: %d, buf_type = %d flags = %d",
@@ -1708,15 +1716,9 @@
             mm_stream_read_user_buf(my_obj, buf_info);
         }
 
-        if ( NULL != my_obj->mem_vtbl.clean_invalidate_buf ) {
-            rc = my_obj->mem_vtbl.clean_invalidate_buf(idx,
-                my_obj->mem_vtbl.user_data);
-            if (0 > rc) {
-                LOGE("Clean invalidate cache failed on buffer index: %d",
-                     idx);
-            }
-        } else {
-            LOGE("Clean invalidate cache op not supported");
+        rc = mm_stream_handle_cache_ops(my_obj, buf_info->buf, TRUE);
+        if (rc != 0) {
+            LOGE("Error cleaning/invalidating the buffer");
         }
     }
 
@@ -1909,18 +1911,10 @@
     buffer.m.planes = &planes[0];
     buffer.length = (__u32)length;
 
-    if ( NULL != my_obj->mem_vtbl.invalidate_buf ) {
-        rc = my_obj->mem_vtbl.invalidate_buf(buffer.index,
-                                             my_obj->mem_vtbl.user_data);
-        if ( 0 > rc ) {
-            LOGE("Cache invalidate failed on buffer index: %d",
-                       buffer.index);
-            return rc;
-        }
-    } else {
-        LOGE("Cache invalidate op not added");
+    rc = mm_stream_handle_cache_ops(my_obj, buf, FALSE);
+    if (rc != 0) {
+        LOGE("Error cleaning/invalidating the buffer");
     }
-
     pthread_mutex_lock(&my_obj->buf_lock);
     my_obj->queued_buffer_count++;
     if (1 == my_obj->queued_buffer_count) {
@@ -2938,22 +2932,27 @@
  *              padding information
  *
  * PARAMETERS :
- *   @fmt     : image format
+ *   @stream_info  : Stream information
  *   @dim     : image dimension
+ *   @padding : Padding info
  *   @buf_planes : [out] buffer plane information
  *
  * RETURN     : int32_t type of status
  *              0  -- success
  *              -1 -- failure
  *==========================================================================*/
-int32_t mm_stream_calc_offset_post_view(cam_format_t fmt,
+int32_t mm_stream_calc_offset_post_view(cam_stream_info_t *stream_info,
                                       cam_dimension_t *dim,
+                                      cam_padding_info_t *padding,
                                       cam_stream_buf_plane_info_t *buf_planes)
 {
     int32_t rc = 0;
     int stride = 0, scanline = 0;
 
-    switch (fmt) {
+    uint32_t width_padding = 0;
+    uint32_t height_padding = 0;
+
+    switch (stream_info->fmt) {
     case CAM_FORMAT_YUV_420_NV12:
     case CAM_FORMAT_YUV_420_NV21:
     case CAM_FORMAT_Y_ONLY:
@@ -2963,8 +2962,16 @@
         /* 2 planes: Y + CbCr */
         buf_planes->plane_info.num_planes = 2;
 
-        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64);
-        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_64);
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            width_padding =  padding->width_padding;
+            height_padding = CAM_PAD_TO_2;
+        } else {
+            width_padding =  padding->width_padding;
+            height_padding = padding->height_padding;
+        }
+
+        stride = PAD_TO_SIZE(dim->width, width_padding);
+        scanline = PAD_TO_SIZE(dim->height, height_padding);
         buf_planes->plane_info.mp[0].offset = 0;
         buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
         buf_planes->plane_info.mp[0].offset_x = 0;
@@ -2974,8 +2981,8 @@
         buf_planes->plane_info.mp[0].width = dim->width;
         buf_planes->plane_info.mp[0].height = dim->height;
 
-        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_64);
-        scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_64);
+        stride = PAD_TO_SIZE(dim->width, width_padding);
+        scanline = PAD_TO_SIZE(dim->height / 2, height_padding);
         buf_planes->plane_info.mp[1].offset = 0;
         buf_planes->plane_info.mp[1].len =
             (uint32_t)(stride * scanline);
@@ -2995,8 +3002,16 @@
         /* 2 planes: Y + CbCr */
         buf_planes->plane_info.num_planes = 2;
 
-        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_32);
-        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_32);
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            width_padding =  CAM_PAD_TO_32;
+            height_padding = CAM_PAD_TO_32;
+        } else {
+            width_padding =  padding->width_padding;
+            height_padding = padding->height_padding;
+        }
+
+        stride = PAD_TO_SIZE(dim->width, width_padding);
+        scanline = PAD_TO_SIZE(dim->height, height_padding);
         buf_planes->plane_info.mp[0].offset = 0;
         buf_planes->plane_info.mp[0].len =
                 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
@@ -3007,8 +3022,8 @@
         buf_planes->plane_info.mp[0].width = dim->width;
         buf_planes->plane_info.mp[0].height = dim->height;
 
-        stride = PAD_TO_SIZE(dim->width / 2, CAM_PAD_TO_32) * 2;
-        scanline = PAD_TO_SIZE(dim->height / 2, CAM_PAD_TO_32);
+        stride = PAD_TO_SIZE(dim->width / 2, width_padding) * 2;
+        scanline = PAD_TO_SIZE(dim->height / 2, height_padding);
         buf_planes->plane_info.mp[1].offset = 0;
         buf_planes->plane_info.mp[1].len =
                 PAD_TO_SIZE((uint32_t)(stride * scanline), CAM_PAD_TO_4K);
@@ -3028,8 +3043,16 @@
         /* 3 planes: Y + Cr + Cb */
         buf_planes->plane_info.num_planes = 3;
 
-        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
-        scanline = PAD_TO_SIZE(dim->height, CAM_PAD_TO_2);
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            width_padding =  CAM_PAD_TO_16;
+            height_padding = CAM_PAD_TO_2;
+        } else {
+            width_padding =  padding->width_padding;
+            height_padding = padding->height_padding;
+        }
+
+        stride = PAD_TO_SIZE(dim->width, width_padding);
+        scanline = PAD_TO_SIZE(dim->height, height_padding);
         buf_planes->plane_info.mp[0].offset = 0;
         buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
         buf_planes->plane_info.mp[0].offset_x = 0;
@@ -3039,8 +3062,8 @@
         buf_planes->plane_info.mp[0].width = dim->width;
         buf_planes->plane_info.mp[0].height = dim->height;
 
-        stride = PAD_TO_SIZE(stride / 2, CAM_PAD_TO_16);
-        scanline = scanline / 2;
+        stride = PAD_TO_SIZE(stride / 2, width_padding);
+        scanline = PAD_TO_SIZE(stride / 2, height_padding);
         buf_planes->plane_info.mp[1].offset = 0;
         buf_planes->plane_info.mp[1].len =
             (uint32_t)(stride * scanline);
@@ -3072,8 +3095,13 @@
         /* 2 planes: Y + CbCr */
         buf_planes->plane_info.num_planes = 2;
 
-        stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
-        scanline = dim->height;
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            stride = PAD_TO_SIZE(dim->width, CAM_PAD_TO_16);
+            scanline = dim->height;
+        } else {
+            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
+            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
+        }
         buf_planes->plane_info.mp[0].offset = 0;
         buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
         buf_planes->plane_info.mp[0].offset_x = 0;
@@ -3100,11 +3128,16 @@
     case CAM_FORMAT_YUV_420_NV12_VENUS:
 #ifdef VENUS_PRESENT
         // using Venus
-        stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
-        scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, dim->width);
+            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12, dim->height);
+        } else {
+            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
+            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
+        }
 
         buf_planes->plane_info.frame_len =
-            VENUS_BUFFER_SIZE(COLOR_FMT_NV12, dim->width, dim->height);
+            VENUS_BUFFER_SIZE(COLOR_FMT_NV12, stride, scanline);
         buf_planes->plane_info.num_planes = 2;
         buf_planes->plane_info.mp[0].len = (uint32_t)(stride * scanline);
         buf_planes->plane_info.mp[0].offset = 0;
@@ -3114,8 +3147,13 @@
         buf_planes->plane_info.mp[0].scanline = scanline;
         buf_planes->plane_info.mp[0].width = dim->width;
         buf_planes->plane_info.mp[0].height = dim->height;
-        stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
-        scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            stride = VENUS_UV_STRIDE(COLOR_FMT_NV12, dim->width);
+            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV12, dim->height);
+        } else {
+            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
+            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
+        }
         buf_planes->plane_info.mp[1].len =
             buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
         buf_planes->plane_info.mp[1].offset = 0;
@@ -3133,8 +3171,13 @@
     case CAM_FORMAT_YUV_420_NV21_VENUS:
 #ifdef VENUS_PRESENT
         // using Venus
-        stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width);
-        scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height);
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            stride = VENUS_Y_STRIDE(COLOR_FMT_NV21, dim->width);
+            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV21, dim->height);
+        } else {
+            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
+            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
+        }
         buf_planes->plane_info.frame_len =
                 VENUS_BUFFER_SIZE(COLOR_FMT_NV21, dim->width, dim->height);
         buf_planes->plane_info.num_planes = 2;
@@ -3146,8 +3189,13 @@
         buf_planes->plane_info.mp[0].scanline = scanline;
         buf_planes->plane_info.mp[0].width = dim->width;
         buf_planes->plane_info.mp[0].height = dim->height;
-        stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width);
-        scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height);
+        if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+            stride = VENUS_UV_STRIDE(COLOR_FMT_NV21, dim->width);
+            scanline = VENUS_UV_SCANLINES(COLOR_FMT_NV21, dim->height);
+        } else {
+            stride = PAD_TO_SIZE(dim->width, padding->width_padding);
+            scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
+        }
         buf_planes->plane_info.mp[1].len =
                 buf_planes->plane_info.frame_len - buf_planes->plane_info.mp[0].len;
         buf_planes->plane_info.mp[1].offset = 0;
@@ -3167,8 +3215,13 @@
         {
             int meta_stride = 0,meta_scanline = 0;
             // using UBWC
-            stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
-            scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
+            if (stream_info->stream_type != CAM_STREAM_TYPE_OFFLINE_PROC) {
+                stride = VENUS_Y_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
+                scanline = VENUS_Y_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
+            } else {
+                stride = PAD_TO_SIZE(dim->width, padding->width_padding);
+                scanline = PAD_TO_SIZE(dim->height, padding->height_padding);
+            }
             meta_stride = VENUS_Y_META_STRIDE(COLOR_FMT_NV12_UBWC, dim->width);
             meta_scanline = VENUS_Y_META_SCANLINES(COLOR_FMT_NV12_UBWC, dim->height);
 
@@ -3215,7 +3268,7 @@
         break;
     default:
         LOGE("Invalid cam_format for preview %d",
-                    fmt);
+                    stream_info->fmt);
         rc = -1;
         break;
     }
@@ -4468,8 +4521,9 @@
                                            plns);
         break;
     case CAM_STREAM_TYPE_POSTVIEW:
-        rc = mm_stream_calc_offset_post_view(stream_info->fmt,
+        rc = mm_stream_calc_offset_post_view(stream_info,
                                            &stream_info->dim,
+                                           padding,
                                            plns);
         break;
     case CAM_STREAM_TYPE_SNAPSHOT:
@@ -4569,6 +4623,7 @@
 int32_t mm_stream_calc_offset(mm_stream_t *my_obj)
 {
     int32_t rc = 0;
+    uint32_t i;
 
     cam_dimension_t dim = my_obj->stream_info->dim;
     if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION &&
@@ -4589,8 +4644,9 @@
                                            &my_obj->stream_info->buf_planes);
         break;
     case CAM_STREAM_TYPE_POSTVIEW:
-      rc = mm_stream_calc_offset_post_view(my_obj->stream_info->fmt,
+      rc = mm_stream_calc_offset_post_view(my_obj->stream_info,
                                          &dim,
+                                         &my_obj->padding_info,
                                          &my_obj->stream_info->buf_planes);
       break;
     case CAM_STREAM_TYPE_SNAPSHOT:
@@ -4634,6 +4690,17 @@
     }
 
     my_obj->frame_offset = my_obj->stream_info->buf_planes.plane_info;
+    LOGH("Stream type %d num_planes %d", my_obj->stream_info->stream_type,
+            my_obj->frame_offset.num_planes);
+    for (i = 0; i < my_obj->frame_offset.num_planes; i++) {
+        LOGH("Plane %d, stride %d, scanline %d, width %d, height %d, \
+                length %d", i, my_obj->frame_offset.mp[i].stride,
+                my_obj->frame_offset.mp[i].scanline,
+                my_obj->frame_offset.mp[i].width,
+                my_obj->frame_offset.mp[i].height,
+                my_obj->frame_offset.mp[i].len);
+    }
+
     return rc;
 }
 
@@ -4853,3 +4920,84 @@
 
     return rc;
 }
+
+/*===========================================================================
+ * FUNCTION   : mm_stream_handle_cache_ops
+ *
+ * DESCRIPTION: handles cache ops of a stream buffer
+ *
+ * PARAMETERS :
+ *   @my_obj       : stream object
+ *   @buf     : ptr to a stream buffer
+ *   @deque  : specifies if enqueue or dequeue
+ *
+ * RETURN     : zero for success
+ *                  non-zero error value
+ *==========================================================================*/
+int32_t mm_stream_handle_cache_ops(mm_stream_t* my_obj,
+        mm_camera_buf_def_t* buf, bool deque)
+{
+    int32_t rc = 0;
+    if(!my_obj || !buf) {
+        LOGE("Error!! my_obj: %p, buf_info: %p", my_obj, buf);
+        rc = -1;
+        return rc;
+    }
+    if ((my_obj->mem_vtbl.clean_invalidate_buf  == NULL) ||
+            (my_obj->mem_vtbl.invalidate_buf  == NULL) ||
+            (my_obj->mem_vtbl.clean_buf  == NULL)) {
+        LOGI("Clean/Invalidate cache ops not supported %p %p %p",
+            my_obj->mem_vtbl.clean_invalidate_buf,
+            my_obj->mem_vtbl.invalidate_buf,
+            my_obj->mem_vtbl.clean_buf);
+        // Not a fatal error
+        rc = 0;
+        return rc;
+    }
+
+    // Modify clean and invalidate flags depending on cache ops for stream
+    switch (my_obj->stream_info->cache_ops) {
+        case CAM_STREAM_CACHE_OPS_CLEAR_FLAGS:
+            buf->cache_flags = 0;
+            break;
+        case CAM_STREAM_CACHE_OPS_DISABLED:
+            if (deque) {
+                buf->cache_flags = CPU_HAS_READ_WRITTEN;
+            }
+            else {
+                buf->cache_flags = CPU_HAS_READ;
+            }
+        case CAM_STREAM_CACHE_OPS_HONOUR_FLAGS:
+        default:
+            // Do not change flags
+            break;
+    }
+
+    if ((buf->cache_flags & CPU_HAS_READ_WRITTEN) ==
+        CPU_HAS_READ_WRITTEN) {
+        rc = my_obj->mem_vtbl.clean_invalidate_buf(
+                buf->buf_idx, my_obj->mem_vtbl.user_data);
+    } else if ((buf->cache_flags & CPU_HAS_READ) ==
+        CPU_HAS_READ) {
+        rc = my_obj->mem_vtbl.invalidate_buf(
+                buf->buf_idx, my_obj->mem_vtbl.user_data);
+    } else if ((buf->cache_flags & CPU_HAS_WRITTEN) ==
+        CPU_HAS_WRITTEN) {
+        rc = my_obj->mem_vtbl.clean_buf(
+                buf->buf_idx, my_obj->mem_vtbl.user_data);
+    }
+
+    LOGH("[CACHE_OPS] Stream type: %d buf index: %d cache ops flags: 0x%x",
+            buf->stream_type, buf->buf_idx, buf->cache_flags);
+
+    if (rc != 0) {
+        LOGE("Clean/Invalidate cache failed on buffer index: %d",
+                buf->buf_idx);
+    } else {
+       // Reset buffer cache flags after cache ops
+        buf->cache_flags = 0;
+    }
+
+    return rc;
+}
+
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h b/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h
index 1851b28..e4b6694 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h
@@ -242,9 +242,11 @@
     int8_t enable_CAC;
     int8_t enable_EZTune;
     int8_t enable_ir;
+    int8_t enable_shdr;
     mm_camera_queue_t pp_frames;
     mm_camera_stream_t *reproc_stream;
     metadata_buffer_t *metadata;
+    mm_jpeg_exif_params_t mExifParams;
     int8_t is_chromatix_reload;
 } mm_camera_test_obj_t;
 
@@ -320,6 +322,7 @@
     MM_CAMERA_LIB_SET_TINTLESS,
     MM_CAMERA_LIB_EZTUNE_ENABLE,
     MM_CAMERA_LIB_IRMODE,
+    MM_CAMERA_LIB_SHDR_MODE,
 } mm_camera_lib_commands;
 
 typedef struct {
@@ -386,6 +389,8 @@
 extern int mm_app_cache_ops(mm_camera_app_meminfo_t *mem_info, int cmd);
 extern int32_t mm_app_stream_clean_invalidate_buf(uint32_t index, void *user_data);
 extern int32_t mm_app_stream_invalidate_buf(uint32_t index, void *user_data);
+extern int32_t mm_app_stream_clean_buf(uint32_t index, void *user_data);
+
 extern int mm_app_open(mm_camera_app_t *cam_app,
                        int cam_id,
                        mm_camera_test_obj_t *test_obj);
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_main_menu.h b/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_main_menu.h
index e996078..9b6a019 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_main_menu.h
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/inc/mm_qcamera_main_menu.h
@@ -53,7 +53,7 @@
   STOP_PREVIEW,
   SET_WHITE_BALANCE,
   SET_TINTLESS_ENABLE,
-  SET_TINTLESS_DISABLE,
+  TOGGLE_SHDR,
   SET_EXP_METERING,
   TOGGLE_IRLED,
   TOGGLE_EZTUNE,
@@ -84,7 +84,7 @@
   ACTION_STOP_PREVIEW,
   ACTION_SET_WHITE_BALANCE,
   ACTION_SET_TINTLESS_ENABLE,
-  ACTION_SET_TINTLESS_DISABLE,
+  ACTION_TOGGLE_SHDR,
   ACTION_SET_EXP_METERING,
   ACTION_TOGGLE_IR_MODE,
   ACTION_TOGGLE_AFR,
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
index 3a3f057..1286d07 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
@@ -470,6 +470,12 @@
     return mm_app_cache_ops(&stream->s_bufs[index].mem_info, ION_IOC_INV_CACHES);
 }
 
+int32_t mm_app_stream_clean_buf(uint32_t index, void *user_data)
+{
+    mm_camera_stream_t *stream = (mm_camera_stream_t *)user_data;
+    return mm_app_cache_ops(&stream->s_bufs[index].mem_info, ION_IOC_CLEAN_CACHES);
+}
+
 static void notify_evt_cb(uint32_t camera_handle,
                           mm_camera_event_t *evt,
                           void *user_data)
@@ -580,6 +586,10 @@
         goto error_after_getparm_buf_map;
     }
     memset(&test_obj->jpeg_ops, 0, sizeof(mm_jpeg_ops_t));
+    test_obj->mExifParams.debug_params = \
+        (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
+    memset(test_obj->mExifParams.debug_params, 0,
+        sizeof(mm_jpeg_debug_exif_params_t));
     mm_dimension pic_size;
     memset(&pic_size, 0, sizeof(mm_dimension));
     pic_size.w = 4000;
@@ -692,6 +702,11 @@
         LOGE("release setparm buf failed, rc=%d",  rc);
     }
 
+    if (test_obj->mExifParams.debug_params) {
+        free(test_obj->mExifParams.debug_params);
+        test_obj->mExifParams.debug_params = NULL;
+   }
+
     return MM_CAMERA_OK;
 }
 
@@ -1096,6 +1111,33 @@
     return rc;
 }
 
+int updateDebuglevel(mm_camera_test_obj_t *test_obj)
+{
+
+    int rc = MM_CAMERA_OK;
+
+    rc = initBatchUpdate(test_obj);
+    if ( rc != MM_CAMERA_OK ) {
+        LOGE("Failed to initialize group update table");
+        return rc;
+    }
+
+    uint32_t dummyDebugLevel = 0;
+    if (ADD_SET_PARAM_ENTRY_TO_BATCH(test_obj->parm_buf.mem_info.data, CAM_INTF_PARM_UPDATE_DEBUG_LEVEL, dummyDebugLevel)) {
+        LOGE("Parameters batch failed");
+        rc = -1;
+        goto ERROR;
+    }
+
+    rc = commitSetBatch(test_obj);
+    if ( rc != MM_CAMERA_OK ) {
+        LOGE("Failed to commit batch parameters");
+        return rc;
+    }
+ERROR:
+    return rc;
+ }
+
 int setEVCompensation(mm_camera_test_obj_t *test_obj, int ev)
 {
     int rc = MM_CAMERA_OK;
@@ -1584,6 +1626,42 @@
     return rc;
 }
 
+int setsHDRMode(mm_camera_test_obj_t *test_obj, uint8_t shdr_mode)
+{
+    int rc = MM_CAMERA_OK;
+   cam_sensor_hdr_type_t vhdr_type = CAM_SENSOR_HDR_MAX;
+
+    rc = initBatchUpdate(test_obj);
+    if (rc != MM_CAMERA_OK) {
+        LOGE("Batch camera parameter update failed\n");
+        goto ERROR;
+    }
+
+   if (shdr_mode) {
+        vhdr_type = CAM_SENSOR_HDR_STAGGERED;
+   } else {
+        vhdr_type = CAM_SENSOR_HDR_OFF;
+   }
+    if (ADD_SET_PARAM_ENTRY_TO_BATCH(test_obj->parm_buf.mem_info.data,
+            CAM_INTF_PARM_SENSOR_HDR, vhdr_type)) {
+        LOGE("Flash parameter not added to batch\n");
+        rc = -1;
+        goto ERROR;
+    }
+
+    rc = commitSetBatch(test_obj);
+    if (rc != MM_CAMERA_OK) {
+        LOGE("Batch parameters commit failed\n");
+        goto ERROR;
+    }
+
+    LOGE("sHDR set to: %d",  (int)shdr_mode);
+
+ERROR:
+    return rc;
+}
+
+
 
 int setEZTune(mm_camera_test_obj_t *test_obj, uint8_t enable)
 {
@@ -1830,6 +1908,13 @@
       LOGE("autofocus error\n");
       goto EXIT;
     }
+
+    rc = updateDebuglevel(&handle->test_obj);
+
+    if (rc != MM_CAMERA_OK) {
+        LOGE("autofocus error\n");
+        goto EXIT;
+    }
     handle->stream_running = 1;
 
 EXIT:
@@ -1935,7 +2020,6 @@
                 }
             }
             break;
-
         case MM_CAMERA_LIB_IRMODE:
             if ( NULL != in_data) {
                 int enable_ir = *(( int * )in_data);
@@ -1950,6 +2034,20 @@
                 }
             }
             break;
+        case MM_CAMERA_LIB_SHDR_MODE:
+            if ( NULL != in_data) {
+                int enable_shdr= *(( int * )in_data);
+                if (enable_shdr != handle->test_obj.enable_ir) {
+                    handle->test_obj.enable_ir = enable_shdr;
+                    rc = setsHDRMode(&handle->test_obj, enable_shdr);
+                    if (rc != MM_CAMERA_OK) {
+                        LOGE("setHDR() err=%d\n",
+                                    rc);
+                        goto EXIT;
+                    }
+                }
+            }
+            break;
         case MM_CAMERA_LIB_FLASH:
             if ( NULL != in_data ) {
                 cam_flash_mode_t flash = *(( int * )in_data);
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c
index 29ae5a9..a310b40 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c
@@ -87,7 +87,7 @@
   {STOP_PREVIEW,               "Stop preview/video"},
   {SET_WHITE_BALANCE,          "Set white balance mode"},
   {SET_TINTLESS_ENABLE,        "Set Tintless Enable"},
-  {SET_TINTLESS_DISABLE,       "Set Tintless Disable"},
+  {TOGGLE_SHDR,                "Toggle sHDR Mode , Default is Off"},
   {SET_EXP_METERING,           "Set exposure metering mode"},
   {TOGGLE_IRLED,               "Toggle IR Mode, Default is Off"},
   {TOGGLE_EZTUNE,              "Toggle EZtune. Default EZTune Off"},
@@ -314,10 +314,9 @@
           LOGD("next_menu_id = MENU_ID_TINTLESSENABLE = %d\n", next_menu_id);
           break;
 
-        case SET_TINTLESS_DISABLE:
-          * action_id_ptr = ACTION_SET_TINTLESS_DISABLE;
-          next_menu_id = MENU_ID_MAIN;
-          LOGD("next_menu_id = MENU_ID_TINTLESSDISABLE = %d\n", next_menu_id);
+        case TOGGLE_SHDR:
+          * action_id_ptr = ACTION_TOGGLE_SHDR;
+          LOGD("next_menu_id = MENU_ID_TOGGLE SHDR = %d\n", next_menu_id);
           break;
 
         case SET_EXP_METERING:
@@ -1637,6 +1636,7 @@
     int isZSL = 0;
     int isezTune = 0;
     int isirmode = 0;
+    int isshdrmode = 0;
     uint8_t wnr_enabled = 0;
     mm_camera_lib_handle lib_handle;
     int num_cameras;
@@ -1751,19 +1751,6 @@
                 }
                 break;
 
-            case ACTION_SET_TINTLESS_DISABLE:
-                LOGD("Selection for the Tintless disable changes\n");
-                set_tintless = 0;
-                rc =  mm_camera_lib_send_command(&lib_handle,
-                                                 MM_CAMERA_LIB_SET_TINTLESS,
-                                                 &set_tintless,
-                                                 NULL);
-                if (rc != MM_CAMERA_OK) {
-                    LOGE("mm_camera_lib_send_command() err=%d\n",  rc);
-                    goto ERROR;
-                }
-                break;
-
             case ACTION_SET_EXP_METERING:
                 LOGD("Selection for the Exposure Metering changes\n");
                 set_exp_metering(&lib_handle, action_param);
@@ -1854,6 +1841,27 @@
                 }
                 break;
 
+
+            case ACTION_TOGGLE_SHDR:
+                LOGE("Select for SHDR Mode");
+                printf("SHDR Mode Toggle\n");
+                isshdrmode = !isshdrmode;
+                if (!isshdrmode) {
+                    printf("sHDR ON !!!");
+                } else {
+                    printf("sHDR OFF !!!");
+                }
+                rc = mm_camera_lib_send_command(&lib_handle,
+                                       MM_CAMERA_LIB_SHDR_MODE,
+                                       &isshdrmode,
+                                       NULL);
+                if (rc != MM_CAMERA_OK) {
+                    LOGE("mm_camera_lib_send_command() err=%d\n", rc);
+                    goto ERROR;
+                }
+                break;
+
+
             case ACTION_SET_ISO:
                 LOGD("Select for ISO changes\n");
                 set_iso(&lib_handle, action_param);
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
index 9703650..54714b2 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
@@ -100,9 +100,98 @@
         return;
     }
   }
+
   memcpy(pme->metadata, frame->buffer, sizeof(metadata_buffer_t));
 
   pMetadata = (metadata_buffer_t *)frame->buffer;
+
+  IF_META_AVAILABLE(uint32_t, flash_mode, CAM_INTF_META_FLASH_MODE, pMetadata) {
+      pme->mExifParams.sensor_params.flash_mode = (cam_flash_mode_t)*flash_mode;
+  }
+
+  IF_META_AVAILABLE(int32_t, flash_state, CAM_INTF_META_FLASH_STATE, pMetadata) {
+      pme->mExifParams.sensor_params.flash_state = (cam_flash_state_t) *flash_state;
+  }
+
+  IF_META_AVAILABLE(float, aperture_value, CAM_INTF_META_LENS_APERTURE, pMetadata) {
+      pme->mExifParams.sensor_params.aperture_value = *aperture_value;
+  }
+
+
+  IF_META_AVAILABLE(int32_t, wb_mode, CAM_INTF_PARM_WHITE_BALANCE, pMetadata) {
+      pme->mExifParams.cam_3a_params.wb_mode = (cam_wb_mode_type) *wb_mode;
+  }
+
+  IF_META_AVAILABLE(cam_sensor_params_t, sensor_params, CAM_INTF_META_SENSOR_INFO, pMetadata) {
+      pme->mExifParams.sensor_params = *sensor_params;
+  }
+
+  IF_META_AVAILABLE(cam_ae_exif_debug_t, ae_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_AE, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->ae_debug_params = *ae_exif_debug_params;
+          pme->mExifParams.debug_params->ae_debug_params_valid = TRUE;
+
+       }
+
+  }
+
+  IF_META_AVAILABLE(cam_awb_exif_debug_t, awb_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_AWB, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->awb_debug_params = *awb_exif_debug_params;
+          pme->mExifParams.debug_params->awb_debug_params_valid = TRUE;
+          LOGE("Storing AWB Metadata");
+      }
+  }
+
+  IF_META_AVAILABLE(cam_af_exif_debug_t, af_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_AF, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->af_debug_params = *af_exif_debug_params;
+          pme->mExifParams.debug_params->af_debug_params_valid = TRUE;
+      }
+  }
+
+  IF_META_AVAILABLE(cam_asd_exif_debug_t, asd_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_ASD, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->asd_debug_params = *asd_exif_debug_params;
+          pme->mExifParams.debug_params->asd_debug_params_valid = TRUE;
+      }
+  }
+
+  IF_META_AVAILABLE(cam_stats_buffer_exif_debug_t, stats_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_STATS, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->stats_debug_params = *stats_exif_debug_params;
+          pme->mExifParams.debug_params->stats_debug_params_valid = TRUE;
+      }
+  }
+
+  IF_META_AVAILABLE(cam_bestats_buffer_exif_debug_t, bestats_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_BESTATS, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->bestats_debug_params = *bestats_exif_debug_params;
+          pme->mExifParams.debug_params->bestats_debug_params_valid = TRUE;
+      }
+  }
+
+  IF_META_AVAILABLE(cam_bhist_buffer_exif_debug_t, bhist_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_BHIST, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->bhist_debug_params = *bhist_exif_debug_params;
+          pme->mExifParams.debug_params->bhist_debug_params_valid = TRUE;
+      }
+  }
+
+  IF_META_AVAILABLE(cam_q3a_tuning_info_t, q3a_tuning_exif_debug_params,
+          CAM_INTF_META_EXIF_DEBUG_3A_TUNING, pMetadata) {
+      if (pme->mExifParams.debug_params) {
+          pme->mExifParams.debug_params->q3a_tuning_debug_params = *q3a_tuning_exif_debug_params;
+          pme->mExifParams.debug_params->q3a_tuning_debug_params_valid = TRUE;
+      }
+  }
   IF_META_AVAILABLE(uint32_t, afState, CAM_INTF_META_AF_STATE, pMetadata) {
     if ((cam_af_state_t)(*afState) == CAM_AF_STATE_FOCUSED_LOCKED ||
             (cam_af_state_t)(*afState) == CAM_AF_STATE_NOT_FOCUSED_LOCKED) {
@@ -533,6 +622,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -631,6 +721,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.userdata = userdata;
@@ -696,6 +787,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -794,6 +886,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -867,7 +960,10 @@
 
     stream->s_config.mem_vtbl.get_bufs = mm_app_stream_initbuf;
     stream->s_config.mem_vtbl.put_bufs = mm_app_stream_deinitbuf;
+    stream->s_config.mem_vtbl.clean_invalidate_buf =
+      mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -952,6 +1048,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -1040,6 +1137,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c
index c68424b..5d52241 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_rdi.c
@@ -150,6 +150,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -211,6 +212,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_reprocess.c b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_reprocess.c
index 6bb7ec6..1658b80 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_reprocess.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_reprocess.c
@@ -137,6 +137,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c
index a3bc9f6..c214d3d 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_snapshot.c
@@ -113,18 +113,104 @@
     /* fill in sink img param */
     job.encode_job.dst_index = 0;
 
+    job.encode_job.hal_version = CAM_HAL_V1;
+    test_obj->mExifParams.sensor_params.sens_type = CAM_SENSOR_RAW;
+    job.encode_job.cam_exif_params = test_obj->mExifParams;
+    job.encode_job.cam_exif_params.debug_params =
+            (mm_jpeg_debug_exif_params_t *) malloc (sizeof(mm_jpeg_debug_exif_params_t));
+
+    if (test_obj->mExifParams.debug_params) {
+        memcpy(job.encode_job.cam_exif_params.debug_params,
+            test_obj->mExifParams.debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
+    }
+
+    job.encode_job.mobicat_mask = 2;
+
     if (test_obj->metadata != NULL) {
         job.encode_job.p_metadata = test_obj->metadata;
     } else {
         LOGE(" Metadata null, not set for jpeg encoding");
     }
 
+    if (NULL != job.encode_job.p_metadata && (job.encode_job.mobicat_mask > 0)) {
+
+       if (test_obj->mExifParams.debug_params) {
+           memcpy(job.encode_job.cam_exif_params.debug_params,
+                   test_obj->mExifParams.debug_params, (sizeof(mm_jpeg_debug_exif_params_t)));
+
+           /* Save a copy of mobicat params */
+           job.encode_job.p_metadata->is_mobicat_aec_params_valid =
+                    job.encode_job.cam_exif_params.cam_3a_params_valid;
+
+           if (job.encode_job.cam_exif_params.cam_3a_params_valid) {
+                    job.encode_job.p_metadata->mobicat_aec_params =
+                    job.encode_job.cam_exif_params.cam_3a_params;
+           }
+
+           /* Save a copy of 3A debug params */
+            job.encode_job.p_metadata->is_statsdebug_ae_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid;
+            job.encode_job.p_metadata->is_statsdebug_awb_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid;
+            job.encode_job.p_metadata->is_statsdebug_af_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->af_debug_params_valid;
+            job.encode_job.p_metadata->is_statsdebug_asd_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid;
+            job.encode_job.p_metadata->is_statsdebug_stats_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid;
+            job.encode_job.p_metadata->is_statsdebug_bestats_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid;
+            job.encode_job.p_metadata->is_statsdebug_bhist_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid;
+            job.encode_job.p_metadata->is_statsdebug_3a_tuning_params_valid =
+                    job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid;
+
+            if (job.encode_job.cam_exif_params.debug_params->ae_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_ae_data =
+                        job.encode_job.cam_exif_params.debug_params->ae_debug_params;
+            }
+            if (job.encode_job.cam_exif_params.debug_params->awb_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_awb_data =
+                        job.encode_job.cam_exif_params.debug_params->awb_debug_params;
+            }
+            if (job.encode_job.cam_exif_params.debug_params->af_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_af_data =
+                        job.encode_job.cam_exif_params.debug_params->af_debug_params;
+            }
+            if (job.encode_job.cam_exif_params.debug_params->asd_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_asd_data =
+                        job.encode_job.cam_exif_params.debug_params->asd_debug_params;
+            }
+            if (job.encode_job.cam_exif_params.debug_params->stats_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_stats_buffer_data =
+                        job.encode_job.cam_exif_params.debug_params->stats_debug_params;
+            }
+            if (job.encode_job.cam_exif_params.debug_params->bestats_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_bestats_buffer_data =
+                        job.encode_job.cam_exif_params.debug_params->bestats_debug_params;
+            }
+            if (job.encode_job.cam_exif_params.debug_params->bhist_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_bhist_data =
+                        job.encode_job.cam_exif_params.debug_params->bhist_debug_params;
+            }
+            if (job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params_valid) {
+                job.encode_job.p_metadata->statsdebug_3a_tuning_data =
+                        job.encode_job.cam_exif_params.debug_params->q3a_tuning_debug_params;
+            }
+        }
+
+    }
+
     rc = test_obj->jpeg_ops.start_job(&job, &test_obj->current_job_id);
     if ( 0 != rc ) {
         free(test_obj->current_job_frames);
         test_obj->current_job_frames = NULL;
     }
 
+    if (job.encode_job.cam_exif_params.debug_params) {
+        free(job.encode_job.cam_exif_params.debug_params);
+    }
+
     return rc;
 }
 
@@ -495,6 +581,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
diff --git a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c
index dd0b139..8a3644b 100644
--- a/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c
+++ b/msmcobalt/QCamera2/stack/mm-camera-test/src/mm_qcamera_video.c
@@ -363,6 +363,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
             mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -412,6 +413,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
       mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
@@ -505,6 +507,7 @@
     stream->s_config.mem_vtbl.clean_invalidate_buf =
             mm_app_stream_clean_invalidate_buf;
     stream->s_config.mem_vtbl.invalidate_buf = mm_app_stream_invalidate_buf;
+    stream->s_config.mem_vtbl.clean_buf = mm_app_stream_clean_buf;
     stream->s_config.mem_vtbl.user_data = (void *)stream;
     stream->s_config.stream_cb = stream_cb;
     stream->s_config.stream_cb_sync = NULL;
diff --git a/msmcobalt/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h b/msmcobalt/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
index 65c07d6..885a4b8 100644
--- a/msmcobalt/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
+++ b/msmcobalt/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
@@ -356,6 +356,9 @@
 
   /* src rotate img bufs */
   mm_jpeg_buf_t src_rot_main_buf[MM_JPEG_MAX_BUF];
+
+  /* lib2d handle*/
+  void *lib2d_handle;
 } mm_jpeg_job_session_t;
 
 typedef struct {
diff --git a/msmcobalt/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c b/msmcobalt/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
index d697d5b..1bc7138 100644
--- a/msmcobalt/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
+++ b/msmcobalt/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
@@ -153,38 +153,41 @@
     }
   }
 
-  if (p_session->lib2d_rotation_flag && p_session->thumb_from_main) {
-    for (i = 0; i < p_session->num_src_rot_bufs; i++) {
-      LOGD("Source rot buffer thumb %d", i);
-      lbuffer_info.fd = (OMX_U32)p_session->src_rot_main_buf[i].fd;
-      ret = OMX_UseBuffer(p_session->omx_handle,
-        &(p_session->p_in_rot_omx_thumb_buf[i]), 2,
-        &lbuffer_info, p_session->src_rot_main_buf[i].buf_size,
-        p_session->src_rot_main_buf[i].buf_vaddr);
-      if (ret) {
-        LOGE("Error %d", ret);
-        return ret;
+  if (p_session->params.encode_thumbnail) {
+    if (p_session->lib2d_rotation_flag && p_session->thumb_from_main) {
+      for (i = 0; i < p_session->num_src_rot_bufs; i++) {
+        LOGD("Source rot buffer thumb %d", i);
+        lbuffer_info.fd = (OMX_U32)p_session->src_rot_main_buf[i].fd;
+        ret = OMX_UseBuffer(p_session->omx_handle,
+          &(p_session->p_in_rot_omx_thumb_buf[i]), 2,
+          &lbuffer_info, p_session->src_rot_main_buf[i].buf_size,
+          p_session->src_rot_main_buf[i].buf_vaddr);
+        if (ret) {
+          LOGE("Error %d", ret);
+          return ret;
+        }
       }
-    }
-  } else {
-    for (i = 0; i < p_params->num_tmb_bufs; i++) {
-      LOGD("Source buffer %d", i);
-      lbuffer_info.fd = (OMX_U32)p_params->src_thumb_buf[i].fd;
-      ret = OMX_UseBuffer(p_session->omx_handle,
-        &(p_session->p_in_omx_thumb_buf[i]), 2,
-        &lbuffer_info, p_params->src_thumb_buf[i].buf_size,
-      p_params->src_thumb_buf[i].buf_vaddr);
-      if (ret) {
-        LOGE("Error %d", ret);
-        return ret;
+    } else {
+      for (i = 0; i < p_params->num_tmb_bufs; i++) {
+        LOGD("Source tmb buffer %d", i);
+        lbuffer_info.fd = (OMX_U32)p_params->src_thumb_buf[i].fd;
+        ret = OMX_UseBuffer(p_session->omx_handle,
+          &(p_session->p_in_omx_thumb_buf[i]), 2,
+          &lbuffer_info, p_params->src_thumb_buf[i].buf_size,
+        p_params->src_thumb_buf[i].buf_vaddr);
+        if (ret) {
+          LOGE("Error %d", ret);
+          return ret;
+        }
       }
     }
   }
 
   for (i = 0; i < p_params->num_dst_bufs; i++) {
     LOGD("Dest buffer %d", i);
+    lbuffer_info.fd = (OMX_U32)p_params->dest_buf[i].fd;
     ret = OMX_UseBuffer(p_session->omx_handle, &(p_session->p_out_omx_buf[i]),
-      1, NULL, p_params->dest_buf[i].buf_size,
+      1, &lbuffer_info, p_params->dest_buf[i].buf_size,
       p_params->dest_buf[i].buf_vaddr);
     if (ret) {
       LOGE("Error");
@@ -238,24 +241,26 @@
     }
   }
 
-  if (p_session->lib2d_rotation_flag && p_session->thumb_from_main) {
-    for (i = 0; i < p_session->num_src_rot_bufs; i++) {
-    LOGD("Source rot buffer thumb %d", i);
-      ret = OMX_FreeBuffer(p_session->omx_handle, 2,
+  if (p_session->params.encode_thumbnail) {
+    if (p_session->lib2d_rotation_flag && p_session->thumb_from_main) {
+      for (i = 0; i < p_session->num_src_rot_bufs; i++) {
+        LOGD("Source rot buffer thumb %d", i);
+        ret = OMX_FreeBuffer(p_session->omx_handle, 2,
         p_session->p_in_rot_omx_thumb_buf[i]);
-      if (ret) {
-        LOGE("Error %d", ret);
-        return ret;
+        if (ret) {
+          LOGE("Error %d", ret);
+          return ret;
+        }
       }
-    }
-  } else {
-    for (i = 0; i < p_params->num_tmb_bufs; i++) {
-      LOGD("Source buffer %d", i);
-      ret = OMX_FreeBuffer(p_session->omx_handle, 2,
-        p_session->p_in_omx_thumb_buf[i]);
-      if (ret) {
-        LOGE("Error %d", ret);
-        return ret;
+    } else {
+      for (i = 0; i < p_params->num_tmb_bufs; i++) {
+        LOGD("Source buffer %d", i);
+        ret = OMX_FreeBuffer(p_session->omx_handle, 2,
+          p_session->p_in_omx_thumb_buf[i]);
+        if (ret) {
+          LOGE("Error %d", ret);
+          return ret;
+        }
       }
     }
   }
@@ -2514,7 +2519,7 @@
  **/
 lib2d_error mm_jpeg_lib2d_rotation_cb(void *userdata, int jobid)
 {
-  LOGE("_GM_ Received CB from lib2d\n");
+  LOGD("Received CB from lib2d\n");
   return MM_LIB2D_SUCCESS;
 }
 
@@ -2538,7 +2543,6 @@
 int32_t mm_jpeg_lib2d_rotation(mm_jpeg_job_session_t *p_session,
   mm_jpeg_job_q_node_t* p_node, mm_jpeg_job_t *p_job, uint32_t *p_job_id)
 {
-  void *lib2d_handle = NULL;
   lib2d_error lib2d_err = MM_LIB2D_SUCCESS;
   mm_lib2d_buffer src_buffer;
   mm_lib2d_buffer dst_buffer;
@@ -2570,22 +2574,39 @@
       p_jobparams->main_dim.crop.height;
     p_jobparams_node->main_dim.crop.height =
       p_jobparams->main_dim.crop.width;
-    p_jobparams_node->main_dim.crop.left =
-      p_jobparams->main_dim.src_dim.height -
-      (p_jobparams->main_dim.crop.top +
-      p_jobparams->main_dim.crop.height);
+
+    if (p_jobparams->main_dim.crop.top ||
+      p_jobparams->main_dim.crop.height) {
+      p_jobparams_node->main_dim.crop.left =
+        p_jobparams->main_dim.src_dim.height -
+        (p_jobparams->main_dim.crop.top +
+        p_jobparams->main_dim.crop.height);
+    } else {
+      p_jobparams_node->main_dim.crop.left = 0;
+    }
     p_jobparams_node->main_dim.crop.top =
       p_jobparams->main_dim.crop.left;
     break;
   case 180:
-    p_jobparams_node->main_dim.crop.left =
-      p_jobparams->main_dim.src_dim.width -
-      (p_jobparams->main_dim.crop.left +
-      p_jobparams->main_dim.crop.width);
-    p_jobparams_node->main_dim.crop.top =
-      p_jobparams->main_dim.src_dim.height -
-      (p_jobparams->main_dim.crop.top +
-      p_jobparams->main_dim.crop.height);
+    if (p_jobparams->main_dim.crop.left ||
+      p_jobparams->main_dim.crop.width) {
+      p_jobparams_node->main_dim.crop.left =
+        p_jobparams->main_dim.src_dim.width -
+        (p_jobparams->main_dim.crop.left +
+        p_jobparams->main_dim.crop.width);
+    } else {
+      p_jobparams_node->main_dim.crop.left = 0;
+    }
+
+    if (p_jobparams->main_dim.crop.top ||
+      p_jobparams->main_dim.crop.height) {
+      p_jobparams_node->main_dim.crop.top =
+        p_jobparams->main_dim.src_dim.height -
+        (p_jobparams->main_dim.crop.top +
+        p_jobparams->main_dim.crop.height);
+    } else {
+      p_jobparams_node->main_dim.crop.top = 0;
+    }
     break;
   case 270:
     p_jobparams_node->main_dim.src_dim.width =
@@ -2604,21 +2625,25 @@
       p_jobparams->main_dim.crop.width;
     p_jobparams_node->main_dim.crop.left =
       p_jobparams->main_dim.crop.top;
-    p_jobparams_node->main_dim.crop.top =
-      p_jobparams->main_dim.src_dim.width -
-      (p_jobparams->main_dim.crop.left +
-      p_jobparams->main_dim.crop.width);
+    if (p_jobparams->main_dim.crop.left ||
+      p_jobparams->main_dim.crop.width) {
+      p_jobparams_node->main_dim.crop.top =
+        p_jobparams->main_dim.src_dim.width -
+        (p_jobparams->main_dim.crop.left +
+        p_jobparams->main_dim.crop.width);
+    } else {
+      p_jobparams_node->main_dim.crop.top = 0;
+    }
     break;
   }
 
-  format = mm_jpeg_get_imgfmt_from_colorfmt(p_session->params.color_format);
-  lib2d_err = mm_lib2d_init(MM_LIB2D_SYNC_MODE, format,
-    format, &lib2d_handle);
-  if (lib2d_err != MM_LIB2D_SUCCESS) {
-    LOGE("lib2d init for rotation failed\n");
-    return -1;
-  }
+  LOGD("crop wxh %dx%d txl %dx%d",
+    p_jobparams_node->main_dim.crop.width,
+    p_jobparams_node->main_dim.crop.height,
+    p_jobparams_node->main_dim.crop.top,
+    p_jobparams_node->main_dim.crop.left);
 
+  format = mm_jpeg_get_imgfmt_from_colorfmt(p_session->params.color_format);
   src_buffer.buffer_type = MM_LIB2D_BUFFER_TYPE_YUV;
   src_buffer.yuv_buffer.fd =
     p_src_main_buf[p_jobparams->src_index].fd;
@@ -2670,8 +2695,9 @@
 
   LOGD(" lib2d rotation = %d\n", p_session->params.rotation);
 
-  lib2d_err = mm_lib2d_start_job(lib2d_handle, &src_buffer, &dst_buffer,
-    *p_job_id, NULL, mm_jpeg_lib2d_rotation_cb, p_session->params.rotation);
+  lib2d_err = mm_lib2d_start_job(p_session->lib2d_handle, &src_buffer,
+    &dst_buffer, *p_job_id, NULL, mm_jpeg_lib2d_rotation_cb,
+    p_session->params.rotation);
   if (lib2d_err != MM_LIB2D_SUCCESS) {
     LOGE("Error in mm_lib2d_start_job \n");
     return -1;
@@ -3084,6 +3110,19 @@
     if (p_session->params.rotation) {
       LOGD("Enable lib2d rotation");
       p_session->lib2d_rotation_flag = 1;
+
+      cam_format_t lib2d_format;
+      lib2d_error lib2d_err = MM_LIB2D_SUCCESS;
+      lib2d_format =
+        mm_jpeg_get_imgfmt_from_colorfmt(p_session->params.color_format);
+      lib2d_err = mm_lib2d_init(MM_LIB2D_SYNC_MODE, lib2d_format,
+      lib2d_format, &p_session->lib2d_handle);
+      if (lib2d_err != MM_LIB2D_SUCCESS) {
+        LOGE("lib2d init for rotation failed\n");
+        rc = -1;
+        p_session->lib2d_rotation_flag = 0;
+        goto error2;
+      }
     } else {
       LOGD("Disable lib2d rotation");
       p_session->lib2d_rotation_flag = 0;
@@ -3306,6 +3345,17 @@
 
   /* abort the current session */
   mm_jpeg_session_abort(p_session);
+
+#ifdef LIB2D_ROTATION_ENABLE
+  lib2d_error lib2d_err = MM_LIB2D_SUCCESS;
+  if (p_session->lib2d_rotation_flag) {
+    lib2d_err = mm_lib2d_deinit(p_session->lib2d_handle);
+    if (lib2d_err != MM_LIB2D_SUCCESS) {
+      LOGE("Error in mm_lib2d_deinit \n");
+    }
+  }
+#endif
+
   mm_jpeg_session_destroy(p_session);
 
   p_cur_sess = p_session;
diff --git a/msmcobalt/QCamera2/stack/mm-lib2d-interface/src/mm_lib2d.c b/msmcobalt/QCamera2/stack/mm-lib2d-interface/src/mm_lib2d.c
index bd322d2..28ef27f 100644
--- a/msmcobalt/QCamera2/stack/mm-lib2d-interface/src/mm_lib2d.c
+++ b/msmcobalt/QCamera2/stack/mm-lib2d-interface/src/mm_lib2d.c
@@ -154,7 +154,6 @@
 int lib2d_callback_handler(void *userdata, img_frame_t *p_in_frame,
   img_frame_t *p_out_frame, img_meta_t *p_meta)
 {
-  mm_lib2d_obj *lib2d_obj = (mm_lib2d_obj *)userdata;
   lib2d_job_private_info *job_info = NULL;
 
   if (NULL == userdata) {
@@ -497,7 +496,6 @@
 {
   mm_lib2d_obj        *lib2d_obj  = (mm_lib2d_obj *)lib2d_obj_handle;
   int                  rc         = IMG_SUCCESS;
-  img_core_ops_t      *p_core_ops = &lib2d_obj->core_ops;
   img_component_ops_t *p_comp     = &lib2d_obj->comp;
 
   img_frame_t *p_in_frame = malloc(sizeof(img_frame_t));
diff --git a/msmcobalt/QCamera2/util/QCameraPerf.cpp b/msmcobalt/QCamera2/util/QCameraPerf.cpp
index e143f0f..6df51a6 100644
--- a/msmcobalt/QCamera2/util/QCameraPerf.cpp
+++ b/msmcobalt/QCamera2/util/QCameraPerf.cpp
@@ -64,9 +64,11 @@
         mPerfLockEnable(0),
         mPerfLockHandle(-1),
         mPerfLockHandleTimed(-1),
+        m_pPowerModule(NULL),
         mTimerSet(0),
         mPerfLockTimeout(0),
         mStartTimeofLock(0)
+
 {
 }