Merge "QCamera2 :  memory leak with memory buffer allocations and deallocation"
diff --git a/QCamera2/HAL/Android.mk b/QCamera2/HAL/Android.mk
index ea39404..e6b183e 100644
--- a/QCamera2/HAL/Android.mk
+++ b/QCamera2/HAL/Android.mk
@@ -1,7 +1,6 @@
 LOCAL_PATH:= $(call my-dir)
 
 include $(CLEAR_VARS)
-
 LOCAL_SRC_FILES := \
         QCamera2Factory.cpp \
         QCamera2Hal.cpp \
@@ -22,6 +21,9 @@
 #Debug logs are enabled
 #LOCAL_CFLAGS += -DDISABLE_DEBUG_LOG
 
+ifeq ($(TARGET_USE_VENDOR_CAMERA_EXT),true)
+LOCAL_CFLAGS += -DUSE_VENDOR_CAMERA_EXT
+endif
 ifneq ($(call is-platform-sdk-version-at-least,18),true)
 LOCAL_CFLAGS += -DUSE_JB_MR1
 endif
@@ -29,13 +31,17 @@
 LOCAL_C_INCLUDES := \
         $(LOCAL_PATH)/../stack/common \
         frameworks/native/include/media/openmax \
-        hardware/qcom/display/libgralloc \
         hardware/qcom/media/libstagefrighthw \
         $(LOCAL_PATH)/../../mm-image-codec/qexif \
         $(LOCAL_PATH)/../../mm-image-codec/qomx_core \
         $(LOCAL_PATH)/../util \
         $(LOCAL_PATH)/wrapper
 
+ifeq ($(TARGET_USE_VENDOR_CAMERA_EXT),true)
+LOCAL_C_INCLUDES += hardware/qcom/display/msm8974/libgralloc
+else
+LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+endif
 LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
 LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/media
 LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index 4973cb4..09a997a 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -43,6 +43,11 @@
 #define CAMERA_MIN_JPEG_ENCODING_BUFFERS 2
 #define CAMERA_MIN_VIDEO_BUFFERS         9
 
+//This multiplier signifies extra buffers that we need to allocate
+//for the output of pproc
+#define CAMERA_PPROC_OUT_BUFFER_MULTIPLIER 2
+
+
 #define HDR_CONFIDENCE_THRESHOLD 0.4
 
 namespace qcamera {
@@ -958,7 +963,8 @@
       mLongshotEnabled(false),
       m_max_pic_width(0),
       m_max_pic_height(0),
-      mFlashNeeded(false)
+      mFlashNeeded(false),
+      mCaptureRotation(0)
 {
     mCameraDevice.common.tag = HARDWARE_DEVICE_TAG;
     mCameraDevice.common.version = HARDWARE_DEVICE_API_VERSION(1, 0);
@@ -1026,8 +1032,12 @@
     }
     ALOGE("[KPI Perf] %s: E PROFILE_OPEN_CAMERA camera id %d", __func__,mCameraId);
     rc = openCamera();
-    if (rc == NO_ERROR)
+    if (rc == NO_ERROR){
         *hw_device = &mCameraDevice.common;
+        if (m_thermalAdapter.init(this) != 0) {
+          ALOGE("Init thermal adapter failed");
+        }
+    }
     else
         *hw_device = NULL;
     return rc;
@@ -1101,12 +1111,6 @@
     }
 
     mParameters.init(gCamCapability[mCameraId], mCameraHandle, this);
-
-    rc = m_thermalAdapter.init(this);
-    if (rc != 0) {
-        ALOGE("Init thermal adapter failed");
-    }
-
     mCameraOpened = true;
 
     return NO_ERROR;
@@ -1305,10 +1309,13 @@
 
     int zslQBuffers = mParameters.getZSLQueueDepth();
 
