camera: change to abort live snapshot.

This patch fixes below issues.
 (a) Abort liveshot when cancelpicture is issued.
 (b) Fix wrong buffer unmapping in live shot mode.
 (c) In monkey runs fix race condition when stop preview gets executed during
     receivecompletejpeg pic.

Bug: 7268830
Bug: 7254998
Bug: 7305012
Change-Id: I9461d32030a2d258e8c059824a4ef7fbb2a60198
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/camera/QCameraHWI.cpp b/camera/QCameraHWI.cpp
index c2911f5..a8713e9 100644
--- a/camera/QCameraHWI.cpp
+++ b/camera/QCameraHWI.cpp
@@ -188,7 +188,8 @@
                     mFocusMode(AF_MODE_MAX),
                     mPreviewFormat(CAMERA_YUV_420_NV21),
                     mRestartPreview(false),
-                    mReleasedRecordingFrame(false)
+                    mReleasedRecordingFrame(false),
+                    mStateLiveshot(false)
 {
     ALOGV("QCameraHardwareInterface: E");
     int32_t result = MM_CAMERA_E_GENERAL;
@@ -740,13 +741,13 @@
       mCameraState);
     switch(channelEvent) {
         case MM_CAMERA_CH_EVT_STREAMING_ON:
-          if (!mFullLiveshotEnabled) {
+          if (!mStateLiveshot) {
             mCameraState =
               isZSLMode() ? CAMERA_STATE_ZSL : CAMERA_STATE_SNAP_CMD_ACKED;
           }
           break;
         case MM_CAMERA_CH_EVT_STREAMING_OFF:
-          if (!mFullLiveshotEnabled) {
+          if (!mStateLiveshot) {
             mCameraState = CAMERA_STATE_READY;
           }
           break;
@@ -1340,6 +1341,10 @@
         return;
     }
 
+    if(mStateLiveshot && mStreamLiveSnap != NULL) {
+        mStreamLiveSnap->stop();
+        mStateLiveshot = false;
+    }
     /*
     * call QCameraStream_record::stop()
     * Unregister Callback, action stop
@@ -1505,12 +1510,18 @@
         case QCAMERA_HAL_PREVIEW_STOPPED:
         case QCAMERA_HAL_PREVIEW_START:
         case QCAMERA_HAL_PREVIEW_STARTED:
+            break;
         case QCAMERA_HAL_RECORDING_STARTED:
-        default:
+            if(mStateLiveshot && (mStreamLiveSnap != NULL)) {
+                mStreamLiveSnap->stop();
+                mStateLiveshot = false;
+            }
             break;
         case QCAMERA_HAL_TAKE_PICTURE:
             ret = cancelPictureInternal();
             break;
+        default:
+            break;
     }
     ALOGI("cancelPicture: X");
     return ret;
@@ -1551,67 +1562,15 @@
     int mJpegMaxSize;
     int mNuberOfVFEOutputs = 0;
     status_t ret;
-    ALOGE("%s: E", __func__);
+    ALOGI("%s: E", __func__);
 
-    ret = cam_config_get_parm(pme->mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE,
-                       &mNuberOfVFEOutputs);
-    if (ret != MM_CAMERA_OK) {
-       ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE  failed");
-       cam_evt_buf_done(pme->mCameraId, recvd_frame);
-       return ;
+    if (!pme->mStateLiveshot) {
+        ALOGE("%s: Returning Buffer. Picture Cancelled", __func__);
+		return;
     }
 
-    mm_camera_ch_data_buf_t* frame =
-         (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
-    if (frame == NULL) {
-        ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
-        cam_evt_buf_done(pme->mCameraId, recvd_frame);
-		return ;
-    }
-    memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t));
-
-    if (mNuberOfVFEOutputs == 1)
-        ALOGE("<DEBUG> Liveshot buffer idx:%d",frame->def.idx);
-    else
-        ALOGE("<DEBUG> Liveshot buffer idx:%d",frame->video.video.idx);
-    memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
-    ret = cam_config_get_parm(pme->mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
-    if (MM_CAMERA_OK != ret) {
-        ALOGE("%s: error - can't get dimension!", __func__);
-        ALOGE("%s: X", __func__);
-    }
-
-#if 1
     ALOGE("Live Snapshot Enabled");
-    if (mNuberOfVFEOutputs == 1){
-       frame->snapshot.main.frame = frame->def.frame;
-       frame->snapshot.main.idx = frame->def.idx;
-       frame->snapshot.thumbnail.frame = frame->def.frame;
-       frame->snapshot.thumbnail.idx = frame->def.idx;
-    } else {
-       frame->snapshot.main.frame = frame->video.video.frame;
-       frame->snapshot.main.idx = frame->video.video.idx;
-       frame->snapshot.thumbnail.frame = frame->video.video.frame;
-       frame->snapshot.thumbnail.idx = frame->video.video.idx;
-    }
-
-    dim.picture_width = pme->mVideoWidth;
-    dim.picture_height = pme->mVideoHeight;
-    dim.ui_thumbnail_width = pme->mVideoWidth;
-    dim.ui_thumbnail_height = pme->mVideoHeight;
-
-    if (mNuberOfVFEOutputs == 1){
-       dim.main_img_format = pme->mDimension.prev_format;
-       dim.thumb_format = pme->mDimension.prev_format;
-    } else {
-       dim.main_img_format = pme->mDimension.enc_format;
-       dim.thumb_format = pme->mDimension.enc_format;
-    }
-
-    mJpegMaxSize = dim.picture_width * dim.picture_height * 1.5;
-
-    ALOGE("Picture w = %d , h = %d, size = %d",dim.picture_width,dim.picture_height,mJpegMaxSize);
-     if (pme->mStreamLiveSnap){
+    if (pme->mStreamLiveSnap){
         ALOGE("%s:Deleting old Snapshot stream instance",__func__);
         QCameraStream_Snapshot::deleteInstance (pme->mStreamLiveSnap);
         pme->mStreamLiveSnap = NULL;
@@ -1622,22 +1581,18 @@
 
     if (!pme->mStreamLiveSnap) {
         ALOGE("%s: error - can't creat snapshot stream!", __func__);
+        cam_evt_buf_done(pme->mCameraId, recvd_frame);
         return ;
     }
     pme->mStreamLiveSnap->setModeLiveSnapshot(true);
     pme->mStreamLiveSnap->setHALCameraControl(pme);
-    pme->mStreamLiveSnap->initSnapshotBuffers(&dim,1);
-    ALOGE("Calling live shot");
 
-
-    ((QCameraStream_Snapshot*)(pme->mStreamLiveSnap))->takePictureLiveshot(frame,&dim,mJpegMaxSize);
-
-#else
-  if(MM_CAMERA_OK != cam_evt_buf_done(pme->mCameraId,frame )) {
-    ALOGE(" BUF DONE FAILED");
-  }
-#endif
-  ALOGE("%s: X", __func__);
+    ret = ((QCameraStream_Snapshot*)(pme->mStreamLiveSnap))->takePictureLiveshot(recvd_frame);
+    if (MM_CAMERA_OK != ret) {
+        ALOGE("%s: Error : returned from takePictureLiveshot",__func__);
+        return;
+    }
+    ALOGE("%s: X", __func__);
 
 }
 
@@ -1719,6 +1674,10 @@
       ret = UNKNOWN_ERROR;
       break;
     case QCAMERA_HAL_RECORDING_STARTED:
+      if(mStateLiveshot) {
+          ALOGE("takePicture : Duplicate TakePicture Call");
+          return ret;
+      }
       if (canTakeFullSizeLiveshot()) {
         ALOGD(" Calling takeFullSizeLiveshot");
         takeFullSizeLiveshot();
@@ -1743,7 +1702,7 @@
                                                     this);
         }
       }
-
+      mStateLiveshot = true;
       break;
     default:
         ret = UNKNOWN_ERROR;
diff --git a/camera/QCameraHWI.h b/camera/QCameraHWI.h
index 8f774c3..ebc18ef 100644
--- a/camera/QCameraHWI.h
+++ b/camera/QCameraHWI.h
@@ -741,6 +741,7 @@
     bool mAppRecordingHint;
     bool mStartRecording;
     bool mReleasedRecordingFrame;
+    bool mStateLiveshot;
     int mHdrMode;
     int mSnapshotFormat;
     int mZslInterval;
diff --git a/camera/QCameraHWI_Preview.cpp b/camera/QCameraHWI_Preview.cpp
index 4ec9220..b769055 100644
--- a/camera/QCameraHWI_Preview.cpp
+++ b/camera/QCameraHWI_Preview.cpp
@@ -254,12 +254,12 @@
         if (cnt < mHalCamCtrl->mPreviewMemory.buffer_count) {
             if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW, cnt, mCameraId,
                                                           CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
-                ALOGE("%s: sending data Msg Failed", __func__);
+                ALOGE("%s: unmapping Preview Buffer", __func__);
             }
             if(mHalCamCtrl->isZSLMode()) {
                 if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, cnt, mCameraId,
                                                           CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
-                    ALOGE("%s: Send socket msg to Unmap Failed", __func__);
+                    ALOGE("%s: unmapping Thumbnail Buffer for ZSL", __func__);
                 }
             }
         }
diff --git a/camera/QCameraHWI_Still.cpp b/camera/QCameraHWI_Still.cpp
old mode 100644
new mode 100755
index 1ff8142..3d6184e
--- a/camera/QCameraHWI_Still.cpp
+++ b/camera/QCameraHWI_Still.cpp
@@ -274,9 +274,10 @@
     camera_memory_t *encodedMem = NULL;
     camera_data_callback jpg_data_cb = NULL;
     bool fail_cb_flag = false;
+
     if (mHalCamCtrl->mHdrMode == HDR_MODE)
         hdrJpegCount++;
-    //Mutex::Autolock l(&snapshotLock);
+
     mStopCallbackLock.lock( );
     if(!mActive && !isLiveSnapshot()) {
         ALOGE("%s : Cancel Picture",__func__);
@@ -379,6 +380,12 @@
     }
     //reset jpeg_offset
     mJpegOffset = 0;
+
+    if(isLiveSnapshot() && mHalCamCtrl->mStateLiveshot) {
+        deInitBuffer();
+    }
+    mHalCamCtrl->mStateLiveshot = false;
+
     ALOGD("%s: X", __func__);
 }
 
@@ -941,17 +948,17 @@
     }
     else
     {
-      if (!isZSLMode() &&
+      if ((!isZSLMode() && !isLiveSnapshot()) &&
       ((mHalCamCtrl->getHDRMode() == HDR_MODE) || (mHalCamCtrl->isWDenoiseEnabled()))) {
         /*register main and thumbnail buffers at back-end for frameproc*/
         for (int i = 0; i < mHalCamCtrl->mSnapshotMemory.buffer_count; i++) {
           if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, mCameraId,
                                                         CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
-            ALOGE("%s: sending unmapping data Msg Failed", __func__);
+            ALOGE("%s: unmapping Main image Buffer for HDR and Denoise", __func__);
           }
           if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL, i, mCameraId,
                                                         CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
-            ALOGE("%s: sending unmapping data Msg Failed", __func__);
+            ALOGE("%s: unmapping Thumbnail buffer for HDR and Denoise", __func__);
           }
         }
       }
