Merge "Camera3: Name HAL threads"
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index 513145b..0464b3a 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -635,6 +635,7 @@
             hw->waitAPIResult(QCAMERA_SM_EVT_PREPARE_SNAPSHOT, &apiResult);
             ret = apiResult.status;
         }
+        hw->mPrepSnapRun = true;
     }
 
     /* Regardless what the result value for prepare_snapshot,
@@ -1002,6 +1003,7 @@
       mFlashNeeded(false),
       mCaptureRotation(0),
       mIs3ALocked(false),
+      mPrepSnapRun(false),
       mZoomLevel(0),
       m_bIntEvtPending(false),
       mSnapshotJob(-1),
@@ -2293,6 +2295,61 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : processMTFDumps
+ *
+ * DESCRIPTION: process MTF jpeg dumps for refocus support
+ *
+ * PARAMETERS :
+ *   @evt     : payload of jpeg event, including information about jpeg encoding
+ *              status, jpeg size and so on.
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *
+ * NOTE       : none
+ *==========================================================================*/
+bool QCamera2HardwareInterface::processMTFDumps(qcamera_jpeg_evt_payload_t *evt)
+{
+   bool ret = true;
+   if (mParameters.isMTFRefocus()) {
+       int index = getOutputImageCount();
+       bool allFocusImage = (index == ((int)mParameters.MTFOutputCount()-1));
+       char name[CAM_FN_CNT];
+
+       camera_memory_t *jpeg_mem = NULL;
+       omx_jpeg_ouput_buf_t *jpeg_out = NULL;
+       uint32_t dataLen;
+       uint8_t *dataPtr;
+       if (!m_postprocessor.getJpegMemOpt()) {
+           dataLen = evt->out_data.buf_filled_len;
+           dataPtr = evt->out_data.buf_vaddr;
+       } else {
+           jpeg_out  = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
+           jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
+           dataPtr = (uint8_t *)jpeg_mem->data;
+           dataLen = jpeg_mem->size;
+       }
+
+       if (allFocusImage)  {
+           strncpy(name, "AllFocusImage", CAM_FN_CNT - 1);
+           index = -1;
+       } else {
+           strncpy(name, "0", CAM_FN_CNT - 1);
+       }
+       CAM_DUMP_TO_FILE("/data/local/multiTouchFocus", name, index, "jpg",
+               dataPtr, dataLen);
+       CDBG("%s:%d] Dump the image %d %d allFocusImage %d", __func__, __LINE__,
+               getOutputImageCount(), index, allFocusImage);
+       setOutputImageCount(getOutputImageCount() + 1);
+       if (!allFocusImage) {
+           ret = false;
+       }
+   }
+   return ret;
+}
+
+/*===========================================================================
  * FUNCTION   : configureAdvancedCapture
  *
  * DESCRIPTION: configure Advanced Capture.
@@ -2312,6 +2369,8 @@
     mParameters.setDisplayFrame(FALSE);
     if (mParameters.isUbiFocusEnabled()) {
         rc = configureAFBracketing();
+    } else if (mParameters.isMultiTouchFocusEnabled()) {
+        rc = configureMTFBracketing();
     } else if (mParameters.isOptiZoomEnabled()) {
         rc = configureOptiZoom();
     } else if (mParameters.isfssrEnabled()) {
@@ -2374,6 +2433,56 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : configureMTFBracketing
+ *
+ * DESCRIPTION: configure multi-touch focus AF Bracketing.
+ *
+ * PARAMETERS :
+ *   @enable  : bool flag if MTF should be enabled
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera2HardwareInterface::configureMTFBracketing(bool enable)
+{
+    int32_t rc = NO_ERROR;
+    cam_af_bracketing_t *mtf_bracketing_need;
+    mtf_bracketing_need = &mParameters.m_MTFBracketInfo;
+
+    //Enable AF Bracketing.
+    cam_af_bracketing_t afBracket;
+    memset(&afBracket, 0, sizeof(cam_af_bracketing_t));
+    afBracket.enable = enable;
+    afBracket.burst_count = mtf_bracketing_need->burst_count;
+
+    for(int8_t i = 0; i < MAX_AF_BRACKETING_VALUES; i++) {
+        if (mtf_bracketing_need->focus_steps[i] != -1) {
+           afBracket.focus_steps[i] = mtf_bracketing_need->focus_steps[i];
+        }
+        CDBG_HIGH("%s: MTF focus_step[%d] = %d",
+                  __func__, i, afBracket.focus_steps[i]);
+    }
+    //Send cmd to backend to set AF Bracketing for MTF.
+    rc = mParameters.commitMTFBracket(afBracket);
+    mParameters.m_currNumBufMTF = afBracket.burst_count;
+    if ( NO_ERROR != rc ) {
+        ALOGE("%s: cannot configure MTF bracketing", __func__);
+        return rc;
+    }
+    if (enable) {
+        mParameters.set3ALock(QCameraParameters::VALUE_TRUE);
+        mIs3ALocked = true;
+    }
+    if (!enable) {
+        mParameters.m_currNumBufMTF = 0;
+    }
+    //reset multi-touch focus parameters for next use.
+    mParameters.resetMultiTouchFocusParam();
+    return rc;
+}
+
+/*===========================================================================
  * FUNCTION   : configureFlashBracketing
  *
  * DESCRIPTION: configure Flash Bracketing.
@@ -2562,6 +2671,8 @@
 
     if(mParameters.isUbiFocusEnabled()) {
         rc = pChannel->startAdvancedCapture(MM_CAMERA_AF_BRACKETING);
+    } else if (mParameters.isMultiTouchFocusEnabled()) {
+        rc = pChannel->startAdvancedCapture(MM_CAMERA_MTF_BRACKETING);
     } else if (mParameters.isChromaFlashEnabled()) {
         rc = pChannel->startAdvancedCapture(MM_CAMERA_FLASH_BRACKETING);
     } else if (mParameters.isHDREnabled() || mParameters.isAEBracketEnabled()) {
@@ -2594,6 +2705,7 @@
     uint8_t numSnapshots = mParameters.getNumOfSnapshots();
 
     if (mParameters.isUbiFocusEnabled() ||
+            mParameters.isMultiTouchFocusEnabled() ||
             mParameters.isOptiZoomEnabled() ||
             mParameters.isfssrEnabled() ||
             mParameters.isHDREnabled() ||
@@ -2619,6 +2731,7 @@
                 return rc;
             }
             if (mParameters.isUbiFocusEnabled() ||
+                    mParameters.isMultiTouchFocusEnabled() ||
                     mParameters.isOptiZoomEnabled() ||
                     mParameters.isHDREnabled() ||
                     mParameters.isfssrEnabled() ||
@@ -2630,7 +2743,7 @@
                     return rc;
                 }
             }
-            if ( mLongshotEnabled ) {
+            if (mLongshotEnabled && mPrepSnapRun) {
                 mCameraHandle->ops->start_zsl_snapshot(
                         mCameraHandle->camera_handle,
                         pZSLChannel->getMyHandle());
@@ -2896,6 +3009,12 @@
         CDBG_HIGH("%s: Restoring previous zoom value!!",__func__);
         mParameters.setAndCommitZoom(mZoomLevel);
     }
+    if (mParameters.isMultiTouchFocusEnabled()) {
+        configureMTFBracketing(false);
+    }
+    if (mParameters.isMultiTouchFocusSelected()) {
+        mParameters.resetMultiTouchFocusParam();
+    }
     return NO_ERROR;
 }
 
@@ -3291,6 +3410,7 @@
                 }
             }
             rc = mParameters.setLongshotEnable(mLongshotEnabled);
+            mPrepSnapRun = false;
         } else {
             rc = NO_INIT;
         }
@@ -3300,13 +3420,14 @@
             cancelPicture();
             processEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE, NULL);
             QCameraChannel *pZSLChannel = m_channels[QCAMERA_CH_TYPE_ZSL];
-            if (isZSLMode() && (NULL != pZSLChannel)) {
+            if (isZSLMode() && (NULL != pZSLChannel) && mPrepSnapRun) {
                 mCameraHandle->ops->stop_zsl_snapshot(
                         mCameraHandle->camera_handle,
                         pZSLChannel->getMyHandle());
             }
         }
         CDBG_HIGH("%s: Longshot Disabled", __func__);
+        mPrepSnapRun = false;
         mLongshotEnabled = false;
         rc = mParameters.setLongshotEnable(mLongshotEnabled);
         break;
@@ -3598,6 +3719,7 @@
                 payload->out_data = *p_output;
             }
             obj->processUFDumps(payload);
+            obj->processMTFDumps(payload);
             obj->processEvt(QCAMERA_SM_EVT_JPEG_EVT_NOTIFY, payload);
         }
     } else {
@@ -3712,6 +3834,12 @@
         ret = sendEvtNotify(CAMERA_MSG_FOCUS,
                             (focus_data.focus_state == CAM_AF_FOCUSED)? true : false,
                             0);
+        // multi-touch focus feature, record current lens position when focused.
+        if (mParameters.isTouchFocusing() &&
+                focus_data.focus_state == CAM_AF_FOCUSED &&
+                mParameters.isMultiTouchFocusSelected()) {
+            mParameters.updateMTFInfo(focus_data.focus_pos);
+        }
         break;
     case CAM_FOCUS_MODE_CONTINOUS_VIDEO:
     case CAM_FOCUS_MODE_CONTINOUS_PICTURE:
@@ -4891,6 +5019,12 @@
         pp_config.feature_mask &= ~CAM_QCOM_FEATURE_UBIFOCUS;
     }
 
+    if(mParameters.isMultiTouchFocusEnabled()) {
+        pp_config.feature_mask |= CAM_QCOM_FEATURE_MULTI_TOUCH_FOCUS;
+    } else {
+        pp_config.feature_mask &= ~CAM_QCOM_FEATURE_MULTI_TOUCH_FOCUS;
+    }
+
     if(mParameters.isChromaFlashEnabled()) {
         pp_config.feature_mask |= CAM_QCOM_FEATURE_CHROMA_FLASH;
         //TODO: check flash value for captured image, then assign.
@@ -6087,15 +6221,18 @@
     }
 
     if (mParameters.isUbiFocusEnabled() |
+        mParameters.isMultiTouchFocusEnabled() |
         mParameters.isChromaFlashEnabled() |
         mParameters.isHDREnabled() |
         mParameters.isfssrEnabled() |
         mParameters.isOptiZoomEnabled()) {
-        CDBG_HIGH("%s: need reprocess for |UbiFocus=%d|ChramaFlash=%d|OptiZoom=%d|fssr=%d|",
-                                         __func__,
-                                         mParameters.isUbiFocusEnabled(),
-                                         mParameters.isChromaFlashEnabled(),
-                                         mParameters.isOptiZoomEnabled(),mParameters.isfssrEnabled());
+        CDBG_HIGH("%s: need reprocess for |UbiFocus=%d|ChramaFlash=%d"
+                  "|OptiZoom=%d|fssr=%d|MultiTouchFocus=%d",__func__,
+                  mParameters.isUbiFocusEnabled(),
+                  mParameters.isChromaFlashEnabled(),
+                  mParameters.isOptiZoomEnabled(),
+                  mParameters.isfssrEnabled(),
+                  mParameters.isMultiTouchFocusEnabled());
         pthread_mutex_unlock(&m_parm_lock);
         return true;
     }
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index 3b05c2c..143f898 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -437,7 +437,8 @@
     bool isZSLMode() {return mParameters.isZSLMode();};
     bool isHFRMode() {return mParameters.isHfrMode();};
     uint8_t numOfSnapshotsExpected() {
-        return mParameters.isUbiRefocus() ? 1 : mParameters.getNumOfSnapshots();};
+        return ((mParameters.isUbiRefocus() || mParameters.isMTFRefocus()) ?
+                1 : mParameters.getNumOfSnapshots());};
     bool isLongshotEnabled() { return mLongshotEnabled; };
     uint8_t getBufNumRequired(cam_stream_type_t stream_type);
     bool needFDMetadata(qcamera_ch_type_enum_t channel_type);
@@ -446,6 +447,7 @@
                             cam_dimension_t size);
     int32_t configureAdvancedCapture();
     int32_t configureAFBracketing(bool enable = true);
+    int32_t configureMTFBracketing(bool enable = true);
     int32_t configureFlashBracketing();
     int32_t startAdvancedCapture(QCameraPicChannel *pChannel);
     int32_t configureZSLHDRBracketing();
@@ -456,7 +458,7 @@
     inline void setOutputImageCount(uint32_t aCount) {mOutputCount = aCount;}
     inline uint32_t getOutputImageCount() {return mOutputCount;}
     bool processUFDumps(qcamera_jpeg_evt_payload_t *evt);
-
+    bool processMTFDumps(qcamera_jpeg_evt_payload_t *evt);
     static void copyList(cam_dimension_t* src_list,
                    cam_dimension_t* dst_list, uint8_t len);
     static void camEvtHandle(uint32_t camera_handle,
@@ -582,6 +584,7 @@
     int32_t mRedEye;
     int32_t mFlashPresence;
     bool mIs3ALocked;
+    bool mPrepSnapRun;
     int32_t mZoomLevel;
 
     //eztune variables for communication with eztune server at backend
diff --git a/QCamera2/HAL/QCameraParameters.cpp b/QCamera2/HAL/QCameraParameters.cpp
index 6fd09cc..b1872ac 100644
--- a/QCamera2/HAL/QCameraParameters.cpp
+++ b/QCamera2/HAL/QCameraParameters.cpp
@@ -136,6 +136,9 @@
 const char QCameraParameters::KEY_QC_SUPPORTED_SEE_MORE_MODES[] = "see-more-values";
 const char QCameraParameters::KEY_QC_TRUE_PORTRAIT[] = "true-portrait";
 const char QCameraParameters::KEY_QC_SUPPORTED_TRUE_PORTRAIT_MODES[] = "true-portrait-values";
+const char QCameraParameters::KEY_QC_MULTI_TOUCH_FOCUS[] = "multi-touch-focus";
+const char QCameraParameters::KEY_QC_SUPPORTED_MULTI_TOUCH_FOCUS_MODES[] =
+        "multi-touch-focus-values";
 const char QCameraParameters::KEY_QC_WB_MANUAL_CCT[] = "wb-manual-cct";
 const char QCameraParameters::KEY_QC_MIN_WB_CCT[] = "min-wb-cct";
 const char QCameraParameters::KEY_QC_MAX_WB_CCT[] = "max-wb-cct";
@@ -336,6 +339,10 @@
 const char QCameraParameters::FSSR_OFF[] = "FSSR-off";
 const char QCameraParameters::FSSR_ON[] = "FSSR-on";
 
+// Value for Multi-touch Focus setting.
+const char QCameraParameters::MULTI_TOUCH_FOCUS_OFF[] = "multi-touch-focus-off";
+const char QCameraParameters::MULTI_TOUCH_FOCUS_ON[] = "multi-touch-focus-on";
+
 // Values for FLIP settings.
 const char QCameraParameters::FLIP_MODE_OFF[] = "off";
 const char QCameraParameters::FLIP_MODE_V[] = "flip-v";
@@ -620,6 +627,11 @@
     { FSSR_ON,  1 }
 };
 
+const QCameraParameters::QCameraMap QCameraParameters::MULTI_TOUCH_FOCUS_MODES_MAP[] = {
+    { MULTI_TOUCH_FOCUS_OFF, 0 },
+    { MULTI_TOUCH_FOCUS_ON,  1 }
+};
+
 const QCameraParameters::QCameraMap QCameraParameters::CDS_MODES_MAP[] = {
     { CDS_MODE_OFF, CAM_CDS_MODE_OFF },
     { CDS_MODE_ON, CAM_CDS_MODE_ON },
@@ -684,6 +696,7 @@
       m_curFocusPos(-1),
       m_tempMap(),
       m_bAFBracketingOn(false),
+      m_bMultiTouchFocusOn(false),
       m_bChromaFlashOn(false),
       m_bOptiZoomOn(false),
       m_bFssrOn(false),
@@ -718,7 +731,15 @@
 
     memset(&m_LiveSnapshotSize, 0, sizeof(m_LiveSnapshotSize));
     memset(&m_default_fps_range, 0, sizeof(m_default_fps_range));
+    memset(&m_MTFBracketInfo, 0, sizeof(m_MTFBracketInfo));
     memset(&m_hfrFpsRange, 0, sizeof(m_hfrFpsRange));
+
+    // init focus steps to -1, invalid steps
+    for (int i = 0; i < MAX_AF_BRACKETING_VALUES; i++) {
+       m_MTFBracketInfo.focus_steps[i] = -1;
+    }
+
+    m_currNumBufMTF = 0;
 }
 
 /*===========================================================================
@@ -768,6 +789,7 @@
     m_bHDROutputCropEnabled(false),
     m_tempMap(),
     m_bAFBracketingOn(false),
+    m_bMultiTouchFocusOn(false),
     m_bChromaFlashOn(false),
     m_bOptiZoomOn(false),
     m_bFssrOn(false),
@@ -783,8 +805,15 @@
     memset(&m_LiveSnapshotSize, 0, sizeof(m_LiveSnapshotSize));
     m_pTorch = NULL;
     m_bReleaseTorchCamera = false;
+    m_currNumBufMTF = 0;
     memset(&m_default_fps_range, 0, sizeof(m_default_fps_range));
     memset(&m_hfrFpsRange, 0, sizeof(m_hfrFpsRange));
+    memset(&m_MTFBracketInfo, 0, sizeof(m_MTFBracketInfo));
+
+    // init focus steps to -1, invalid steps
+    for (int i = 0; i < MAX_AF_BRACKETING_VALUES; i++) {
+       m_MTFBracketInfo.focus_steps[i] = -1;
+    }
 }
 
 /*===========================================================================
@@ -3151,6 +3180,165 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : setMultiTouchFocus
+ *
+ * DESCRIPTION: set multi-touch focus value
+ *
+ * PARAMETERS :
+ *   @multiTouchFocusStr : multi-touch focus value string
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraParameters::setMultiTouchFocus(const char *multiTouchFocusStr)
+{
+    if(multiTouchFocusStr != NULL) {
+        int value = lookupAttr(MULTI_TOUCH_FOCUS_MODES_MAP,
+                            sizeof(MULTI_TOUCH_FOCUS_MODES_MAP)/sizeof(QCameraMap),
+                            multiTouchFocusStr);
+        if(value != NAME_NOT_FOUND) {
+            m_bMultiTouchFocusOn = (value != 0);
+            if (!m_bMultiTouchFocusOn) {
+                resetMultiTouchFocusParam();
+            }
+            updateParamEntry(KEY_QC_MULTI_TOUCH_FOCUS, multiTouchFocusStr);
+            return NO_ERROR;
+        }
+    }
+    CDBG_HIGH("Invalid multi-touch focus value: %s",
+            (multiTouchFocusStr == NULL) ? "NULL" : multiTouchFocusStr);
+    return BAD_VALUE;
+}
+
+/*===========================================================================
+ * FUNCTION   : setMultiTouchFocus
+ *
+ * DESCRIPTION: set multi-touch focus af bracket from user setting
+ *
+ * PARAMETERS :
+ *   @params  : user setting parameters
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraParameters::setMultiTouchFocus(const QCameraParameters& params)
+{
+    if ((m_pCapability->qcom_supported_feature_mask &
+        CAM_QCOM_FEATURE_MULTI_TOUCH_FOCUS) == 0) {
+        CDBG_HIGH("%s: multi-touch focus is not supported",__func__);
+        return NO_ERROR;
+    }
+    const char *str = params.get(KEY_QC_MULTI_TOUCH_FOCUS);
+    const char *prev_str = get(KEY_QC_MULTI_TOUCH_FOCUS);
+    CDBG_HIGH("%s: str =%s & prev_str =%s",__func__, str, prev_str);
+    if (str != NULL) {
+        if (prev_str == NULL || strcmp(str, prev_str) != 0) {
+            m_bNeedRestart = true;
+            return setMultiTouchFocus(str);
+        }
+    }
+    return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION   : setTouchAFAEC
+ *
+ * DESCRIPTION: set touch af aec value
+ *
+ * PARAMETERS :
+ *   @touchAfAecStr : touch focus value string
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraParameters::setTouchAFAEC(const char *touchAfAecStr)
+{
+    if (touchAfAecStr != NULL) {
+        int value = lookupAttr(TOUCH_AF_AEC_MODES_MAP,
+                               sizeof(TOUCH_AF_AEC_MODES_MAP)/sizeof(QCameraMap),
+                               touchAfAecStr);
+        if (value != NAME_NOT_FOUND) {
+            m_bTouchFocusOn = (value != 0);
+            updateParamEntry(KEY_QC_TOUCH_AF_AEC, touchAfAecStr);
+            return NO_ERROR;
+        }
+    }
+    CDBG_HIGH("Invalid touch af aec value: %s",
+            (touchAfAecStr == NULL) ? "NULL" : touchAfAecStr);
+    return BAD_VALUE;
+}
+
+/*===========================================================================
+ * FUNCTION   : setTouchAFAEC
+ *
+ * DESCRIPTION: set touch AF from user setting
+ *
+ * PARAMETERS :
+ *   @params  : user setting parameters
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraParameters::setTouchAFAEC(const QCameraParameters& params)
+{
+    const char *str = params.get(KEY_QC_TOUCH_AF_AEC);
+    const char *prev_str = get(KEY_QC_TOUCH_AF_AEC);
+    CDBG("%s: str =%s & prev_str =%s",__func__, str, prev_str);
+    if (str != NULL) {
+        if (prev_str == NULL || strcmp(str, prev_str) != 0) {
+            return setTouchAFAEC(str);
+        }
+    }
+    return NO_ERROR;
+}
+
+/*===========================================================================
+ * FUNCTION   : updateMTFInfo
+ *
+ * DESCRIPTION: update lens position selected by user
+ *
+ * PARAMETERS :
+ *   @lensPos : current lens position to add into array
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+
+int32_t QCameraParameters::updateMTFInfo(const int32_t lensPos)
+{
+   CDBG_HIGH("%s: current lens position is: %d, burst count = %d",
+           __func__, lensPos, m_MTFBracketInfo.burst_count);
+   if (m_MTFBracketInfo.burst_count >= MAX_AF_BRACKETING_VALUES) {
+       return BAD_VALUE;
+   }
+   if (m_MTFBracketInfo.burst_count == 0) {
+       m_MTFBracketInfo.focus_steps[0] = lensPos;
+   } else {
+      for (int i = 0; i < m_MTFBracketInfo.burst_count; i++) {
+         if (lensPos > m_MTFBracketInfo.focus_steps[i]) {
+            for (int j = m_MTFBracketInfo.burst_count; j > i; j--) {
+               m_MTFBracketInfo.focus_steps[j] = m_MTFBracketInfo.focus_steps[j-1];
+            }
+            m_MTFBracketInfo.focus_steps[i] = lensPos;
+            break;
+         }
+      }
+   }
+   for (int i = 0; i < MAX_AF_BRACKETING_VALUES; i++) {
+      CDBG_HIGH("%s: current focus_step[%d] = %d", __func__, i,
+          m_MTFBracketInfo.focus_steps[i]);
+   }
+
+   m_MTFBracketInfo.burst_count++;
+   return NO_ERROR;
+}
+
+/*===========================================================================
  * FUNCTION   : setChromaFlash
  *
  * DESCRIPTION: set chroma flash from user setting
@@ -3988,6 +4176,8 @@
     if ((rc = setOptiZoom(params)))                     final_rc = rc;
     if ((rc = setFssr(params)))                         final_rc = rc;
     if ((rc = setSeeMore(params)))                      final_rc = rc;
+    if ((rc = setMultiTouchFocus(params)))              final_rc = rc;
+    if ((rc = setTouchAFAEC(params)))                   final_rc = rc;
     if ((rc = setLongshotParam(params)))                final_rc = rc;
     if ((rc = setTruePortrait(params)))                 final_rc = rc;
 
@@ -4484,6 +4674,16 @@
         setFssr(FSSR_OFF);
     }
 
+    //Set Multi-touch Focus.
+    if ((m_pCapability->qcom_supported_feature_mask &
+            CAM_QCOM_FEATURE_MULTI_TOUCH_FOCUS) > 0){
+        String8 multiTouchFocusValues = createValuesStringFromMap(
+                MULTI_TOUCH_FOCUS_MODES_MAP,
+                sizeof(MULTI_TOUCH_FOCUS_MODES_MAP) / sizeof(QCameraMap));
+        set(KEY_QC_SUPPORTED_MULTI_TOUCH_FOCUS_MODES, multiTouchFocusValues);
+        setMultiTouchFocus(MULTI_TOUCH_FOCUS_OFF);
+    }
+
     // Set Denoise
     if ((m_pCapability->qcom_supported_feature_mask & CAM_QCOM_FEATURE_DENOISE2D) > 0){
     String8 denoiseValues = createValuesStringFromMap(
@@ -6485,8 +6685,8 @@
             }
             int32_t focus_mode;
             if (value == 1) {
-                if (isUbiFocusEnabled()) {
-                    //For Ubi focus move focus to infinity.
+                if (isUbiFocusEnabled() || isMultiTouchFocusEnabled()) {
+                    //For Ubi focus and Multi-touch Focus move focus to infinity.
                     focus_mode = CAM_FOCUS_MODE_INFINITY;
                 } else if (isOptiZoomEnabled() || isfssrEnabled()){
                     //For optizoom set focus as fixed.
@@ -6616,6 +6816,25 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : isMultiTouchFocusEnabled
+ *
+ * DESCRIPTION: checks whether Multi-touch Focus is enabled
+ *
+ * PARAMETERS :
+ *
+ * RETURN     : true - enabled, false - disabled
+ *
+ *==========================================================================*/
+bool QCameraParameters::isMultiTouchFocusEnabled()
+{
+    if (m_bMultiTouchFocusOn &&
+            (m_MTFBracketInfo.burst_count > 1 || m_currNumBufMTF > 1)) {
+       return true;
+    }
+    return false;
+}
+
+/*===========================================================================
  * FUNCTION   : commitAFBracket
  *
  * DESCRIPTION: commit AF Bracket.
@@ -6654,6 +6873,60 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : commitMTFBracket
+ *
+ * DESCRIPTION: commit multi-touch focus Bracket.
+ *
+ * PARAMETERS :
+ *   @mtfBracket : AF bracketing configuration
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraParameters::commitMTFBracket(cam_af_bracketing_t mtfBracket)
+{
+    int32_t rc = NO_ERROR;
+    if (initBatchUpdate(m_pParamBuf) < 0 ) {
+        ALOGE("%s:Failed to initialize group update table", __func__);
+        return BAD_TYPE;
+    }
+
+    rc = AddSetParmEntryToBatch(m_pParamBuf,
+            CAM_INTF_PARM_MULTI_TOUCH_FOCUS_BRACKETING,
+            sizeof(mtfBracket),
+            &mtfBracket);
+    if (rc != NO_ERROR) {
+        ALOGE("%s:Failed to update table", __func__);
+        return rc;
+    }
+
+    rc = commitSetBatch();
+    if (rc != NO_ERROR) {
+        ALOGE("%s:Failed to commit batch", __func__);
+    }
+
+    return rc;
+}
+
+/*===========================================================================
+ * FUNCTION   : resetMultiTouchFocusParam
+ *
+ * DESCRIPTION: reset MTF params to invalid state.
+ *
+ * PARAMETERS :
+ *
+ * RETURN     :
+ *==========================================================================*/
+void QCameraParameters::resetMultiTouchFocusParam()
+{
+    m_MTFBracketInfo.burst_count = 0;
+    for (int i = 0; i < MAX_AF_BRACKETING_VALUES; i++) {
+        m_MTFBracketInfo.focus_steps[i] = -1;
+    }
+}
+
+/*===========================================================================
  * FUNCTION   : commitFlashBracket
  *
  * DESCRIPTION: commit Flash Bracket.
@@ -7747,13 +8020,28 @@
     }
 
     /* update the count for refocus */