-    int minCircularBufNum = CAMERA_MIN_STREAMING_BUFFERS +
-                            CAMERA_MIN_JPEG_ENCODING_BUFFERS +
-                            mParameters.getMaxUnmatchedFramesInQueue() +
-                            mParameters.getNumOfExtraHDRInBufsIfNeeded();
+    int minCircularBufNum = mParameters.getMaxUnmatchedFramesInQueue() +
+                            CAMERA_MIN_JPEG_ENCODING_BUFFERS;
+
+    int maxStreamBuf = minCaptureBuffers + mParameters.getMaxUnmatchedFramesInQueue() +
+                       mParameters.getNumOfExtraHDRInBufsIfNeeded() -
+                       mParameters.getNumOfExtraHDROutBufsIfNeeded();
+
     int minUndequeCount = 0;
     if (!isNoDisplayMode() && mPreviewWindow != NULL) {
         if (mPreviewWindow->get_min_undequeued_buffer_count(mPreviewWindow,&minUndequeCount)
@@ -1332,13 +1339,12 @@
         break;
     case CAM_STREAM_TYPE_POSTVIEW:
         {
-            bufferCnt = minCaptureBuffers +
+            bufferCnt = minCaptureBuffers*CAMERA_PPROC_OUT_BUFFER_MULTIPLIER +
                         mParameters.getNumOfExtraHDRInBufsIfNeeded() -
-                        mParameters.getNumOfExtraHDROutBufsIfNeeded() +
-                        mParameters.getMaxUnmatchedFramesInQueue();
+                        mParameters.getNumOfExtraHDROutBufsIfNeeded();
 
-            if (bufferCnt > zslQBuffers + minCircularBufNum) {
-                bufferCnt = zslQBuffers + minCircularBufNum;
+            if (bufferCnt > maxStreamBuf) {
+                bufferCnt = maxStreamBuf;
             }
             bufferCnt += minUndequeCount;
         }
@@ -1348,13 +1354,12 @@
             if (mParameters.isZSLMode()) {
                 bufferCnt = zslQBuffers + minCircularBufNum;
             } else {
-                bufferCnt = minCaptureBuffers +
+                bufferCnt = minCaptureBuffers*CAMERA_PPROC_OUT_BUFFER_MULTIPLIER +
                             mParameters.getNumOfExtraHDRInBufsIfNeeded() -
-                            mParameters.getNumOfExtraHDROutBufsIfNeeded() +
-                            mParameters.getMaxUnmatchedFramesInQueue();
+                            mParameters.getNumOfExtraHDROutBufsIfNeeded();
 
-                if (bufferCnt > zslQBuffers + minCircularBufNum) {
-                    bufferCnt = zslQBuffers + minCircularBufNum;
+                if (bufferCnt > maxStreamBuf) {
+                    bufferCnt = maxStreamBuf;
                 }
             }
         }
@@ -1363,11 +1368,12 @@
         if (mParameters.isZSLMode()) {
             bufferCnt = zslQBuffers + minCircularBufNum;
         } else {
-            bufferCnt = minCaptureBuffers +
-                        mParameters.getMaxUnmatchedFramesInQueue();
+            bufferCnt = minCaptureBuffers*CAMERA_PPROC_OUT_BUFFER_MULTIPLIER +
+                        mParameters.getNumOfExtraHDRInBufsIfNeeded() -
+                        mParameters.getNumOfExtraHDROutBufsIfNeeded();
 
-            if (bufferCnt > zslQBuffers + minCircularBufNum) {
-                bufferCnt = zslQBuffers + minCircularBufNum;
+            if (bufferCnt > maxStreamBuf) {
+                bufferCnt = maxStreamBuf;
             }
         }
         break;
@@ -1395,12 +1401,7 @@
         break;
     case CAM_STREAM_TYPE_OFFLINE_PROC:
         {
-            bufferCnt = minCaptureBuffers +
-                        mParameters.getNumOfExtraHDROutBufsIfNeeded();
-
-            if (bufferCnt > zslQBuffers + minCircularBufNum) {
-                bufferCnt = zslQBuffers + minCircularBufNum;
-            }
+            bufferCnt = minCaptureBuffers;
         }
         break;
     case CAM_STREAM_TYPE_DEFAULT:
@@ -1475,7 +1476,7 @@
         break;
     case CAM_STREAM_TYPE_VIDEO:
         {
-            char value[32];
+            char value[PROPERTY_VALUE_MAX];
             property_get("persist.camera.mem.usecache", value, "1");
             if (atoi(value) == 0) {
                 bCachedMem = QCAMERA_ION_USE_NOCACHE;
@@ -1567,8 +1568,8 @@
     streamInfo->stream_type = stream_type;
     rc = mParameters.getStreamFormat(stream_type, streamInfo->fmt);
     rc = mParameters.getStreamDimension(stream_type, streamInfo->dim);
+    rc = mParameters.getStreamRotation(stream_type, streamInfo->pp_config, streamInfo->dim);
     streamInfo->num_bufs = getBufNumRequired(stream_type);
-
     streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
     switch (stream_type) {
     case CAM_STREAM_TYPE_SNAPSHOT:
@@ -2039,6 +2040,7 @@
 {
     int rc = NO_ERROR;
     uint8_t numSnapshots = mParameters.getNumOfSnapshots();
+    getOrientation();
     ALOGD("%s: E", __func__);
     if (mParameters.isZSLMode()) {
         QCameraPicChannel *pZSLChannel =
@@ -2252,6 +2254,8 @@
 {
     int rc = NO_ERROR;
 
+    getOrientation();
+
     // start post processor
     rc = m_postprocessor.start(m_channels[QCAMERA_CH_TYPE_SNAPSHOT]);
 
@@ -3721,7 +3725,7 @@
 
     if (needRotationReprocess()) {
         pp_config.feature_mask |= CAM_QCOM_FEATURE_ROTATION;
-        int rotation = mParameters.getJpegRotation();
+        int rotation = getJpegRotation();
         if (rotation == 0) {
             pp_config.rotation = ROTATE_0;
         } else if (rotation == 90) {
@@ -3735,10 +3739,6 @@
 
     uint8_t minStreamBufNum = getBufNumRequired(CAM_STREAM_TYPE_OFFLINE_PROC);
 
-    if (pp_config.feature_mask) {
-        minStreamBufNum += mParameters.getMaxUnmatchedFramesInQueue();
-    }
-
     if (mParameters.isHDREnabled()){
         pp_config.feature_mask |= CAM_QCOM_FEATURE_HDR;
         pp_config.hdr_param.hdr_enable = 1;
@@ -3757,9 +3757,24 @@
 
     ALOGD("%s: After pproc config check, ret = %x", __func__, pp_config.feature_mask);
 
+    //WNR and HDR happen inline. No extra buffers needed.
+    uint32_t temp_feature_mask = pp_config.feature_mask;
+    temp_feature_mask &= ~CAM_QCOM_FEATURE_HDR;
+    temp_feature_mask &= ~CAM_QCOM_FEATURE_DENOISE2D;
+
+    if (temp_feature_mask) {
+        int minCaptureBuffers = mParameters.getNumOfSnapshots();
+        int maxStreamBuf = minCaptureBuffers + mParameters.getMaxUnmatchedFramesInQueue();
+        minStreamBufNum *= CAMERA_PPROC_OUT_BUFFER_MULTIPLIER;
+        if (minStreamBufNum > maxStreamBuf) {
+            minStreamBufNum = maxStreamBuf;
+        }
+    }
+
     if ( mLongshotEnabled ) {
         minStreamBufNum = getBufNumRequired(CAM_STREAM_TYPE_PREVIEW);
     }
+
     rc = pChannel->addReprocStreamsFromSource(*this,
                                               pp_config,
                                               pInputChannel,
@@ -4653,9 +4668,9 @@
     }
 
     if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & CAM_QCOM_FEATURE_ROTATION) > 0 &&
-            (mParameters.getJpegRotation() > 0) &&  (mParameters.getRecordingHintValue() == false)) {
+            (getJpegRotation() > 0) &&  (mParameters.getRecordingHintValue() == false)) {
             // current rotation is not zero, and pp has the capability to process rotation
-            ALOGD("%s: need to do reprocess for rotation=%d", __func__, mParameters.getJpegRotation());
+            ALOGD("%s: need to do reprocess for rotation=%d", __func__, getJpegRotation());
             pthread_mutex_unlock(&m_parm_lock);
             return true;
     }
@@ -4712,9 +4727,9 @@
     }
 
         if ((gCamCapability[mCameraId]->qcom_supported_feature_mask & CAM_QCOM_FEATURE_ROTATION) > 0 &&
-            (mParameters.getJpegRotation() > 0) && (mParameters.getRecordingHintValue() == false)) {
+            (getJpegRotation() > 0) && (mParameters.getRecordingHintValue() == false)) {
             // current rotation is not zero, and pp has the capability to process rotation
-            ALOGD("%s: need to do reprocess for rotation=%d", __func__, mParameters.getJpegRotation());
+            ALOGD("%s: need to do reprocess for rotation=%d", __func__, getJpegRotation());
             pthread_mutex_unlock(&m_parm_lock);
             return true;
         }
@@ -4802,11 +4817,22 @@
  * RETURN     : rotation information
  *==========================================================================*/
 int QCamera2HardwareInterface::getJpegRotation() {
-    int rotation = 0;
+    return mCaptureRotation;
+}
+
+/*===========================================================================
+ * FUNCTION   : getOrientation
+ *
+ * DESCRIPTION: get rotation information from camera parameters
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : rotation information
+ *==========================================================================*/
+void QCamera2HardwareInterface::getOrientation() {
     pthread_mutex_lock(&m_parm_lock);
-    rotation = mParameters.getJpegRotation();
+    mCaptureRotation = mParameters.getJpegRotation();
     pthread_mutex_unlock(&m_parm_lock);
-    return rotation;
 }
 
 /*===========================================================================
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index efd6b1f..16007e7 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -313,6 +313,7 @@
     void getThumbnailSize(cam_dimension_t &dim);
     int getJpegQuality();
     int getJpegRotation();
+    void getOrientation();
     QCameraExif *getExifData();
 
     int32_t processAutoFocusEvent(cam_auto_focus_data_t &focus_data);
@@ -479,6 +480,7 @@
     int32_t m_max_pic_width;
     int32_t m_max_pic_height;
     uint8_t mFlashNeeded;
+    int mCaptureRotation;
 };
 
 }; // namespace qcamera
diff --git a/QCamera2/HAL/QCamera2HWICallbacks.cpp b/QCamera2/HAL/QCamera2HWICallbacks.cpp
index 98a8341..5e380c8 100644
--- a/QCamera2/HAL/QCamera2HWICallbacks.cpp
+++ b/QCamera2/HAL/QCamera2HWICallbacks.cpp
@@ -1057,6 +1057,11 @@
     mm_camera_buf_def_t *frame = super_frame->bufs[0];
     cam_metadata_info_t *pMetaData = (cam_metadata_info_t *)frame->buffer;
 
+    if(pme->m_stateMachine.isNonZSLCaptureRunning()&& pMetaData->is_meta_valid == 1) {
+       //Make shutter call back in non ZSL mode once raw frame is received from VFE.
+       pme->playShutter();
+    }
+
     if (pMetaData->is_tuning_params_valid && pme->mParameters.getRecordingHintValue() == true) {
         //Dump Tuning data for video
         pme->dumpMetadataToFile(stream,frame,(char *)"Video");
@@ -1178,7 +1183,8 @@
           pMetaData->is_hdr_scene_data_valid,
           pMetaData->hdr_scene_data.is_hdr_scene,
           pMetaData->hdr_scene_data.hdr_confidence);
-    if (pMetaData->is_hdr_scene_data_valid) {
+    //Handle this HDR meta data only if capture is not in process
+    if (pMetaData->is_hdr_scene_data_valid && !pme->m_stateMachine.isCaptureRunning()) {
         int32_t rc = pme->processHDRData(pMetaData->hdr_scene_data);
         if (rc != NO_ERROR) {
             ALOGE("%s: processHDRData failed", __func__);
diff --git a/QCamera2/HAL/QCamera2Hal.cpp b/QCamera2/HAL/QCamera2Hal.cpp
index a2a2f17..1ff3231 100644
--- a/QCamera2/HAL/QCamera2Hal.cpp
+++ b/QCamera2/HAL/QCamera2Hal.cpp
@@ -48,4 +48,8 @@
 #ifndef USE_JB_MR1
     set_callbacks: NULL,
 #endif
+#ifdef USE_VENDOR_CAMERA_EXT
+    get_vendor_tag_ops: NULL,
+    reserved:  {0}
+#endif
 };
diff --git a/QCamera2/HAL/QCameraParameters.cpp b/QCamera2/HAL/QCameraParameters.cpp
index f258ecd..fd73671 100644
--- a/QCamera2/HAL/QCameraParameters.cpp
+++ b/QCamera2/HAL/QCameraParameters.cpp
@@ -107,6 +107,7 @@
 const char QCameraParameters::KEY_QC_SNAPSHOT_BURST_NUM[] = "snapshot-burst-num";
 const char QCameraParameters::KEY_QC_SNAPSHOT_FD_DATA[] = "snapshot-fd-data-enable";
 const char QCameraParameters::KEY_QC_TINTLESS_ENABLE[] = "tintless";
+const char QCameraParameters::KEY_QC_VIDEO_ROTATION[] = "video-rotation";
 
 // Values for effect settings.
 const char QCameraParameters::EFFECT_EMBOSS[] = "emboss";
@@ -581,7 +582,7 @@
       m_bHDR1xExtraBufferNeeded(true),
       m_tempMap()
 {
-    char value[32];
+    char value[PROPERTY_VALUE_MAX];
     // TODO: may move to parameter instead of sysprop
     property_get("persist.debug.sf.showfps", value, "0");
     m_bDebugFps = atoi(value) > 0 ? true : false;
@@ -1140,7 +1141,7 @@
  *==========================================================================*/
 int32_t QCameraParameters::setLiveSnapshotSize(const QCameraParameters& params)
 {
-    char value[32];
+    char value[PROPERTY_VALUE_MAX];
     property_get("persist.camera.opt.livepic", value, "1");
     bool useOptimal = atoi(value) > 0 ? true : false;
 
@@ -1218,10 +1219,6 @@
     ALOGI("%s: live snapshot size %d x %d", __func__,
           m_LiveSnapshotSize.width, m_LiveSnapshotSize.height);
 
-    if (m_bRecordingHint) {
-        CameraParameters::setPictureSize(m_LiveSnapshotSize.width, m_LiveSnapshotSize.height);
-    }
-
     return NO_ERROR;
 }
 
@@ -2035,6 +2032,33 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : setVideoRotation
+ *
+ * DESCRIPTION: set rotation value from user setting
+ *
+ * PARAMETERS :
+ *   @params  : user setting parameters
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCameraParameters::setVideoRotation(const QCameraParameters& params)
+{
+    int rotation = params.getInt(KEY_QC_VIDEO_ROTATION);
+    if (rotation != -1) {
+        if (rotation == 0 || rotation == 90 ||
+            rotation == 180 || rotation == 270) {
+            set(KEY_QC_VIDEO_ROTATION, rotation);
+        } else {
+            ALOGE("Invalid rotation value: %d", rotation);
+            return BAD_VALUE;
+        }
+    }
+    return NO_ERROR;
+}
+
+/*===========================================================================
  * FUNCTION   : setRotation
  *
  * DESCRIPTION: set rotation value from user setting
@@ -2773,6 +2797,17 @@
  *==========================================================================*/
 int32_t QCameraParameters::setWaveletDenoise(const QCameraParameters& params)
 {
+    const char *str_pf = params.getPictureFormat();
+    int32_t pictureFormat =
+        lookupAttr(PICTURE_TYPES_MAP,
+                   sizeof(PICTURE_TYPES_MAP) / sizeof(QCameraMap),
+                   str_pf);
+    if (pictureFormat != NAME_NOT_FOUND) {
+        if (CAM_FORMAT_YUV_422_NV16 == pictureFormat) {
+            ALOGE("NV16 format isn't supported in denoise lib!");
+            return setWaveletDenoise(DENOISE_OFF);
+        }
+    }
     const char *str = params.get(KEY_QC_DENOISE);
     const char *prev_str = get(KEY_QC_DENOISE);
     if (str != NULL) {
@@ -2822,7 +2857,7 @@
 int32_t QCameraParameters::setZslAttributes(const QCameraParameters& params)
 {
     // TODO: may switch to pure param instead of sysprop
-    char prop[32];
+    char prop[PROPERTY_VALUE_MAX];
 
     const char *str = params.get(KEY_QC_ZSL_BURST_INTERVAL);
     if (str != NULL) {
@@ -2967,7 +3002,7 @@
  *==========================================================================*/
 int32_t QCameraParameters::setSnapshotFDReq(const QCameraParameters& params)
 {
-    char prop[32];
+    char prop[PROPERTY_VALUE_MAX];
     const char *str = params.get(KEY_QC_SNAPSHOT_FD_DATA);
 
     if(str != NULL){
@@ -3015,6 +3050,7 @@
     if ((rc = setJpegQuality(params)))                  final_rc = rc;
     if ((rc = setOrientation(params)))                  final_rc = rc;
     if ((rc = setRotation(params)))                     final_rc = rc;
+    if ((rc = setVideoRotation(params)))                final_rc = rc;
     if ((rc = setNoDisplayMode(params)))                final_rc = rc;
     if ((rc = setZslMode(params)))                      final_rc = rc;
     if ((rc = setZslAttributes(params)))                final_rc = rc;
@@ -3844,7 +3880,7 @@
 int32_t QCameraParameters::setPreviewFpsRange(int minFPS, int maxFPS)
 {
     char str[32];
-    char value[32];
+    char value[PROPERTY_VALUE_MAX];
     int fixedFpsValue;
     /*This property get value should be the fps that user needs*/
     property_get("persist.debug.set.fixedfps", value, "0");
@@ -5064,20 +5100,28 @@
 {
     char prop[PROPERTY_VALUE_MAX];
     memset(prop, 0, sizeof(prop));
-    property_get("persist.denoise.process.plates", prop, "0");
-    int processPlate = atoi(prop);
-    switch(processPlate) {
-    case 0:
-        return CAM_WAVELET_DENOISE_YCBCR_PLANE;
-    case 1:
-        return CAM_WAVELET_DENOISE_CBCR_ONLY;
-    case 2:
-        return CAM_WAVELET_DENOISE_STREAMLINE_YCBCR;
-    case 3:
-        return CAM_WAVELET_DENOISE_STREAMLINED_CBCR;
-    default:
-        return CAM_WAVELET_DENOISE_STREAMLINE_YCBCR;
+    cam_denoise_process_type_t processPlate = CAM_WAVELET_DENOISE_CBCR_ONLY;
+    property_get("persist.denoise.process.plates", prop, "");
+    if (strlen(prop) > 0) {
+        switch(atoi(prop)) {
+        case 0:
+            processPlate = CAM_WAVELET_DENOISE_YCBCR_PLANE;
+            break;
+        case 1:
+            processPlate = CAM_WAVELET_DENOISE_CBCR_ONLY;
+            break;
+        case 2:
+            processPlate = CAM_WAVELET_DENOISE_STREAMLINE_YCBCR;
+            break;
+        case 3:
+            processPlate = CAM_WAVELET_DENOISE_STREAMLINED_CBCR;
+            break;
+        default:
+            processPlate = CAM_WAVELET_DENOISE_CBCR_ONLY;
+            break;
+        }
     }
+    return processPlate;
 }
 
 /*===========================================================================
@@ -5255,6 +5299,68 @@
  *              NO_ERROR  -- success
  *              none-zero failure code
  *==========================================================================*/
+int32_t QCameraParameters::getStreamRotation(cam_stream_type_t streamType,
+                                            cam_pp_feature_config_t &featureConfig,
+                                            cam_dimension_t &dim)
+{
+    int32_t ret = NO_ERROR;
+    int rotationParam = getInt(KEY_QC_VIDEO_ROTATION);
+    featureConfig.rotation = ROTATE_0;
+    int swapDim = 0;
+    switch (streamType) {
+    case CAM_STREAM_TYPE_VIDEO:
+           switch(rotationParam) {
+            case 90:
+               featureConfig.feature_mask |= CAM_QCOM_FEATURE_ROTATION;
+               featureConfig.rotation = ROTATE_90;
+               swapDim = 1;
+               break;
+            case 180:
+               featureConfig.feature_mask |= CAM_QCOM_FEATURE_ROTATION;
+               featureConfig.rotation = ROTATE_180;
+               break;
+            case 270:
+               featureConfig.feature_mask |= CAM_QCOM_FEATURE_ROTATION;
+               featureConfig.rotation = ROTATE_270;
+               swapDim = 1;
+              break;
+            default:
+               featureConfig.rotation = ROTATE_0;
+        }
+        break;
+    case CAM_STREAM_TYPE_PREVIEW:
+    case CAM_STREAM_TYPE_POSTVIEW:
+    case CAM_STREAM_TYPE_SNAPSHOT:
+    case CAM_STREAM_TYPE_RAW:
+    case CAM_STREAM_TYPE_METADATA:
+    case CAM_STREAM_TYPE_OFFLINE_PROC:
+    case CAM_STREAM_TYPE_DEFAULT:
+    default:
+        break;
+    }
+
+    if (swapDim > 0) {
+        int w = 0;
+        w = dim.width;
+        dim.width = dim.height;
+        dim.height = w;
+    }
+    return ret;
+}
+
+/*===========================================================================
+ * FUNCTION   : getStreamFormat
+ *
+ * DESCRIPTION: get stream format by its type
+ *
+ * PARAMETERS :
+ *   @streamType : [input] stream type
+ *   @format     : [output] stream format
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
 int32_t QCameraParameters::getStreamFormat(cam_stream_type_t streamType,
                                             cam_format_t &format)
 {
diff --git a/QCamera2/HAL/QCameraParameters.h b/QCamera2/HAL/QCameraParameters.h
index 3785308..fb415d3 100644
--- a/QCamera2/HAL/QCameraParameters.h
+++ b/QCamera2/HAL/QCameraParameters.h
@@ -219,6 +219,9 @@
     //Auto HDR enable
     static const char KEY_QC_AUTO_HDR_ENABLE[];
 
+    // video rotation
+    static const char KEY_QC_VIDEO_ROTATION[];
+
     //Redeye Reduction
     static const char KEY_QC_REDEYE_REDUCTION[];
     static const char KEY_QC_SUPPORTED_REDEYE_REDUCTION[];
@@ -430,6 +433,9 @@
     int32_t updateParameters(QCameraParameters&, bool &needRestart);
     int32_t commitParameters();
     int getPreviewHalPixelFormat() const;
+    int32_t getStreamRotation(cam_stream_type_t streamType,
+                               cam_pp_feature_config_t &featureConfig,
+                               cam_dimension_t &dim);
     int32_t getStreamFormat(cam_stream_type_t streamType,
                              cam_format_t &format);
     int32_t getStreamDimension(cam_stream_type_t streamType,
@@ -535,6 +541,7 @@
     int32_t setZoom(const QCameraParameters& );
     int32_t setISOValue(const QCameraParameters& );
     int32_t setRotation(const QCameraParameters& );
+    int32_t setVideoRotation(const QCameraParameters& );
     int32_t setFlash(const QCameraParameters& );
     int32_t setAecLock(const QCameraParameters& );
     int32_t setAwbLock(const QCameraParameters& );
diff --git a/QCamera2/HAL/QCameraPostProc.cpp b/QCamera2/HAL/QCameraPostProc.cpp
index 274ab65..42bc9e7 100644
--- a/QCamera2/HAL/QCameraPostProc.cpp
+++ b/QCamera2/HAL/QCameraPostProc.cpp
@@ -505,7 +505,8 @@
         processRawData(frame);
     } else {
         //play shutter sound
-        m_parent->playShutter();
+        if(!m_parent->m_stateMachine.isNonZSLCaptureRunning())
+           m_parent->playShutter();
 
         ALOGD("%s: no need offline reprocess, sending to jpeg encoding", __func__);
         qcamera_jpeg_data_t *jpeg_job =
diff --git a/QCamera2/HAL/QCameraStateMachine.cpp b/QCamera2/HAL/QCameraStateMachine.cpp
index 07931c1..b3d2f91 100644
--- a/QCamera2/HAL/QCameraStateMachine.cpp
+++ b/QCamera2/HAL/QCameraStateMachine.cpp
@@ -2795,5 +2795,25 @@
         return false;
     }
 }
+/*===========================================================================
+ * FUNCTION   : isNonZSLCaptureRunning
+ *
+ * DESCRIPTION: check if image capture is in process in non ZSL mode.
+ *
+ * PARAMETERS : None
+ *
+ * RETURN     : true -- capture running in non ZSL mode
+ *              false -- Either in not capture mode or captur is not in non ZSL mode
+ *==========================================================================*/
+bool QCameraStateMachine::isNonZSLCaptureRunning()
+{
+    switch (m_state) {
+    case QCAMERA_SM_STATE_PIC_TAKING:
+        return true;
+    default:
+        return false;
+    }
+}
+
 
 }; // namespace qcamera
diff --git a/QCamera2/HAL/QCameraStateMachine.h b/QCamera2/HAL/QCameraStateMachine.h
index e9beadc..63c59ff 100644
--- a/QCamera2/HAL/QCameraStateMachine.h
+++ b/QCamera2/HAL/QCameraStateMachine.h
@@ -161,6 +161,7 @@
 
     bool isPreviewRunning(); // check if preview is running
     bool isCaptureRunning(); // check if image capture is running
+    bool isNonZSLCaptureRunning(); // check if image capture is running in non ZSL mode
 
 private:
     typedef enum {
diff --git a/QCamera2/HAL/test/qcamera_test.cpp b/QCamera2/HAL/test/qcamera_test.cpp
index b6a5ab0..63e054b 100644
--- a/QCamera2/HAL/test/qcamera_test.cpp
+++ b/QCamera2/HAL/test/qcamera_test.cpp
@@ -569,7 +569,11 @@
 #ifndef USE_JB_MR1
 
         gbp = mPreviewSurface->getIGraphicBufferProducer();
+#ifdef USE_VENDOR_CAMERA_EXT
+        ret |= mCamera->setPreviewTarget(gbp);
+#else
         ret |= mCamera->setPreviewTexture(gbp);
+#endif
 
 #else
 
diff --git a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
index 3705baf..3c28e2d 100644
--- a/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
+++ b/QCamera2/stack/mm-camera-interface/src/mm_camera_stream.c
@@ -2652,7 +2652,8 @@
     int32_t rc = 0;
 
     cam_dimension_t dim = my_obj->stream_info->dim;
-    if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION) {
+    if (my_obj->stream_info->pp_config.feature_mask & CAM_QCOM_FEATURE_ROTATION &&
+        my_obj->stream_info->stream_type != CAM_STREAM_TYPE_VIDEO) {
         if (my_obj->stream_info->pp_config.rotation == ROTATE_90 ||
             my_obj->stream_info->pp_config.rotation == ROTATE_270) {
             // rotated by 90 or 270, need to switch width and height
diff --git a/QCamera2/stack/mm-camera-test/Android.mk b/QCamera2/stack/mm-camera-test/Android.mk
index 6fcad22..fb34b0d 100644
--- a/QCamera2/stack/mm-camera-test/Android.mk
+++ b/QCamera2/stack/mm-camera-test/Android.mk
@@ -26,7 +26,9 @@
         src/mm_qcamera_snapshot.c \
         src/mm_qcamera_rdi.c \
         src/mm_qcamera_reprocess.c\
-        src/mm_qcamera_queue.c
+        src/mm_qcamera_queue.c \
+        src/mm_qcamera_socket.c \
+        src/mm_qcamera_commands.c
 #        src/mm_qcamera_dual_test.c \
 
 LOCAL_C_INCLUDES:=$(LOCAL_PATH)/inc
@@ -114,7 +116,9 @@
         src/mm_qcamera_snapshot.c \
         src/mm_qcamera_rdi.c \
         src/mm_qcamera_reprocess.c\
-        src/mm_qcamera_queue.c
+        src/mm_qcamera_queue.c \
+        src/mm_qcamera_socket.c \
+        src/mm_qcamera_commands.c
 #        src/mm_qcamera_dual_test.c \
 
 LOCAL_C_INCLUDES:=$(LOCAL_PATH)/inc
diff --git a/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h b/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h
index d70ed7f..b30b5ef 100644
--- a/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h
+++ b/QCamera2/stack/mm-camera-test/inc/mm_qcamera_app.h
@@ -43,6 +43,7 @@
 
 #include "mm_camera_interface.h"
 #include "mm_jpeg_interface.h"
+#include "mm_qcamera_socket.h"
 
 #define MM_QCAMERA_APP_INTERATION 1
 
@@ -113,10 +114,18 @@
 typedef void (*prev_callback) (mm_camera_buf_def_t *preview_frame);
 
 typedef struct {
-	int (*command_process) (void *recv, mm_camera_tune_cmd_t cmd, void *param);
-    int (*prevcommand_process) (void *recv, mm_camera_tune_prevcmd_t cmd, void *param);
+  char *send_buf;
+  uint32_t send_len;
+  void *next;
+} eztune_prevcmd_rsp;
+
+typedef struct {
+    int (*command_process) (void *recv, mm_camera_tune_cmd_t cmd,
+      void *param, char *send_buf, uint32_t send_len);
+    int (*prevcommand_process) (void *recv, mm_camera_tune_prevcmd_t cmd,
+      void *param, char **send_buf, uint32_t *send_len);
     void (*prevframe_callback) (mm_camera_buf_def_t *preview_frame);
-}mm_camera_tune_func_t;
+} mm_camera_tune_func_t;
 
 typedef struct {
     mm_camera_tune_func_t *func_tbl;
@@ -242,7 +251,8 @@
 
   uint8_t (*get_num_of_cameras) ();
   mm_camera_vtbl_t *(*mm_camera_open) (uint8_t camera_idx);
-  uint32_t (*jpeg_open) (mm_jpeg_ops_t *ops);
+  uint32_t (*jpeg_open) (mm_jpeg_ops_t *ops, mm_dimension picture_size);
+
 } hal_interface_lib_t;
 
 typedef struct {
@@ -309,11 +319,19 @@
 } mm_camera_lib_params;
 
 typedef struct {
+  tuneserver_protocol_t *proto;
+  int clientsocket_id;
+  prserver_protocol_t *pr_proto;
+  int pr_clientsocket_id;
+  mm_camera_tuning_lib_params_t tuning_params;
+} tuningserver_t;
+
+typedef struct {
     mm_camera_app_t app_ctx;
     mm_camera_test_obj_t test_obj;
     mm_camera_lib_params current_params;
     int stream_running;
-    mm_camera_tuning_lib_params_t tuning_params;
+    tuningserver_t tsctrl;
 } mm_camera_lib_ctx;
 
 typedef mm_camera_lib_ctx mm_camera_lib_handle;
@@ -448,8 +466,8 @@
 int mm_camera_lib_stop_stream(mm_camera_lib_handle *handle);
 int mm_camera_lib_number_of_cameras(mm_camera_lib_handle *handle);
 int mm_camera_lib_close(mm_camera_lib_handle *handle);
-int32_t mm_camera_load_tuninglibrary
-    (mm_camera_tuning_lib_params_t *tuning_param);
+int32_t mm_camera_load_tuninglibrary(
+  mm_camera_tuning_lib_params_t *tuning_param);
 int mm_camera_lib_set_preview_usercb(
   mm_camera_lib_handle *handle, prev_callback cb);
 //
diff --git a/QCamera2/stack/mm-camera-test/inc/mm_qcamera_commands.h b/QCamera2/stack/mm-camera-test/inc/mm_qcamera_commands.h
new file mode 100644
index 0000000..1540c20
--- /dev/null
+++ b/QCamera2/stack/mm-camera-test/inc/mm_qcamera_commands.h
@@ -0,0 +1,67 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MM_QCAMERA_COMMANDS_H__
+#define __MM_QCAMERA_COMMANDS_H__
+
+#include "mm_qcamera_socket.h"
+#include "mm_qcamera_app.h"
+
+int tuneserver_close_cam(mm_camera_lib_handle *lib_handle);
+int tuneserver_stop_cam(mm_camera_lib_handle *lib_handle);
+int tuneserver_open_cam(mm_camera_lib_handle *lib_handle);
+
+int tuneserver_initialize_tuningp(void * ctrl, int client_socket_id,
+  char *send_buf, uint32_t send_len);
+int tuneserver_deinitialize_tuningp(void * ctrl, int client_socket_id,
+  char *send_buf, uint32_t send_len);
+int tuneserver_process_get_list_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len);
+int tuneserver_process_misc_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len);
+int tuneserver_process_get_params_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len);
+int tuneserver_process_set_params_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len);
+
+int tuneserver_initialize_prevtuningp(void * ctrl,
+  int pr_client_socket_id, cam_dimension_t dimension,
+  char **send_buf, uint32_t *send_len);
+int tuneserver_deinitialize_prevtuningp(void * ctrl,
+  char **send_buf, uint32_t *send_len);
+int tuneserver_preview_getinfo(void * ctrl,
+  char **send_buf, uint32_t *send_len);
+int tuneserver_preview_getchunksize(void * ctrl,
+  char **send_buf, uint32_t *send_len);
+int tuneserver_preview_getframe(void * ctrl,
+  char **send_buf, uint32_t *send_len);
+int tuneserver_preview_unsupported(void * ctrl,
+  char **send_buf, uint32_t *send_len);
+
+#endif /*__MM_QCAMERA_COMMANDS_H__*/
diff --git a/QCamera2/stack/mm-camera-test/inc/mm_qcamera_socket.h b/QCamera2/stack/mm-camera-test/inc/mm_qcamera_socket.h
new file mode 100644
index 0000000..c054d63
--- /dev/null
+++ b/QCamera2/stack/mm-camera-test/inc/mm_qcamera_socket.h
@@ -0,0 +1,125 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __MM_QCAMERA_SOCKET_H__
+#define __MM_QCAMERA_SOCKET_H__
+
+#include <stdint.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <termios.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <linux/socket.h>
+#include <arpa/inet.h>
+#include <utils/Log.h>
+
+#undef __FD_SET
+#define __FD_SET(fd, fdsetp) \
+  (((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] |= (1<<((fd) & 31)))
+
+#undef __FD_CLR
+#define __FD_CLR(fd, fdsetp) \
+  (((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] &= ~(1<<((fd) & 31)))
+
+#undef  __FD_ISSET
+#define __FD_ISSET(fd, fdsetp) \
+  ((((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] & (1<<((fd) & 31))) != 0)
+
+#undef  __FD_ZERO
+#define __FD_ZERO(fdsetp) \
+  (memset (fdsetp, 0, sizeof (*(fd_set *)(fdsetp))))
+
+#define TUNESERVER_MAX_RECV 2048
+#define TUNESERVER_MAX(a, b)  (((a) > (b)) ? (a) : (b))
+
+#define TUNESERVER_GET_LIST 1014
+#define TUNESERVER_GET_PARMS 1015
+#define TUNESERVER_SET_PARMS 1016
+#define TUNESERVER_MISC_CMDS 1021
+
+#define TUNE_PREV_GET_INFO        0x0001
+#define TUNE_PREV_CH_CNK_SIZE     0x0002
+#define TUNE_PREV_GET_PREV_FRAME  0x0003
+#define TUNE_PREV_GET_JPG_SNAP    0x0004
+#define TUNE_PREV_GET_RAW_SNAP    0x0005
+#define TUNE_PREV_GET_RAW_PREV    0x0006
+
+typedef struct {
+  char data[128];
+} tuneserver_misc_cmd;
+
+typedef enum {
+  TUNESERVER_RECV_COMMAND = 1,
+  TUNESERVER_RECV_PAYLOAD_SIZE,
+  TUNESERVER_RECV_PAYLOAD,
+  TUNESERVER_RECV_RESPONSE,
+  TUNESERVERER_RECV_INVALID,
+} tuneserver_recv_cmd_t;
+
+typedef struct {
+  uint16_t          current_cmd;
+  tuneserver_recv_cmd_t next_recv_code;
+  uint32_t          next_recv_len;
+  void              *recv_buf;
+  uint32_t          recv_len;
+  uint32_t          send_len;
+  void              *send_buf;
+} tuneserver_protocol_t;
+
+typedef enum {
+  TUNE_PREV_RECV_COMMAND = 1,
+  TUNE_PREV_RECV_NEWCNKSIZE,
+  TUNE_PREV_RECV_INVALID
+} tune_prev_cmd_t;
+
+typedef struct _eztune_preview_protocol_t {
+  uint16_t         current_cmd;
+  tune_prev_cmd_t  next_recv_code;
+  uint32_t         next_recv_len;
+  int32_t          send_len;
+  char*            send_buf;
+  uint32_t         send_buf_size;
+  uint32_t         new_cnk_size;
+  uint32_t         new_cmd_available;
+} prserver_protocol_t;
+
+
+int eztune_server_start(void *lib_handle);
+
+#endif /*__MM_QCAMERA_SOCKET_H__*/
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
old mode 100755
new mode 100644
index 0507c56..21d518a
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_app.c
@@ -561,7 +561,11 @@
         goto error_after_getparm_buf_map;
     }
     memset(&test_obj->jpeg_ops, 0, sizeof(mm_jpeg_ops_t));
-    test_obj->jpeg_hdl = cam_app->hal_lib.jpeg_open(&test_obj->jpeg_ops);
+    mm_dimension pic_size;
+    memset(&pic_size, 0, sizeof(mm_dimension));
+    pic_size.w = 4000;
+    pic_size.h = 3000;
+    test_obj->jpeg_hdl = cam_app->hal_lib.jpeg_open(&test_obj->jpeg_ops,pic_size);
     if (test_obj->jpeg_hdl == 0) {
         CDBG_ERROR("%s: jpeg lib open err", __func__);
         rc = -MM_CAMERA_E_GENERAL;
@@ -963,7 +967,6 @@
         goto ERROR;
     }
 
-    printf("%s: Setting AECLock value %d \n", __func__, value);
     rc = AddSetParmEntryToBatch(test_obj,
                                 CAM_INTF_PARM_AEC_LOCK,
                                 sizeof(value),
@@ -993,7 +996,6 @@
         goto ERROR;
     }
 
-    printf("%s: Setting AWB Lock value %d \n", __func__, value);
     rc = AddSetParmEntryToBatch(test_obj,
                                 CAM_INTF_PARM_AWB_LOCK,
                                 sizeof(value),
@@ -1875,9 +1877,7 @@
     }
 
     if(run_tc) {
-        printf("\tRunning unit test engine only\n");
         rc = mm_app_unit_test_entry(&my_cam_app);
-        printf("\tUnit test engine. EXIT(%d)!!!\n", rc);
         return rc;
     }
 #if 0
@@ -1895,6 +1895,7 @@
 {
   void *(*tuning_open_lib)(void) = NULL;
 
+  CDBG("%s  %d\n", __func__, __LINE__);
   tuning_param->lib_handle = dlopen("libmmcamera_tuning.so", RTLD_NOW);
   if (!tuning_param->lib_handle) {
     CDBG_ERROR("%s Failed opening libmmcamera_tuning.so\n", __func__);
@@ -1908,15 +1909,18 @@
     return -EINVAL;
   }
 
+  if (tuning_param->func_tbl) {
+    CDBG_ERROR("%s already loaded tuninglib..", __func__);
+    return 0;
+  }
+
   tuning_param->func_tbl = (mm_camera_tune_func_t *)tuning_open_lib();
   if (!tuning_param->func_tbl) {
     CDBG_ERROR("%s Failed opening library func table ptr\n", __func__);
     return -EINVAL;
   }
 
-  CDBG_ERROR("tuning_param->func_tbl =%p",tuning_param->func_tbl);
-
-  CDBG("exit");
+  CDBG("%s  %d\n", __func__, __LINE__);
   return 0;
 }
 
@@ -1950,7 +1954,8 @@
         goto EXIT;
     }
 
-    rc = mm_app_initialize_fb(&handle->test_obj);
+    //rc = mm_app_initialize_fb(&handle->test_obj);
+    rc = MM_CAMERA_OK;
     if (rc != MM_CAMERA_OK) {
         CDBG_ERROR("%s: mm_app_initialize_fb() cam_idx=%d, err=%d\n",
                    __func__, cam_id, rc);
@@ -2495,7 +2500,8 @@
         goto EXIT;
     }
 
-    rc = mm_app_close_fb(&handle->test_obj);
+    //rc = mm_app_close_fb(&handle->test_obj);
+    rc = MM_CAMERA_OK;
     if (rc != MM_CAMERA_OK) {
         CDBG_ERROR("%s:mm_app_close_fb() err=%d\n",
                    __func__, rc);
@@ -2517,10 +2523,9 @@
    mm_camera_lib_handle *handle, prev_callback cb)
 {
     if (handle->test_obj.user_preview_cb != NULL) {
-        CDBG_ERROR("%s, already set user preview callbacks...", __func__);
+        CDBG_ERROR("%s, already set preview callbacks\n", __func__);
         return -1;
     }
     handle->test_obj.user_preview_cb = *cb;
-    printf("%s  %d pointer =%p\n", __func__, __LINE__, handle->test_obj.user_preview_cb);
     return 0;
 }
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_commands.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_commands.c
new file mode 100755
index 0000000..890a8cb
--- /dev/null
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_commands.c
@@ -0,0 +1,291 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <stdlib.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <dlfcn.h>
+#include <mm_qcamera_app.h>
+#include "mm_qcamera_commands.h"
+#include "mm_qcamera_dbg.h"
+
+int tuneserver_initialize_prevtuningp(void * ctrl,
+  int pr_client_socket_id, cam_dimension_t dimension,
+  char **send_buf, uint32_t *send_len)
+{
+  int result = 0;
+  mm_camera_lib_handle *lib_handle = (mm_camera_lib_handle *) ctrl;
+  tuningserver_t *tctrl = &lib_handle->tsctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  if (tctrl->tuning_params.func_tbl->prevcommand_process == NULL) {
+      ALOGE("%s  %d\n", __func__, __LINE__);
+      return -1;
+  }
+
+  result = tctrl->tuning_params.func_tbl->prevcommand_process(
+      NULL, TUNE_PREVCMD_INIT, (void *)&pr_client_socket_id,
+      send_buf, send_len);
+  result = tctrl->tuning_params.func_tbl->prevcommand_process(
+      NULL, TUNE_PREVCMD_SETDIM, (void *)&dimension,
+      send_buf, send_len);
+
+  mm_camera_lib_set_preview_usercb(lib_handle,
+      (tctrl->tuning_params.func_tbl->prevframe_callback));
+
+  return result;
+}
+
+int tuneserver_deinitialize_prevtuningp(void * ctrl,
+    char **send_buf, uint32_t *send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+
+  result = tctrl->tuning_params.func_tbl->prevcommand_process(
+    &tctrl->pr_proto, TUNE_PREVCMD_DEINIT, NULL, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_preview_getinfo(void * ctrl, char **send_buf, uint32_t *send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->prevcommand_process(
+    &tctrl->pr_proto, TUNE_PREVCMD_GETINFO, NULL, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_preview_getchunksize(void * ctrl,
+  char **send_buf, uint32_t *send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->prevcommand_process(
+    &tctrl->pr_proto, TUNE_PREVCMD_GETCHUNKSIZE,
+    (void *)&tctrl->pr_proto->new_cnk_size, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_preview_getframe(void * ctrl,
+  char **send_buf, uint32_t *send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->prevcommand_process(
+    &tctrl->pr_proto, TUNE_PREVCMD_GETFRAME, NULL, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_preview_unsupported(void * ctrl,
+  char **send_buf, uint32_t *send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->prevcommand_process(
+    &tctrl->pr_proto, TUNE_PREVCMD_UNSUPPORTED, NULL, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_initialize_tuningp(void * ctrl, int client_socket_id,
+  char *send_buf, uint32_t send_len)
+{
+  int result = 0;
+  mm_camera_lib_handle *lib_handle = (mm_camera_lib_handle *) ctrl;
+  tuningserver_t *tctrl = &lib_handle->tsctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->command_process(
+    lib_handle, TUNE_CMD_INIT, &client_socket_id, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_deinitialize_tuningp(void * ctrl, int client_socket_id,
+  char *send_buf, uint32_t send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+
+  result = tctrl->tuning_params.func_tbl->command_process(
+    NULL, TUNE_CMD_DEINIT, &client_socket_id, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_process_get_list_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->command_process(
+     recv_cmd, TUNE_CMD_GET_LIST, NULL, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_process_get_params_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->command_process
+    (recv_cmd, TUNE_CMD_GET_PARAMS, NULL, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_process_set_params_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->command_process(
+     recv_cmd, TUNE_CMD_SET_PARAMS, NULL, send_buf, send_len);
+
+  return result;
+}
+
+int tuneserver_process_misc_cmd(void * ctrl, void *recv_cmd,
+  char *send_buf, uint32_t send_len)
+{
+  int result = 0;
+  tuningserver_t *tctrl = (tuningserver_t *) ctrl;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = tctrl->tuning_params.func_tbl->command_process(
+     recv_cmd, TUNE_CMD_MISC, NULL, send_buf, send_len);
+
+  return result;
+}
+
+/** tuneserver_close_cam
+ *    @lib_handle: the camera handle object
+ *
+ *  closes the camera
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+int tuneserver_close_cam(mm_camera_lib_handle *lib_handle)
+{
+  int result = 0;
+
+  result = mm_camera_lib_close(lib_handle);
+  if (result < 0) {
+    printf("%s: Camera close failed\n", __func__);
+  } else {
+    printf("Camera is closed \n");
+  }
+  return result;
+}
+#if 0
+/** tuneserver_start_cam
+ *    @lib_handle: the camera handle object
+ *
+ *  starts the camera
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+static int tuneserver_start_cam(mm_camera_lib_handle *lib_handle)
+{
+  int result = 0;
+
+  result = mm_camera_lib_start_stream(lib_handle);
+  if (result < 0) {
+    printf("%s: Camera start failed\n", __func__);
+    goto error1;
+  }
+  return result;
+error1:
+  mm_camera_lib_close(lib_handle);
+  return result;
+}
+#endif
+
+/** tuneserver_stop_cam
+ *    @lib_handle: the camera handle object
+ *
+ *  stops the camera
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+int tuneserver_stop_cam(mm_camera_lib_handle *lib_handle)
+{
+  int result = 0;
+
+  result = mm_camera_lib_stop_stream(lib_handle);
+  if (result < 0) {
+    printf("%s: Camera stop failed\n", __func__);
+  }
+//  result = mm_camera_lib_close(lib_handle);
+  return result;
+}
+
+/** tuneserver_open_cam
+ *    @lib_handle: the camera handle object
+ *
+ *  opens the camera
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+#if 1
+int tuneserver_open_cam(mm_camera_lib_handle *lib_handle)
+{
+  int result = 0;
+
+  CDBG("%s  %d\n", __func__, __LINE__);
+  result = mm_camera_load_tuninglibrary(&lib_handle->tsctrl.tuning_params);
+  if (result < 0) {
+    CDBG_ERROR("%s: tuning library open failed\n", __func__);
+  }
+  return result;
+}
+#endif
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c
old mode 100755
new mode 100644
index 149a295..394bbbb
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_main_menu.c
@@ -37,6 +37,7 @@
 #include "mm_qcamera_main_menu.h"
 #include "mm_qcamera_app.h"
 #include "mm_qcamera_dbg.h"
+#include "mm_qcamera_socket.h"
 
 /*===========================================================================
  * Macro
@@ -1690,6 +1691,9 @@
             goto ERROR;
         }
     }
+    /*start the eztune server*/
+    CDBG_HIGH("Starting eztune Server \n");
+    eztune_server_start(&lib_handle);
 
     do {
         print_current_menu (current_menu_id);
@@ -1712,7 +1716,6 @@
                     CDBG_ERROR("%s:mm_camera_lib_start_stream() err=%d\n", __func__, rc);
                     goto ERROR;
                 }
-
                 previewing = 1;
                 break;
 
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
index 10c38b1..7a2e750 100644
--- a/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_preview.c
@@ -129,7 +129,6 @@
     }
 #endif
     if (pme->user_preview_cb) {
-        printf("%s call back %d\n", __func__, __LINE__);
         CDBG_ERROR("[DBG] %s, user defined own preview cb. calling it...", __func__);
         pme->user_preview_cb(frame);
     }
diff --git a/QCamera2/stack/mm-camera-test/src/mm_qcamera_socket.c b/QCamera2/stack/mm-camera-test/src/mm_qcamera_socket.c
new file mode 100644
index 0000000..ae5c729
--- /dev/null
+++ b/QCamera2/stack/mm-camera-test/src/mm_qcamera_socket.c
@@ -0,0 +1,862 @@
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include "mm_qcamera_socket.h"
+#include "mm_qcamera_commands.h"
+#include "mm_qcamera_dbg.h"
+
+#define IP_ADDR                  "127.0.0.1"
+#define TUNING_CHROMATIX_PORT     55555
+#define TUNING_PREVIEW_PORT       55556
+
+#define CURRENT_COMMAND_ACK_SUCCESS 1
+#define CURRENT_COMMAND_ACK_FAILURE 2
+
+pthread_t eztune_thread_id;
+
+static int tuneserver_send_command_rsp(tuningserver_t *tsctrl,
+  char *send_buf, uint32_t send_len)
+{
+  int rc;
+
+  /* send ack back to client upon req */
+  if (send_len <= 0) {
+    ALOGE("%s:Invalid send len \n", __func__);
+    return -1;
+  }
+  if (send_buf == NULL) {
+    ALOGE("%s:Invalid send buf \n", __func__);
+    return -1;
+  }
+
+  rc = send(tsctrl->clientsocket_id, send_buf, send_len, 0);
+  if (rc < 0) {
+    ALOGE("%s:RSP send returns error %s\n", __func__, strerror(errno));
+  } else {
+    rc = 0;
+  }
+
+  if (send_buf != NULL) {
+    free(send_buf);
+    send_buf = NULL;
+  }
+  return rc;
+}
+
+static void release_eztune_prevcmd_rsp(eztune_prevcmd_rsp *pHead)
+{
+  if (pHead != NULL ) {
+    release_eztune_prevcmd_rsp((eztune_prevcmd_rsp *)pHead->next);
+    free(pHead);
+  }
+}
+
+static int tuneserver_ack(uint16_t a, uint32_t b, tuningserver_t *tsctrl)
+{
+  int rc;
+  char ack_1[6];
+  /*Ack the command here*/
+  memcpy(ack_1, &a, 2);
+  memcpy(ack_1+2, &b, 4);
+  /* send echo back to client upon accept */
+  rc = send(tsctrl->clientsocket_id, &ack_1, sizeof(ack_1), 0);
+  if (rc < 0) {
+    ALOGE("%s: eztune_server_run: send returns error %s\n", __func__,
+      strerror(errno));
+    return rc;
+  } else if (rc < (int32_t)sizeof(ack_1)) {
+    /*Shouldn't hit this for packets <1K; need to re-send if we do*/
+  }
+  return 0;
+}
+
+static int tuneserver_send_command_ack( uint8_t ack, tuningserver_t *tsctrl)
+{
+  int rc;
+  /* send ack back to client upon req */
+  rc = send(tsctrl->clientsocket_id, &ack, sizeof(ack), 0);
+  if (rc < 0) {
+    ALOGE("%s:ACK send returns error %s\n", __func__, strerror(errno));
+    return rc;
+  }
+  return 0;
+}
+
+/** tuneserver_process_command
+ *    @tsctrl: the server control object
+ *
+ *  Processes the command that the client sent
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+static int32_t tuneserver_process_command(tuningserver_t *tsctrl,
+  char *send_buf, uint32_t send_len)
+{
+  tuneserver_protocol_t *p = tsctrl->proto;
+  int result = 0;
+
+  CDBG("%s: Current command is %d\n", __func__, p->current_cmd);
+  switch (p->current_cmd) {
+  case TUNESERVER_GET_LIST:
+    if(tuneserver_send_command_ack(CURRENT_COMMAND_ACK_SUCCESS, tsctrl)) {
+      ALOGE("%s: Ack Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    result = tuneserver_process_get_list_cmd(tsctrl, p->recv_buf,
+      send_buf, send_len);
+    if (result < 0) {
+      ALOGE("%s: RSP processing Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if(tuneserver_send_command_rsp(tsctrl, send_buf, send_len)) {
+      ALOGE("%s: RSP Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    break;
+
+  case TUNESERVER_GET_PARMS:
+    if(tuneserver_send_command_ack(CURRENT_COMMAND_ACK_SUCCESS, tsctrl)) {
+      ALOGE("%s: Ack Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    result = tuneserver_process_get_params_cmd(tsctrl, p->recv_buf,
+      send_buf, send_len);
+    if (result < 0) {
+      ALOGE("%s: RSP processing Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if(tuneserver_send_command_rsp(tsctrl, send_buf, send_len)) {
+      ALOGE("%s: RSP Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    break;
+
+  case TUNESERVER_SET_PARMS:
+    if(tuneserver_send_command_ack(CURRENT_COMMAND_ACK_SUCCESS, tsctrl)) {
+      ALOGE("%s: Ack Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    result = tuneserver_process_set_params_cmd(tsctrl, p->recv_buf,
+      send_buf, send_len);
+    if (result < 0) {
+      ALOGE("%s: RSP processing Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if(tuneserver_send_command_rsp(tsctrl, send_buf, send_len)) {
+      ALOGE("%s: RSP Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    break;
+
+  case TUNESERVER_MISC_CMDS: {
+    if(tuneserver_send_command_ack(CURRENT_COMMAND_ACK_SUCCESS, tsctrl)) {
+      ALOGE("%s: Ack Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    result = tuneserver_process_misc_cmd(tsctrl, p->recv_buf,
+      send_buf, send_len);
+    if (result < 0) {
+      ALOGE("%s: RSP processing Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if(tuneserver_send_command_rsp(tsctrl, send_buf, send_len)) {
+      ALOGE("%s: RSP Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    break;
+  }
+
+  default:
+    if(tuneserver_send_command_ack(CURRENT_COMMAND_ACK_SUCCESS, tsctrl)) {
+      ALOGE("%s: Ack Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    ALOGE("%s: p->current_cmd: default\n", __func__);
+    result = -1;
+    break;
+  }
+
+  return result;
+}
+
+/** tuneserver_process_client_message
+ *    @recv_buffer: received message from the client
+ *    @tsctrl: the server control object
+ *
+ *  Processes the message from client and prepares for next
+ *  message.
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+static int32_t tuneserver_process_client_message(void *recv_buffer,
+  tuningserver_t *tsctrl)
+{
+  int rc = 0;
+  tuneserver_protocol_t *p = tsctrl->proto;
+
+  switch (tsctrl->proto->next_recv_code) {
+  case TUNESERVER_RECV_COMMAND:
+    p->current_cmd = *(uint16_t *)recv_buffer;
+    p->next_recv_code = TUNESERVER_RECV_PAYLOAD_SIZE;
+    p->next_recv_len = sizeof(uint32_t);
+    break;
+
+  case TUNESERVER_RECV_PAYLOAD_SIZE:
+    p->next_recv_code = TUNESERVER_RECV_PAYLOAD;
+    p->next_recv_len = *(uint32_t *)recv_buffer;
+    p->recv_len = p->next_recv_len;
+    if (p->next_recv_len > TUNESERVER_MAX_RECV)
+      return -1;
+    if (p->next_recv_len == 0) {
+      p->next_recv_code = TUNESERVER_RECV_RESPONSE;
+      p->next_recv_len = sizeof(uint32_t);
+    }
+    break;
+
+  case TUNESERVER_RECV_PAYLOAD:
+    p->recv_buf = malloc(p->next_recv_len);
+    if (!p->recv_buf) {
+      ALOGE("%s:Error allocating memory for recv_buf %s\n", __func__,
+        strerror(errno));
+      return -1;
+    }
+    memcpy(p->recv_buf, recv_buffer, p->next_recv_len);
+    p->next_recv_code = TUNESERVER_RECV_RESPONSE;
+    p->next_recv_len = sizeof(uint32_t);
+    /*Process current command at this point*/
+    break;
+
+  case TUNESERVER_RECV_RESPONSE:
+    p->next_recv_code = TUNESERVER_RECV_COMMAND;
+    p->next_recv_len = 2;
+    p->send_len = *(uint32_t *)recv_buffer;
+    p->send_buf =  (char *)calloc(p->send_len, sizeof(char *));
+    if (!p->send_buf) {
+      ALOGE("%s:Error allocating memory for send_buf %s\n", __func__,
+        strerror(errno));
+      return -1;
+    }
+    rc = tuneserver_process_command(tsctrl, p->send_buf, p->send_len);
+    free(p->recv_buf);
+    p->recv_buf = NULL;
+    p->recv_len = 0;
+    break;
+
+  default:
+    ALOGE("%s: p->next_recv_code: default\n", __func__);
+    rc = -1;
+    break;
+  }
+
+  return rc;
+}
+
+/** tuneserver_ack_onaccept_initprotocol
+ *    @tsctrl: the server control object
+ *
+ *  Acks a connection from the cient and sets up the
+ *  protocol object to start receiving commands.
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+static int32_t tuneserver_ack_onaccept_initprotocol(tuningserver_t *tsctrl)
+{
+  int32_t rc = 0;
+  uint32_t ack_status;
+
+  ALOGE("%s starts\n", __func__);
+/*
+  if(tsctrl->camera_running) {
+    ack_status = 1;
+  } else {
+    ack_status = 2;
+  }
+*/
+  ack_status = 1;
+
+  rc = tuneserver_ack(1, ack_status, tsctrl);
+
+  tsctrl->proto = malloc(sizeof(tuneserver_protocol_t));
+  if (!tsctrl->proto) {
+    ALOGE("%s: malloc returns NULL with error %s\n", __func__, strerror(errno));
+    return -1;
+  }
+
+  tsctrl->proto->current_cmd    = 0xFFFF;
+  tsctrl->proto->next_recv_code = TUNESERVER_RECV_COMMAND;
+  tsctrl->proto->next_recv_len  = 2;
+  tsctrl->proto->recv_buf       = NULL;
+  tsctrl->proto->send_buf       = NULL;
+
+  CDBG("%s end\n", __func__);
+
+  return rc;
+}
+
+/** tuneserver_check_status
+ *    @tsctrl: the server control object
+ *
+ *  Checks if camera is running and stops it.
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+#if 0
+static void tuneserver_check_status(tuningserver_t *tsctrl)
+{
+  if (tsctrl->camera_running == 1) {
+    /*TODO: Stop camera here*/
+    tuneserver_stop_cam(&tsctrl->lib_handle);
+  }
+  tsctrl->camera_running = 0;
+
+  tuneserver_close_cam(&tsctrl->lib_handle);
+}
+#endif
+
+static int prevserver_send_command_rsp(tuningserver_t *tsctrl,
+  char *send_buf, uint32_t send_len)
+{
+  int rc;
+
+  /* send ack back to client upon req */
+  if (send_len <= 0) {
+    ALOGE("%s:Invalid send len \n", __func__);
+    return -1;
+  }
+  if (send_buf == NULL) {
+    ALOGE("%s:Invalid send buf \n", __func__);
+    return -1;
+  }
+
+  rc = send(tsctrl->pr_clientsocket_id, send_buf, send_len, 0);
+  if (rc < 0) {
+    ALOGE("%s:RSP send returns error %s\n", __func__, strerror(errno));
+  } else {
+    rc = 0;
+  }
+  if (send_buf != NULL) {
+    free(send_buf);
+    send_buf = NULL;
+  }
+  return rc;
+}
+
+static void prevserver_init_protocol(tuningserver_t *tsctrl)
+{
+  tsctrl->pr_proto = malloc(sizeof(prserver_protocol_t));
+  if (!tsctrl->pr_proto) {
+    ALOGE("%s: malloc returns NULL with error %s\n",
+     __func__, strerror(errno));
+    return;
+  }
+
+  tsctrl->pr_proto->current_cmd    = 0xFFFF;
+  tsctrl->pr_proto->next_recv_code = TUNE_PREV_RECV_COMMAND;
+  tsctrl->pr_proto->next_recv_len  = 2;
+}
+
+static int32_t prevserver_process_command(
+  tuningserver_t *tsctrl, char **send_buf, uint32_t *send_len)
+{
+  prserver_protocol_t *p = tsctrl->pr_proto;
+  int result = 0;
+  eztune_prevcmd_rsp *rsp_ptr=NULL, *rspn_ptr=NULL, *head_ptr=NULL;
+
+  CDBG("%s: Current command is %d\n", __func__, p->current_cmd);
+  switch (p->current_cmd) {
+  case TUNE_PREV_GET_INFO:
+    result = tuneserver_preview_getinfo(tsctrl, send_buf, send_len);
+    if (result < 0) {
+      ALOGE("%s: RSP processing Failed for cmd %d\n", __func__,
+        p->current_cmd);
+      return -1;
+    }
+    rsp_ptr = (eztune_prevcmd_rsp *)*send_buf;
+    if ((!rsp_ptr) || (!rsp_ptr->send_buf)) {
+      ALOGE("%s: RSP ptr is NULL %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if (prevserver_send_command_rsp(tsctrl,
+      rsp_ptr->send_buf, rsp_ptr->send_len)) {
+      ALOGE("%s: RSP Failed for TUNE_PREV_GET_INFO ver cmd %d\n", __func__,
+        p->current_cmd);
+      return -1;
+    }
+    rspn_ptr = (eztune_prevcmd_rsp *)rsp_ptr->next;
+    if ((!rspn_ptr) || (!rspn_ptr->send_buf)) {
+      ALOGE("%s: RSP1 ptr is NULL %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if (prevserver_send_command_rsp(tsctrl,
+        rspn_ptr->send_buf, rspn_ptr->send_len)) {
+      ALOGE("%s: RSP Failed for TUNE_PREV_GET_INFO caps cmd %d\n", __func__,
+        p->current_cmd);
+      return -1;
+    }
+    free(rspn_ptr);
+    free(rsp_ptr);
+    break;
+
+  case TUNE_PREV_CH_CNK_SIZE:
+    result = tuneserver_preview_getchunksize(tsctrl, send_buf, send_len);
+    if (result < 0) {
+      ALOGE("%s: RSP processing Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if (prevserver_send_command_rsp(tsctrl, *send_buf, *send_len)) {
+      ALOGE("%s: RSP Failed for TUNE_PREV_CH_CNK_SIZE cmd %d\n", __func__,
+        p->current_cmd);
+      return -1;
+    }
+    break;
+
+  case TUNE_PREV_GET_PREV_FRAME:
+    result = tuneserver_preview_getframe(tsctrl, send_buf, send_len);
+    if (result < 0) {
+      ALOGE("%s: RSP processing Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    rsp_ptr = (eztune_prevcmd_rsp *)*send_buf;
+    if ((!rsp_ptr) || (!rsp_ptr->send_buf)) {
+      ALOGE("%s: RSP ptr is NULL %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    head_ptr = rsp_ptr;
+
+    while (rsp_ptr != NULL) {
+      if ((!rsp_ptr) || (!rsp_ptr->send_buf)) {
+        ALOGE("%s: RSP ptr is NULL %d\n", __func__, p->current_cmd);
+        return -1;
+      }
+      if (prevserver_send_command_rsp(tsctrl,
+        rsp_ptr->send_buf, rsp_ptr->send_len)) {
+        ALOGE("%s: RSP Failed for TUNE_PREV_GET_INFO ver cmd %d\n", __func__,
+          p->current_cmd);
+        return -1;
+      }
+      rsp_ptr = (eztune_prevcmd_rsp *)rsp_ptr->next;
+    }
+    release_eztune_prevcmd_rsp(head_ptr);
+    break;
+
+  case TUNE_PREV_GET_JPG_SNAP:
+  case TUNE_PREV_GET_RAW_SNAP:
+  case TUNE_PREV_GET_RAW_PREV:
+    result = tuneserver_preview_unsupported(tsctrl, send_buf, send_len);
+    if (result < 0) {
+       ALOGE("%s:RSP processing Failed for cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    if (prevserver_send_command_rsp(tsctrl, *send_buf, *send_len)) {
+      ALOGE("%s:RSP Failed for UNSUPPORTED cmd %d\n", __func__, p->current_cmd);
+      return -1;
+    }
+    break;
+
+  default:
+    ALOGE("%s: p->current_cmd: default\n", __func__);
+    result = -1;
+    break;
+  }
+
+  return result;
+}
+
+/** previewserver_process_client_message
+ *    @recv_buffer: received message from the client
+ *    @tsctrl: the server control object
+ *
+ *  Processes the message from client and prepares for next
+ *  message.
+ *
+ *  Return: >=0 on success, -1 on failure.
+ **/
+static int32_t prevserver_process_client_message(void *recv_buffer,
+  tuningserver_t *tsctrl)
+{
+  int rc = 0;
+  prserver_protocol_t *p = tsctrl->pr_proto;
+
+  switch (p->next_recv_code) {
+  case TUNE_PREV_RECV_COMMAND:
+    CDBG("%s  %d\n", __func__, __LINE__);
+    p->current_cmd = *(uint16_t *)recv_buffer;
+    if(p->current_cmd != TUNE_PREV_CH_CNK_SIZE) {
+      rc = prevserver_process_command(tsctrl,
+        &p->send_buf, (uint32_t *)&p->send_len);
+      break;
+    }
+    p->next_recv_code = TUNE_PREV_RECV_NEWCNKSIZE;
+    p->next_recv_len = sizeof(uint32_t);
+    CDBG("%s TUNE_PREV_COMMAND X\n", __func__);
+    break;
+  case TUNE_PREV_RECV_NEWCNKSIZE:
+    CDBG("%s  %d\n", __func__, __LINE__);
+    p->new_cnk_size = *(uint32_t *)recv_buffer;
+    p->next_recv_code = TUNE_PREV_RECV_COMMAND;
+    p->next_recv_len  = 2;
+    rc = prevserver_process_command(tsctrl,
+      &p->send_buf, (uint32_t *)&p->send_len);
+    break;
+  default:
+    ALOGE("%s prev_proc->next_recv_code: default\n", __func__);
+    rc = -1;
+    break;
+  }
+
+  return rc;
+}
+
+/** tunning_server_socket_listen
+ *    @ip_addr: the ip addr to listen
+ *    @port: the port to listen
+ *
+ *  Setup a listen socket for eztune.
+ *
+ *  Return: >0 on success, <=0 on failure.
+ **/
+int tunning_server_socket_listen(const char* ip_addr, uint16_t port)
+{
+  int sock_fd = -1;
+  struct sockaddr_in server_addr;
+  int result;
+  int option;
+  int socket_flag;
+
+  memset(&server_addr, 0, sizeof(server_addr));
+  server_addr.sin_family = AF_INET;
+  server_addr.sin_port= htons(port);
+  server_addr.sin_addr.s_addr = inet_addr(ip_addr);
+
+  if (server_addr.sin_addr.s_addr == INADDR_NONE) {
+    ALOGE("[ERR] %s invalid address.\n", __func__);
+    return -1;
+  }
+
+  /* Create an AF_INET stream socket to receive incoming connection ON */
+  sock_fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (sock_fd < 0) {
+    ALOGE("[ERR] %s socket failed\n", __func__);
+    return sock_fd;
+  }
+
+  // set listen socket to non-block, but why??
+  socket_flag = fcntl(sock_fd, F_GETFL, 0);
+  fcntl(sock_fd, F_SETFL, socket_flag | O_NONBLOCK);
+
+  /* reuse in case it is in timeout */
+  option = 1;
+  result = setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR,
+    &option, sizeof(option));
+
+  if (result < 0) {
+    ALOGE("eztune setsockopt failed");
+    close(sock_fd);
+    sock_fd = -1;
+    return sock_fd;
+  }
+
+  result = bind(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr));
+  if (result < 0) {
+    ALOGE("eztune socket bind failed");
+    close(sock_fd);
+    sock_fd = -1;
+    return sock_fd;
+  }
+
+  result = listen(sock_fd, 1);
+  if (result < 0) {
+    ALOGE("eztune socket listen failed");
+    close(sock_fd);
+    sock_fd = -1;
+    return sock_fd;
+  }
+
+  CDBG_HIGH("%s. sock_fd: %d, listen at port: %d\n", __func__, sock_fd, port);
+
+  return sock_fd;
+}
+
+/** main
+ *
+ *  Creates the server, and starts waiting for
+ *  connections/messages from a prospective
+ *  client
+ *
+ **/
+void *eztune_proc(void *data)
+{
+  int server_socket = -1, client_socket = -1;
+  int prev_server_socket = -1, prev_client_socket = -1;
+
+  struct sockaddr_in addr_client_inet;
+  socklen_t addr_client_len = sizeof(struct sockaddr_in);
+  int result;
+  fd_set tsfds;
+  int num_fds = 0;
+  int recv_bytes;
+  char buf[TUNESERVER_MAX_RECV];
+
+  mm_camera_lib_handle *lib_handle = (mm_camera_lib_handle *)data;
+
+  ALOGE(">>> Starting tune server <<< \n");
+
+  // for eztune chromatix params
+  server_socket = tunning_server_socket_listen(IP_ADDR, TUNING_CHROMATIX_PORT);
+  if (server_socket <= 0) {
+    ALOGE("[ERR] fail to setup listen socket for eztune chromatix parms...");
+    return NULL;
+  }
+  prev_server_socket = tunning_server_socket_listen(IP_ADDR, TUNING_PREVIEW_PORT);
+  if (prev_server_socket <= 0) {
+    ALOGE("[ERR] fail to setup listen socket for eztune preview...\n");
+    return NULL;
+  }
+  num_fds = TUNESERVER_MAX(server_socket, prev_server_socket);
+  CDBG_HIGH("num_fds = %d\n", num_fds);
+
+  do {
+    FD_ZERO(&tsfds);
+    FD_SET(server_socket, &tsfds);
+    FD_SET(prev_server_socket, &tsfds);
+    if (client_socket > 0) {
+      FD_SET(client_socket, &tsfds);
+    }
+    if (prev_client_socket > 0) {
+      FD_SET( prev_client_socket, &tsfds);
+    }
+
+    /* no timeout */
+    result = select(num_fds + 1, &tsfds, NULL, NULL, NULL);
+    if (result < 0) {
+      ALOGE("[ERR] select failed: %s\n", strerror(errno));
+      continue;
+    }
+
+    /*
+     ** (1) CHROMATIX SERVER
+     */
+    if (FD_ISSET(server_socket, &tsfds)) {
+      CDBG("Receiving New client connection\n");
+
+      client_socket = accept(server_socket,
+        (struct sockaddr *)&addr_client_inet, &addr_client_len);
+      if (client_socket == -1) {
+        ALOGE("accept failed %s", strerror(errno));
+        continue;
+      }
+
+      ALOGE("accept a new connect on 55555, sd(%d)\n", client_socket);
+      num_fds = TUNESERVER_MAX(num_fds, client_socket);
+
+      // open camera and get handle - this is needed to
+      // be able to set parameters without starting
+      // preview stream
+      /*if (!tsctrl.camera_running) {
+        result = tuneserver_open_cam(&tsctrl.lib_handle, &tsctrl);
+        if(result) {
+          printf("\n Camera Open Fail !!! \n");
+          close(server_socket);
+          return EXIT_FAILURE;
+        }
+      }*/
+      result = tuneserver_open_cam(lib_handle);
+      if(result) {
+        ALOGE("\n Tuning Library open failed!!!\n");
+        close(server_socket);
+        return NULL;
+      }
+      lib_handle->tsctrl.clientsocket_id = client_socket;
+      if (tuneserver_ack_onaccept_initprotocol(&lib_handle->tsctrl) < 0) {
+        ALOGE("%s: Error while acking\n", __func__);
+        close(client_socket);
+        continue;
+      }
+      tuneserver_initialize_tuningp(lib_handle, client_socket,
+        lib_handle->tsctrl.proto->send_buf, lib_handle->tsctrl.proto->send_len);
+    }
+
+    if (FD_ISSET(client_socket, &tsfds)) {
+      if (lib_handle->tsctrl.proto == NULL) {
+        ALOGE("%s: Cannot receive msg without connect\n", __func__);
+        continue;
+      }
+
+      /*Receive message and process it*/
+      recv_bytes = recv(client_socket, (void *)buf,
+        lib_handle->tsctrl.proto->next_recv_len, 0);
+      CDBG("Receive %d bytes \n", recv_bytes);
+
+      if (recv_bytes == -1) {
+        ALOGE("%s: Receive failed with error %s\n", __func__, strerror(errno));
+        //tuneserver_check_status(&tsctrl);
+        continue;
+      } else if (recv_bytes == 0) {
+        ALOGE("%s %d: connection has been terminated\n", __func__, __LINE__);
+
+        tuneserver_deinitialize_tuningp(&lib_handle->tsctrl, client_socket,
+          lib_handle->tsctrl.proto->send_buf,
+          lib_handle->tsctrl.proto->send_len);
+        free(lib_handle->tsctrl.proto);
+        lib_handle->tsctrl.proto = NULL;
+
+        close(client_socket);
+        client_socket = 0;
+        //tuneserver_check_status(&tsctrl);
+      } else {
+        CDBG("%s: Processing socket command\n", __func__);
+
+        result = tuneserver_process_client_message(buf, &lib_handle->tsctrl);
+
+        if (result < 0) {
+          ALOGE("%s %d Protocol violated\n", __func__, __LINE__);
+
+          free(lib_handle->tsctrl.proto);
+          lib_handle->tsctrl.proto = NULL;
+
+          close(client_socket);
+          client_socket = 0;
+          //tuneserver_check_status(&tsctrl);
+          continue;
+        }
+      }
+    }
+
+    /*
+     ** (2) PREVIEW SERVER
+     */
+    if (FD_ISSET(prev_server_socket, &tsfds)) {
+      CDBG("Receiving New Preview client connection\n");
+
+      prev_client_socket = accept(prev_server_socket,
+        (struct sockaddr *)&addr_client_inet, &addr_client_len);
+      if (prev_client_socket == -1) {
+        ALOGE("accept failed %s", strerror(errno));
+        continue;
+      }
+
+      lib_handle->tsctrl.pr_clientsocket_id = prev_client_socket;
+
+      CDBG("Accepted a new connection, fd(%d)\n", prev_client_socket);
+      num_fds = TUNESERVER_MAX(num_fds, prev_client_socket);
+
+      // start camera
+      /*if (!tsctrl.camera_running) {
+        result = 0;
+        result = tuneserver_open_cam(&tsctrl.lib_handle, &tsctrl);
+        if(result) {
+          printf("\n Camera Open Fail !!! \n");
+          return EXIT_FAILURE;
+        }
+      }*/
+      cam_dimension_t dim;
+      dim.width = lib_handle->test_obj.buffer_width;
+      dim.height = lib_handle->test_obj.buffer_height;
+
+      CDBG("preview dimension info: w(%d), h(%d)\n", dim.width, dim.height);
+      // we have to make sure that camera is running, before init connection,
+      // because we need to know the frame size for allocating the memory.
+      prevserver_init_protocol(&lib_handle->tsctrl);
+
+      result = tuneserver_initialize_prevtuningp(lib_handle, prev_client_socket,
+        dim, (char **)&lib_handle->tsctrl.proto->send_buf,
+        &lib_handle->tsctrl.proto->send_len);
+      if (result < 0) {
+        ALOGE("tuneserver_initialize_prevtuningp error!");
+        close(prev_client_socket);
+        prev_client_socket = 0;
+      }
+    }
+
+    if (FD_ISSET(prev_client_socket, &tsfds)) {
+      recv_bytes = recv(prev_client_socket, (void *)buf,
+        lib_handle->tsctrl.pr_proto->next_recv_len, 0);
+
+      CDBG("%s prev_client_socket=%d\n", __func__, prev_client_socket);
+      CDBG("%s next_recv_len=%d\n", __func__, *(uint16_t *)buf);
+
+      if (recv_bytes <= 0) {
+        if (recv_bytes == 0) {
+          ALOGE("client close the connection.\n");
+        } else {
+          ALOGE("receive error: %s\n", strerror(errno));
+        }
+
+        //tuneserver_check_status(&tsctrl);
+        // if recv error, we should close the connection, free the proto data,
+        // AND wait for a new connecton..
+        // close_connection();
+        // stop_camera()
+        // cleanup_proto_data();
+        tuneserver_deinitialize_prevtuningp(&lib_handle->tsctrl,
+          (char **)&lib_handle->tsctrl.proto->send_buf,
+          &lib_handle->tsctrl.proto->send_len);
+        close(prev_client_socket);
+        prev_client_socket = 0;
+      } else {
+        result = prevserver_process_client_message((void *)buf,
+          &lib_handle->tsctrl);
+        if (result < 0) {
+          ALOGE("%s %d Protocol violated\n", __func__, __LINE__);
+
+          //free(tsctrl->preivew_proto);
+          //free(tsctrl);
+          //max_fd = ezt_parms_listen_sd + 1;
+          tuneserver_deinitialize_prevtuningp(&lib_handle->tsctrl,
+            (char **)&lib_handle->tsctrl.proto->send_buf,
+            &lib_handle->tsctrl.proto->send_len);
+          close(prev_client_socket);
+          prev_client_socket = 0;
+          //tuneserver_check_status(&tsctrl);
+        }
+        //sleep(1);
+      }
+    }
+  } while (1);
+
+  if (server_socket > 0) {
+    close(server_socket);
+  }
+  if (client_socket > 0) {
+    close(client_socket);
+  }
+  if (prev_server_socket > 0) {
+    close(prev_server_socket);
+  }
+  if (prev_client_socket > 0) {
+    close(prev_client_socket);
+  }
+
+  return EXIT_SUCCESS;
+}
+
+int eztune_server_start (void *lib_handle)
+{
+  return pthread_create(&eztune_thread_id, NULL,  eztune_proc, lib_handle);
+}
+
diff --git a/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h b/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
index 00f9a81..1dfe50b 100644
--- a/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
+++ b/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg.h
@@ -387,7 +387,6 @@
   uint32_t* p_session_id);
 extern int32_t mm_jpeg_destroy_session_by_id(mm_jpeg_obj *my_obj,
   uint32_t session_id);
-extern int32_t mm_jpeg_destroy_job(mm_jpeg_job_session_t *p_session);
 
 extern int32_t mm_jpegdec_init(mm_jpeg_obj *my_obj);
 extern int32_t mm_jpegdec_deinit(mm_jpeg_obj *my_obj);
diff --git a/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg_inlines.h b/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg_inlines.h
index 0a8025b..39fec8d 100644
--- a/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg_inlines.h
+++ b/QCamera2/stack/mm-jpeg-interface/inc/mm_jpeg_inlines.h
@@ -65,35 +65,6 @@
   return p_session;
 }
 
-/** mm_jpeg_session_encode:
- *
- *  Arguments:
- *    @p_session: encode session
- *
- *  Return:
- *       OMX_ERRORTYPE
- *
- *  Description:
- *       Start the encoding
- *
- **/
-static inline void mm_jpeg_job_done(mm_jpeg_job_session_t *p_session)
-{
-  mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
-  mm_jpeg_job_q_node_t *node = NULL;
-
-  /*remove the job*/
-  node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
-    p_session->jobId);
-  if (node) {
-    free(node);
-  }
-  p_session->encoding = OMX_FALSE;
-
-  /* wake up jobMgr thread to work on new job if there is any */
-  cam_sem_post(&my_obj->job_mgr.job_sem);
-}
-
 /** mm_jpeg_get_job_idx:
  *
  *  Arguments:
diff --git a/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c b/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
index 13e7e88..2cb5dd4 100644
--- a/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
+++ b/QCamera2/stack/mm-jpeg-interface/src/mm_jpeg.c
@@ -55,6 +55,8 @@
     OMX_U32 nData2,
     OMX_PTR pEventData);
 
+static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session);
+static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session);
 
 /** mm_jpeg_session_send_buffers:
  *
@@ -1009,7 +1011,7 @@
       CDBG("%s:%d] OMX_SendCommand returned error %d", __func__, __LINE__, ret);
       return 1;
     }
-    rc = mm_jpeg_destroy_job(p_session);
+    rc = mm_jpegenc_destroy_job(p_session);
     if (rc != 0) {
       CDBG("%s:%d] Destroy job returned error %d", __func__, __LINE__, rc);
     }
@@ -1325,7 +1327,7 @@
   }
 
   /*remove the job*/
-  mm_jpeg_job_done(p_session);
+  mm_jpegenc_job_done(p_session);
   CDBG("%s:%d] Error X ", __func__, __LINE__);
 
   return rc;
@@ -1833,7 +1835,7 @@
   return rc;
 }
 
-/** mm_jpeg_destroy_job
+/** mm_jpegenc_destroy_job
  *
  *  Arguments:
  *    @p_session: Session obj
@@ -1845,7 +1847,7 @@
  *       Destroy the job based paramenters
  *
  **/
-int32_t mm_jpeg_destroy_job(mm_jpeg_job_session_t *p_session)
+static int32_t mm_jpegenc_destroy_job(mm_jpeg_job_session_t *p_session)
 {
   mm_jpeg_encode_job_t *p_jobparams = &p_session->encode_job;
   int i = 0, rc = 0;
@@ -1864,6 +1866,38 @@
   return rc;
 }
 
+/** mm_jpeg_session_encode:
+ *
+ *  Arguments:
+ *    @p_session: encode session
+ *
+ *  Return:
+ *       OMX_ERRORTYPE
+ *
+ *  Description:
+ *       Start the encoding
+ *
+ **/
+static void mm_jpegenc_job_done(mm_jpeg_job_session_t *p_session)
+{
+  mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
+  mm_jpeg_job_q_node_t *node = NULL;
+
+  /*Destroy job related params*/
+  mm_jpegenc_destroy_job(p_session);
+
+  /*remove the job*/
+  node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
+    p_session->jobId);
+  if (node) {
+    free(node);
+  }
+  p_session->encoding = OMX_FALSE;
+
+  /* wake up jobMgr thread to work on new job if there is any */
+  cam_sem_post(&my_obj->job_mgr.job_sem);
+}
+
 /** mm_jpeg_destroy_session:
  *
  *  Arguments:
@@ -2103,7 +2137,7 @@
       p_session->params.userdata);
 
     /* remove from ready queue */
-    mm_jpeg_job_done(p_session);
+    mm_jpegenc_job_done(p_session);
   }
   pthread_mutex_unlock(&p_session->lock);
   CDBG("%s:%d] ", __func__, __LINE__);
@@ -2152,7 +2186,7 @@
       }
 
       /* remove from ready queue */
-      mm_jpeg_job_done(p_session);
+      mm_jpegenc_job_done(p_session);
     }
     pthread_cond_signal(&p_session->cond);
   } else if (eEvent == OMX_EventCmdComplete) {
diff --git a/QCamera2/stack/mm-jpeg-interface/src/mm_jpegdec.c b/QCamera2/stack/mm-jpeg-interface/src/mm_jpegdec.c
index 65b7de8..0001714 100644
--- a/QCamera2/stack/mm-jpeg-interface/src/mm_jpegdec.c
+++ b/QCamera2/stack/mm-jpeg-interface/src/mm_jpegdec.c
@@ -53,6 +53,60 @@
     OMX_U32 nData2,
     OMX_PTR pEventData);
 
+
+/** mm_jpegdec_destroy_job
+ *
+ *  Arguments:
+ *    @p_session: Session obj
+ *
+ *  Return:
+ *       0 for success else failure
+ *
+ *  Description:
+ *       Destroy the job based paramenters
+ *
+ **/
+static int32_t mm_jpegdec_destroy_job(mm_jpeg_job_session_t *p_session)
+{
+  mm_jpeg_decode_job_t *p_jobparams = &p_session->decode_job;
+  int32_t rc = 0;
+
+  return rc;
+}
+
+/** mm_jpeg_job_done:
+ *
+ *  Arguments:
+ *    @p_session: decode session
+ *
+ *  Return:
+ *       OMX_ERRORTYPE
+ *
+ *  Description:
+ *       Finalize the job
+ *
+ **/
+static void mm_jpegdec_job_done(mm_jpeg_job_session_t *p_session)
+{
+  mm_jpeg_obj *my_obj = (mm_jpeg_obj *)p_session->jpeg_obj;
+  mm_jpeg_job_q_node_t *node = NULL;
+
+  /*Destroy job related params*/
+  mm_jpegdec_destroy_job(p_session);
+
+  /*remove the job*/
+  node = mm_jpeg_queue_remove_job_by_job_id(&my_obj->ongoing_job_q,
+    p_session->jobId);
+  if (node) {
+    free(node);
+  }
+  p_session->encoding = OMX_FALSE;
+
+  /* wake up jobMgr thread to work on new job if there is any */
+  cam_sem_post(&my_obj->job_mgr.job_sem);
+}
+
+
 /** mm_jpegdec_session_send_buffers:
  *
  *  Arguments:
@@ -163,6 +217,8 @@
   p_session->omx_callbacks.EmptyBufferDone = mm_jpegdec_ebd;
   p_session->omx_callbacks.FillBufferDone = mm_jpegdec_fbd;
   p_session->omx_callbacks.EventHandler = mm_jpegdec_event_handler;
+  p_session->exif_count_local = 0;
+
   rc = OMX_GetHandle(&p_session->omx_handle,
     "OMX.qcom.image.jpeg.decoder",
     (void *)p_session,
@@ -658,7 +714,7 @@
   }
 
   /*remove the job*/
-  mm_jpeg_job_done(p_session);
+  mm_jpegdec_job_done(p_session);
   CDBG("%s:%d] Error X ", __func__, __LINE__);
 
   return rc;
@@ -936,7 +992,7 @@
       p_session->dec_params.userdata);
 
     /* remove from ready queue */
-    mm_jpeg_job_done(p_session);
+    mm_jpegdec_job_done(p_session);
   }
   pthread_mutex_unlock(&p_session->lock);
   CDBG("%s:%d] ", __func__, __LINE__);
@@ -984,7 +1040,7 @@
       }
 
       /* remove from ready queue */
-      mm_jpeg_job_done(p_session);
+      mm_jpegdec_job_done(p_session);
     }
     pthread_cond_signal(&p_session->cond);
   } else if (eEvent == OMX_EventCmdComplete) {