@@ -960,7 +967,7 @@
          for (int i = 0; i < mHalCamCtrl->mSnapshotMemory.buffer_count; i++) {
              if (NO_ERROR != mHalCamCtrl->sendUnMappingBuf(MSM_V4L2_EXT_CAPTURE_MODE_MAIN, i, mCameraId,
                  CAM_SOCK_MSG_TYPE_FD_UNMAPPING)) {
-             ALOGE("%s: sending unmapping data Msg Failed", __func__);
+                 ALOGE("%s: unmapping Main image Buffer for ZSL", __func__);
              }
          }
     }
@@ -1355,30 +1362,93 @@
 
 }
 
-/* This is called from vide stream object */
 status_t QCameraStream_Snapshot::
-takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame,
-                    cam_ctrl_dimension_t *dim,
-                    int frame_len)
+takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame)
 {
     status_t ret = NO_ERROR;
+    int mJpegMaxSize;
+    int mNuberOfVFEOutputs = 0;
     common_crop_t crop_info;
-    //common_crop_t crop;
-    uint32_t aspect_ratio;
     camera_notify_callback notifyCb;
     camera_data_callback dataCb;
+    cam_ctrl_dimension_t dim;
 
-    ALOGI("%s: E", __func__);
+    mStopCallbackLock.lock();
+    if (!mHalCamCtrl->mStateLiveshot) {
+        ALOGE("%s: Picture Cancelled", __func__);
+        mStopCallbackLock.unlock();
+        return FAILED_TRANSACTION;
+    }
+
+    ret = cam_config_get_parm(mHalCamCtrl->mCameraId,MM_CAMERA_PARM_VFE_OUTPUT_ENABLE,
+                       &mNuberOfVFEOutputs);
+    if (ret != MM_CAMERA_OK) {
+       ALOGE("get parm MM_CAMERA_PARM_VFE_OUTPUT_ENABLE  failed");
+       cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame);
+       mStopCallbackLock.unlock();
+       return FAILED_TRANSACTION;
+    }
+
+    mm_camera_ch_data_buf_t* frame =
+         (mm_camera_ch_data_buf_t *)malloc(sizeof(mm_camera_ch_data_buf_t));
+    if (frame == NULL) {
+        ALOGE("%s: Error allocating memory to save received_frame structure.", __func__);
+        cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame);
+        mStopCallbackLock.unlock();
+        return FAILED_TRANSACTION;
+    }
+    memcpy(frame, recvd_frame, sizeof(mm_camera_ch_data_buf_t));
+
+    if (mNuberOfVFEOutputs == 1){
+        ALOGE("<DEBUG> Liveshot buffer idx:%d",frame->def.idx);
+       frame->snapshot.main.frame = frame->def.frame;
+       frame->snapshot.main.idx = frame->def.idx;
+       frame->snapshot.thumbnail.frame = frame->def.frame;
+       frame->snapshot.thumbnail.idx = frame->def.idx;
+    } else {
+       ALOGE("<DEBUG> Liveshot buffer idx:%d",frame->video.video.idx);
+       frame->snapshot.main.frame = frame->video.video.frame;
+       frame->snapshot.main.idx = frame->video.video.idx;
+       frame->snapshot.thumbnail.frame = frame->video.video.frame;
+       frame->snapshot.thumbnail.idx = frame->video.video.idx;
+    }
+
+    memset(&dim, 0, sizeof(cam_ctrl_dimension_t));
+    ret = cam_config_get_parm(mHalCamCtrl->mCameraId, MM_CAMERA_PARM_DIMENSION, &dim);
+    if (MM_CAMERA_OK != ret) {
+        ALOGE("%s: X error - can't get dimension!", __func__);
+        cam_evt_buf_done(mHalCamCtrl->mCameraId, recvd_frame);
+        setModeLiveSnapshot(false);
+        mStopCallbackLock.unlock();
+        return FAILED_TRANSACTION;
+    }
+    dim.picture_width = dim.video_width;
+    dim.picture_height = dim.video_height;
+    dim.ui_thumbnail_width = dim.video_width;
+    dim.ui_thumbnail_height = dim.video_height;
+
+    if (mNuberOfVFEOutputs == 1){
+       dim.main_img_format = dim.prev_format;
+       dim.thumb_format = dim.prev_format;
+    } else {
+       dim.main_img_format = dim.enc_format;
+       dim.thumb_format = dim.enc_format;
+    }
+    initSnapshotBuffers(&dim,1);
 
     /* set flag to indicate we are doing livesnapshot */
     resetSnapshotCounters( );
     setModeLiveSnapshot(true);
 