-    if (isUbiRefocus())
+   if (isUbiRefocus()) {
        numOfSnapshot += UfOutputCount();
+   }
 
     return (uint8_t)numOfSnapshot;
 }
 
 /*===========================================================================
+ * FUNCTION   : MTFOutputCount
+ *
+ * DESCRIPTION: find # of output for MTF feature
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : # of output for MTF feature
+ *==========================================================================*/
+uint32_t QCameraParameters::MTFOutputCount()
+{
+   return m_currNumBufMTF+1;
+}
+
+/*===========================================================================
  * FUNCTION   : getBurstCountForAdvancedCapture
  *
  * DESCRIPTION: get burst count for advanced capture.
@@ -7778,6 +8066,9 @@
         //number of snapshots required for Chroma Flash.
         //TODO: remove hardcoded value, add in capability.
         burstCount = 2;
+    } else if (isMultiTouchFocusEnabled()) {
+        //number of snapshots required by multi-touch focus.
+        burstCount = m_currNumBufMTF;
     } else if (isHDREnabled()) {
         //number of snapshots required for HDR.
         burstCount = m_pCapability->hdr_bracketing_setting.num_frames;
@@ -9580,11 +9871,13 @@
 bool QCameraParameters::needThumbnailReprocess(uint32_t *pFeatureMask)
 {
     if (isUbiFocusEnabled() || isChromaFlashEnabled() ||
-        isOptiZoomEnabled() || isfssrEnabled()) {
+            isOptiZoomEnabled() || isfssrEnabled() ||
+            isMultiTouchFocusEnabled()) {
         *pFeatureMask &= ~CAM_QCOM_FEATURE_CHROMA_FLASH;
         *pFeatureMask &= ~CAM_QCOM_FEATURE_UBIFOCUS;
         *pFeatureMask &= ~CAM_QCOM_FEATURE_OPTIZOOM;
         *pFeatureMask &= ~CAM_QCOM_FEATURE_FSSR;
+        *pFeatureMask &= ~CAM_QCOM_FEATURE_MULTI_TOUCH_FOCUS;
         return false;
     } else {
         return true;
@@ -9611,6 +9904,11 @@
             numOfBufs +=
                 m_pCapability->ubifocus_af_bracketing_need.burst_count + 1;
         }
+    } else if (isMultiTouchFocusEnabled()) {
+        numOfBufs += m_currNumBufMTF - 1;
+        if (isMTFRefocus()) {
+            numOfBufs += m_currNumBufMTF + 1;
+        }
     } else if (m_bOptiZoomOn) {
         numOfBufs += m_pCapability->opti_zoom_settings_need.burst_count - 1;
     } else if (isChromaFlashEnabled()) {
diff --git a/QCamera2/HAL/QCameraParameters.h b/QCamera2/HAL/QCameraParameters.h
index 8522dfc..e09632f 100644
--- a/QCamera2/HAL/QCameraParameters.h
+++ b/QCamera2/HAL/QCameraParameters.h
@@ -291,6 +291,10 @@
     //ZSL+HDR
     static const char KEY_QC_ZSL_HDR_SUPPORTED[];
 
+    //Multi-touch Focus
+    static const char KEY_QC_MULTI_TOUCH_FOCUS[];
+    static const char KEY_QC_SUPPORTED_MULTI_TOUCH_FOCUS_MODES[];
+
     // Values for Touch AF/AEC
     static const char TOUCH_AF_AEC_OFF[];
     static const char TOUCH_AF_AEC_ON[];
@@ -467,6 +471,10 @@
     static const char TRUE_PORTRAIT_OFF[];
     static const char TRUE_PORTRAIT_ON[];
 
+    // Values for Multi-touch Focus settings
+    static const char MULTI_TOUCH_FOCUS_OFF[];
+    static const char MULTI_TOUCH_FOCUS_ON[];
+
     // Values for HFR settings.
     static const char VIDEO_HFR_OFF[];
     static const char VIDEO_HFR_2X[];
@@ -628,6 +636,10 @@
     uint8_t getNumOfExtraBuffersForPreview();
     bool needThumbnailReprocess(uint32_t *pFeatureMask);
     inline bool isUbiFocusEnabled() {return m_bAFBracketingOn;};
+    inline bool isMultiTouchFocusSelected() {return m_bMultiTouchFocusOn;};
+    bool isMultiTouchFocusEnabled();
+    void resetMultiTouchFocusParam();
+    inline bool isTouchFocusing() {return m_bTouchFocusOn;};
     inline bool isChromaFlashEnabled() {return m_bChromaFlashOn;};
     inline bool isSeeMoreEnabled() {return m_bSeeMoreOn;};
     inline bool isTruePortraitEnabled() {return m_bTruePortraitOn;};
@@ -641,6 +653,7 @@
     bool isfssrEnabled() {return m_bFssrOn;};
     bool isDifferentFlipZSL();
     int32_t commitAFBracket(cam_af_bracketing_t afBracket);
+    int32_t commitMTFBracket(cam_af_bracketing_t mtfBracket);
     int32_t commitFlashBracket(cam_flash_bracketing_t flashBracket);
     int32_t set3ALock(const char *lockStr);
     int32_t setAndCommitZoom(int zoom_level);
@@ -650,13 +663,21 @@
         (m_pCapability->ubifocus_af_bracketing_need.output_count > 1);};
     inline uint32_t UfOutputCount() {
         return m_pCapability->ubifocus_af_bracketing_need.output_count;};
+    inline bool isMTFRefocus() {return (isMultiTouchFocusEnabled() &&
+            (m_pCapability->mtf_af_bracketing_parm.output_count > 1));};
+    uint32_t MTFOutputCount();
     inline bool generateThumbFromMain() {return isUbiFocusEnabled() ||
-        isChromaFlashEnabled() || isOptiZoomEnabled() || isDifferentFlipZSL() || isfssrEnabled(); }
+            isChromaFlashEnabled() || isOptiZoomEnabled() || isDifferentFlipZSL() ||
+            isfssrEnabled() || isMultiTouchFocusEnabled();}
+    cam_af_bracketing_t m_MTFBracketInfo;
+    int32_t updateMTFInfo(const int32_t lenPos);
+    uint8_t m_currNumBufMTF;
     int32_t  updateCurrentFocusPosition(int32_t pos);
     bool isDisplayFrameNeeded() { return m_bDisplayFrame; };
     int32_t setDisplayFrame(bool enabled) {m_bDisplayFrame=enabled; return 0;};
     bool isAdvCamFeaturesEnabled() {return isUbiFocusEnabled() ||
-        isChromaFlashEnabled() || isOptiZoomEnabled() || isHDREnabled() || isfssrEnabled();}
+            isChromaFlashEnabled() || isOptiZoomEnabled() || isHDREnabled() ||
+            isfssrEnabled() || isMultiTouchFocusEnabled();}
     int32_t setIntEvent(cam_int_evt_params_t params);
 
 private:
@@ -706,6 +727,8 @@
     int32_t setSelectableZoneAf(const QCameraParameters& );
     int32_t setAEBracket(const QCameraParameters& );
     int32_t setAFBracket(const QCameraParameters& );
+    int32_t setMultiTouchFocus(const QCameraParameters& );
+    int32_t setTouchAFAEC(const QCameraParameters& params);
     int32_t setChromaFlash(const QCameraParameters& );
     int32_t setOptiZoom(const QCameraParameters& );
     int32_t setTruePortrait(const QCameraParameters& );
@@ -768,6 +791,8 @@
     int32_t setSelectableZoneAf(const char *selZoneAFStr);
     int32_t setAEBracket(const char *aecBracketStr);
     int32_t setAFBracket(const char *afBracketStr);
+    int32_t setMultiTouchFocus(const char *multiTouchFocusStr);
+    int32_t setTouchAFAEC(const char *touchAfAecStr);
     int32_t setChromaFlash(const char *chromaFlashStr);
     int32_t setOptiZoom(const char *optiZoomStr);
     int32_t setTruePortrait(const char *truePortraitStr);
@@ -845,6 +870,7 @@
     static const QCameraMap OPTI_ZOOM_MODES_MAP[];
     static const QCameraMap TRUE_PORTRAIT_MODES_MAP[];
     static const QCameraMap FSSR_MODES_MAP[];
+    static const QCameraMap MULTI_TOUCH_FOCUS_MODES_MAP[];
     static const QCameraMap CDS_MODES_MAP[];
     static const QCameraMap SEE_MORE_MODES_MAP[];
 
@@ -899,6 +925,8 @@
     cam_fps_range_t m_default_fps_range;
 
     bool m_bAFBracketingOn;
+    bool m_bMultiTouchFocusOn;
+    bool m_bTouchFocusOn;
     bool m_bChromaFlashOn;
     bool m_bOptiZoomOn;
     bool m_bFssrOn;
diff --git a/QCamera2/HAL/QCameraPostProc.cpp b/QCamera2/HAL/QCameraPostProc.cpp
index 7ad30df..1b4c1d2 100644
--- a/QCamera2/HAL/QCameraPostProc.cpp
+++ b/QCamera2/HAL/QCameraPostProc.cpp
@@ -833,9 +833,12 @@
         }
 
         /* check if the all the captures are done */
-        if (m_parent->mParameters.isUbiRefocus() &&
+        if ((m_parent->mParameters.isUbiRefocus() &&
             (m_parent->getOutputImageCount() <
-            m_parent->mParameters.UfOutputCount())) {
+            m_parent->mParameters.UfOutputCount()))
+            || (m_parent->mParameters.isMTFRefocus()
+            && (m_parent->getOutputImageCount() <
+            m_parent->mParameters.MTFOutputCount()))) {
             jpeg_out  = (omx_jpeg_ouput_buf_t*) evt->out_data.buf_vaddr;
             jpeg_mem = (camera_memory_t *)jpeg_out->mem_hdl;
             if (NULL != jpeg_mem) {
@@ -1636,6 +1639,7 @@
     bool hdr_output_crop = m_parent->mParameters.isHDROutputCropEnabled();
     bool img_feature_enabled =
       m_parent->mParameters.isUbiFocusEnabled() ||
+      m_parent->mParameters.isMultiTouchFocusEnabled() ||
       m_parent->mParameters.isChromaFlashEnabled() ||
       m_parent->mParameters.isOptiZoomEnabled() ||
       m_parent->mParameters.isfssrEnabled();
@@ -1670,10 +1674,18 @@
                mem, imgProp.size);
            /* dump image */
            if (mem && mem->data) {
-               CAM_DUMP_TO_FILE("/data/local/ubifocus", "DepthMapImage",
-                                -1, "y",
-                                (uint8_t *)mem->data,
-                                imgProp.size);
+               if (m_parent->mParameters.isUbiFocusEnabled()){
+                   CAM_DUMP_TO_FILE("/data/local/ubifocus", "DepthMapImage",
+                                    -1, "y",
+                                    (uint8_t *)mem->data,
+                                    imgProp.size);
+               }
+               if (m_parent->mParameters.isMultiTouchFocusEnabled()) {
+                   CAM_DUMP_TO_FILE("/data/local/multiTouchFocus", "DepthMapImage",
+                                    -1, "y",
+                                    (uint8_t *)mem->data,
+                                    imgProp.size);
+               }
            }
            return NO_ERROR;
         }