-    if(!mHalCamCtrl->mShutterSoundPlayed) {
-        notifyShutter(&crop_info, true);
+    mStopCallbackLock.unlock();
+    if (mHalCamCtrl->mStateLiveshot) {
+        if(!mHalCamCtrl->mShutterSoundPlayed) {
+            notifyShutter(&crop_info, true);
+        }
+        notifyShutter(&crop_info, false);
+        mHalCamCtrl->mShutterSoundPlayed = false;
     }
-    notifyShutter(&crop_info, false);
-    mHalCamCtrl->mShutterSoundPlayed = false;
+    mStopCallbackLock.lock();
 
     // send upperlayer callback for raw image (data or notify, not both)
     if((mHalCamCtrl->mDataCb) && (mHalCamCtrl->mMsgEnabled & CAMERA_MSG_RAW_IMAGE)){
@@ -1392,17 +1462,17 @@
       notifyCb = NULL;
     }
 
-    ALOGI("%s:Passed picture size: %d X %d", __func__,
-         dim->picture_width, dim->picture_height);
-    ALOGI("%s:Passed thumbnail size: %d X %d", __func__,
-         dim->ui_thumbnail_width, dim->ui_thumbnail_height);
+    mPictureWidth = dim.picture_width;
+    mPictureHeight = dim.picture_height;
+    mThumbnailWidth = dim.ui_thumbnail_width;
+    mThumbnailHeight = dim.ui_thumbnail_height;
+    mPictureFormat = dim.main_img_format;
+    mThumbnailFormat = dim.thumb_format;
 
-    mPictureWidth = dim->picture_width;
-    mPictureHeight = dim->picture_height;
-    mThumbnailWidth = dim->ui_thumbnail_width;
-    mThumbnailHeight = dim->ui_thumbnail_height;
-    mPictureFormat = dim->main_img_format;
-    mThumbnailFormat = dim->thumb_format;
+    mJpegMaxSize = mPictureWidth * mPictureHeight * 1.5;
+
+    ALOGE("Liveshot res = %d X %d, Thumabnail = %d % %d",
+          mPictureWidth,mPictureHeight,mThumbnailWidth,mThumbnailHeight);
 
     memset(&crop_info, 0, sizeof(common_crop_t));
     crop_info.in1_w = mPictureWidth;
@@ -1418,32 +1488,22 @@
    }
     crop_info.out1_w = mHalCamCtrl->thumbnailWidth;
     crop_info.out1_h =  mHalCamCtrl->thumbnailHeight;