diff --git a/QCamera2/stack/common/cam_intf.h b/QCamera2/stack/common/cam_intf.h
index c6b8fdb..bc0c8e7 100644
--- a/QCamera2/stack/common/cam_intf.h
+++ b/QCamera2/stack/common/cam_intf.h
@@ -302,7 +302,8 @@
     cam_true_portrait_t  true_portrait_settings_need;
     /* FSSR info */
     cam_fssr_t      fssr_settings_need;
-
+    /* AF bracketing info for multi-touch focus*/
+    cam_af_bracketing_t  mtf_af_bracketing_parm;
     /* Sensor type information */
     cam_sensor_type_t sensor_type;
 } cam_capability_t;
@@ -551,6 +552,7 @@
     INCLUDE(CAM_INTF_PARM_ISP_DEBUG_MASK,           uint32_t,                    1);
     INCLUDE(CAM_INTF_PARM_ALGO_OPTIMIZATIONS_MASK,  uint32_t,                    1);
     INCLUDE(CAM_INTF_PARM_FOCUS_BRACKETING,         cam_af_bracketing_t,         1);
+    INCLUDE(CAM_INTF_PARM_MULTI_TOUCH_FOCUS_BRACKETING, cam_af_bracketing_t,     1);
     INCLUDE(CAM_INTF_PARM_FLASH_BRACKETING,         cam_flash_bracketing_t,      1);
 } parm_type_t;
 
diff --git a/QCamera2/stack/common/cam_types.h b/QCamera2/stack/common/cam_types.h
index eb90da1..3ddf525 100644
--- a/QCamera2/stack/common/cam_types.h
+++ b/QCamera2/stack/common/cam_types.h
@@ -1266,6 +1266,7 @@
     /* Indicates streams ID of all the requested buffers */
     CAM_INTF_META_STREAM_ID,
     CAM_INTF_PARM_FOCUS_BRACKETING,
+    CAM_INTF_PARM_MULTI_TOUCH_FOCUS_BRACKETING,
     CAM_INTF_PARM_FLASH_BRACKETING,
     CAM_INTF_PARM_GET_IMG_PROP,
 
@@ -1439,8 +1440,10 @@
 #define CAM_QCOM_FEATURE_DIS20          (1<<16)
 #define CAM_QCOM_FEATURE_SENSOR_HDR     (1<<17)
 #define CAM_QCOM_FEATURE_TRUEPORTRAIT   (1<<18)
+#define CAM_QCOM_FEATURE_MULTI_TOUCH_FOCUS (1<<19)
 #define CAM_QCOM_FEATURE_FSSR           (1<<20)
 
+
 // Debug mask
 #define HAL_DEBUG_MASK_HAL                 (1<<0)
 #define HAL_DEBUG_MASK_MM_CAMERA_INTERFACE (1<<1)