-    ret = encodeData(recvd_frame, &crop_info, frame_len, 0);
+    ret = encodeData(frame, &crop_info, mJpegMaxSize, 0);
     if (ret != NO_ERROR) {
         ALOGE("%s: Failure configuring JPEG encoder", __func__);
-
-        /* Failure encoding this frame. Just notify upper layer
-           about it.*/
-        #if 0
-        if(mHalCamCtrl->mDataCb &&
-            (mHalCamCtrl->mMsgEnabled & MEDIA_RECORDER_MSG_COMPRESSED_IMAGE)) {
-            /* get picture failed. Give jpeg callback with NULL data
-             * to the application to restore to preview mode
-             */
-        }
-        #endif
         setModeLiveSnapshot(false);
+        mStopCallbackLock.unlock();
+        ret = FAILED_TRANSACTION;
         goto end;
     }
-
-    if (dataCb) {
-      dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mSnapshotMemory.camera_memory[0],
+    mStopCallbackLock.unlock();
+    if (dataCb && mHalCamCtrl->mStateLiveshot) {
+      dataCb(CAMERA_MSG_RAW_IMAGE, mHalCamCtrl->mRecordingMemory.camera_memory[frame->video.video.idx],
                            1, NULL, mHalCamCtrl->mCallbackCookie);
     }
-    if (notifyCb) {
+    if (notifyCb && mHalCamCtrl->mStateLiveshot) {
       notifyCb(CAMERA_MSG_RAW_IMAGE_NOTIFY, 0, 0, mHalCamCtrl->mCallbackCookie);
     }
-
 end:
     ALOGI("%s: X", __func__);
     return ret;
@@ -2380,23 +2440,35 @@
     status_t ret = NO_ERROR;
 
     ALOGV("%s: E", __func__);
-    //Mutex::Autolock l(&snapshotLock);
+
+    if(isLiveSnapshot() && mHalCamCtrl->mStateLiveshot) {
+        if(getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) {
+            ALOGV("Destroy Liveshot Jpeg Instance");
+            omxJpegAbort();
+        }
+        mStopCallbackLock.lock();
+        deInitBuffer();
+        mHalCamCtrl->mStateLiveshot = false;
+        mStopCallbackLock.unlock();
+        return;
+    }
 
     if(!mActive) {
       ALOGV("%s: Not Active return now", __func__);
       return;
     }
     mActive = false;
-    Mutex::Autolock lock(mStopCallbackLock);
+    mStopCallbackLock.lock();
     if (getSnapshotState() != SNAPSHOT_STATE_UNINIT) {
         /* Stop polling for further frames */
         stopPolling();
 
         if(getSnapshotState() == SNAPSHOT_STATE_JPEG_ENCODING) {
+            mStopCallbackLock.unlock();
             ALOGV("Destroy Jpeg Instance");
             omxJpegAbort();
+            mStopCallbackLock.lock();
         }
-
         /* Depending upon current state, we'll need to allocate-deallocate-deinit*/
         deInitBuffer();
     }
@@ -2432,6 +2504,7 @@
     omxJpegClose();
 #endif
     mFullLiveshot = false;
+    mStopCallbackLock.unlock();
     ALOGV("%s: X", __func__);
 
 }
@@ -2442,9 +2515,6 @@
     ALOGV("%s: E", __func__);
     //Mutex::Autolock l(&snapshotLock);
 
-    if(isLiveSnapshot()) {
-        deInitBuffer();
-    }
     if(!mInit){
         ALOGE("%s : Stream not Initalized",__func__);
         return;
diff --git a/camera/QCameraStream.h b/camera/QCameraStream.h
index 736f3b2..6e4fd27 100644
--- a/camera/QCameraStream.h
+++ b/camera/QCameraStream.h
@@ -120,9 +120,7 @@
     virtual void *getLastQueuedFrame(void){return NULL;}
     virtual status_t takePictureZSL(void){return NO_ERROR;}
     virtual status_t takeLiveSnapshot(){return NO_ERROR;}
-    virtual status_t takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame,
-                                 cam_ctrl_dimension_t *dim,
-                                 int frame_len){return NO_ERROR;}
+    virtual status_t takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame){return NO_ERROR;}
 	virtual void setModeLiveSnapshot(bool){;}
     virtual status_t initSnapshotBuffers(cam_ctrl_dimension_t *dim,
                                  int num_of_buf){return NO_ERROR;}
@@ -272,9 +270,7 @@
     static void deleteInstance(QCameraStream *p);
 
     status_t takePictureZSL(void);
-    status_t takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame,
-                                 cam_ctrl_dimension_t *dim,
-                                 int frame_len);
+    status_t takePictureLiveshot(mm_camera_ch_data_buf_t* recvd_frame);
     status_t receiveRawPicture(mm_camera_ch_data_buf_t* recvd_frame);
     void receiveCompleteJpegPicture(jpeg_event_t event);
 	void jpegErrorHandler(jpeg_event_t event);