@@ -1489,7 +1492,7 @@
 typedef struct {
     uint8_t enable;
     uint8_t burst_count;
-    uint8_t focus_steps[MAX_AF_BRACKETING_VALUES];
+    int32_t focus_steps[MAX_AF_BRACKETING_VALUES];
     uint8_t output_count;
 } cam_af_bracketing_t;
 
diff --git a/QCamera2/stack/common/mm_camera_interface.h b/QCamera2/stack/common/mm_camera_interface.h
index 09a2b58..53b7a77 100644
--- a/QCamera2/stack/common/mm_camera_interface.h
+++ b/QCamera2/stack/common/mm_camera_interface.h
@@ -250,6 +250,7 @@
    MM_CAMERA_AF_BRACKETING = 0,
    MM_CAMERA_AE_BRACKETING,
    MM_CAMERA_FLASH_BRACKETING,
+   MM_CAMERA_MTF_BRACKETING,
    MM_CAMERA_ZOOM_1X,
 } mm_camera_advanced_capture_t;
 
diff --git a/QCamera2/stack/mm-camera-interface/inc/mm_camera.h b/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
index 9126a05..1dbd79d 100644
--- a/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
+++ b/QCamera2/stack/mm-camera-interface/inc/mm_camera.h
@@ -91,6 +91,7 @@
     MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING,
     MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING,
     MM_CAMERA_GENERIC_CMD_TYPE_FLASH_BRACKETING,
+    MM_CAMERA_GENERIC_CMD_TYPE_MTF_BRACKETING,
     MM_CAMERA_GENERIC_CMD_TYPE_ZOOM_1X,
 } mm_camera_generic_cmd_type_t;
 
@@ -285,6 +286,7 @@
     MM_CHANNEL_EVT_AF_BRACKETING,
     MM_CHANNEL_EVT_AE_BRACKETING,
     MM_CHANNEL_EVT_FLASH_BRACKETING,
+    MM_CHANNEL_EVT_MTF_BRACKETING,
     MM_CHANNEL_EVT_ZOOM_1X,
 } mm_channel_evt_type_t;
 
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera.c b/QCamera2/stack/mm-camera-interface/src/mm_camera.c
index 88f6fb8..eca2e63 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera.c
@@ -1820,6 +1820,12 @@
                                        (void *)start_flag,
                                        NULL);
                 break;
+            case MM_CAMERA_MTF_BRACKETING:
+                rc = mm_channel_fsm_fn(ch_obj,
+                                       MM_CHANNEL_EVT_MTF_BRACKETING,
+                                       (void *)start_flag,
+                                       NULL);
+                break;
             case MM_CAMERA_ZOOM_1X:
                 rc = mm_channel_fsm_fn(ch_obj,
                                        MM_CHANNEL_EVT_ZOOM_1X,
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
index d79cc7c..f8858a0 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_channel.c
@@ -251,7 +251,8 @@
         CDBG_HIGH("%s:%d] MM_CAMERA_CMD_TYPE_GENERAL", __func__, __LINE__);
         switch (cmd_cb->u.gen_cmd.type) {
             case MM_CAMERA_GENERIC_CMD_TYPE_AE_BRACKETING:
-            case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING: {
+            case MM_CAMERA_GENERIC_CMD_TYPE_AF_BRACKETING:
+            case MM_CAMERA_GENERIC_CMD_TYPE_MTF_BRACKETING: {
                 int8_t start = cmd_cb->u.gen_cmd.payload[0];
                 CDBG_HIGH("%s:%d] MM_CAMERA_GENERIC_CMDTYPE_AF_BRACKETING %d",
                     __func__, __LINE__, start);
@@ -707,6 +708,16 @@
             rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
         }
         break;
+    case MM_CHANNEL_EVT_MTF_BRACKETING:
+        {
+            CDBG_HIGH("MM_CHANNEL_EVT_MTF_BRACKETING");
+            int32_t start_flag = ( int32_t ) in_val;
+            mm_camera_generic_cmd_t gen_cmd;
+            gen_cmd.type = MM_CAMERA_GENERIC_CMD_TYPE_MTF_BRACKETING;
+            gen_cmd.payload[0] = start_flag;
+            rc = mm_channel_proc_general_cmd(my_obj, &gen_cmd);
+        }
+        break;
     case MM_CHANNEL_EVT_AE_BRACKETING:
         {
             CDBG_HIGH("MM_CHANNEL_EVT_AE_BRACKETING");