QCamera2: Enables longshot mode

- Longshot mode is also triggered by every
  'takePicture()' call instead of the continuous
  processing that was done before.

TODO:
  - Instead of calling the shutter callback after
    re-process we need to call it after CAC is done.
    There is still no support for this V4L2 event.

CRs-Fixed: 514199
Change-Id: I6a8e33965883350028e7e8672a9dfa2c0a251726
diff --git a/QCamera2/HAL/QCamera2HWI.cpp b/QCamera2/HAL/QCamera2HWI.cpp
index 7017a75..7f7eefb 100644
--- a/QCamera2/HAL/QCamera2HWI.cpp
+++ b/QCamera2/HAL/QCamera2HWI.cpp
@@ -952,7 +952,8 @@
       mDumpFrmCnt(0),
       mDumpSkipCnt(0),
       mThermalLevel(QCAMERA_THERMAL_NO_ADJUSTMENT),
-      m_HDRSceneEnabled(false)
+      m_HDRSceneEnabled(false),
+      mLongshotEnabled(false)
 {
     mCameraDevice.common.tag = HARDWARE_DEVICE_TAG;
     mCameraDevice.common.version = HARDWARE_DEVICE_API_VERSION(1, 0);
@@ -960,7 +961,6 @@
     mCameraDevice.ops = &mCameraOps;
     mCameraDevice.priv = this;
 
-
     pthread_mutex_init(&m_lock, NULL);
     pthread_cond_init(&m_cond, NULL);
     memset(&m_apiResult, 0, sizeof(qcamera_api_result_t));
@@ -2117,6 +2117,37 @@
 }
 
 /*===========================================================================
+ * FUNCTION   : longShot
+ *
+ * DESCRIPTION: Queue one more ZSL frame
+ *              in the longshot pipe.
+ *
+ * PARAMETERS : none
+ *
+ * RETURN     : int32_t type of status
+ *              NO_ERROR  -- success
+ *              none-zero failure code
+ *==========================================================================*/
+int32_t QCamera2HardwareInterface::longShot()
+{
+    int32_t rc = NO_ERROR;
+    uint8_t numSnapshots = mParameters.getNumOfSnapshots();
+
+    QCameraPicChannel *pZSLChannel =
+            (QCameraPicChannel *)m_channels[QCAMERA_CH_TYPE_ZSL];
+    if (NULL != pZSLChannel) {
+        rc = pZSLChannel->takePicture(numSnapshots);
+    } else {
+        ALOGE(" %s : ZSL channel not initialized!", __func__);
+        rc = NO_INIT;
+        goto end;
+    }
+
+end:
+    return rc;
+}
+
+/*===========================================================================
  * FUNCTION   : cancelPicture
  *
  * DESCRIPTION: cancel picture impl
@@ -2295,6 +2326,22 @@
     int rc = NO_ERROR;
 
     switch (command) {
+    case CAMERA_CMD_LONGSHOT_ON:
+        // Longshot can only be enabled when image capture
+        // is not active.
+        if ( !m_stateMachine.isCaptureRunning() ) {
+            mLongshotEnabled = true;
+        } else {
+            rc = NO_INIT;
+        }
+        break;
+    case CAMERA_CMD_LONGSHOT_OFF:
+        if ( mLongshotEnabled && m_stateMachine.isCaptureRunning() ) {
+            cancelPicture();
+            processEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE, NULL);
+        }
+        mLongshotEnabled = false;
+        break;
     case CAMERA_CMD_HISTOGRAM_ON:
     case CAMERA_CMD_HISTOGRAM_OFF:
         rc = setHistogram(command == CAMERA_CMD_HISTOGRAM_ON? true : false);
@@ -3570,12 +3617,16 @@
 
     ALOGD("%s: After pproc config check, ret = %x", __func__, pp_config.feature_mask);
 
+    if ( mLongshotEnabled ) {
+        minStreamBufNum = getBufNumRequired(CAM_STREAM_TYPE_PREVIEW);
+    }
     rc = pChannel->addReprocStreamsFromSource(*this,
                                               pp_config,
                                               pInputChannel,
                                               minStreamBufNum,
                                               &gCamCapability[mCameraId]->padding_info,
-                                              mParameters);
+                                              mParameters,
+                                              mLongshotEnabled);
     if (rc != NO_ERROR) {
         delete pChannel;
         return NULL;
@@ -3853,14 +3904,8 @@
      cbArg.cb_type = QCAMERA_NOTIFY_CALLBACK;
      cbArg.msg_type = CAMERA_MSG_SHUTTER;
      cbArg.ext1 = 0;
-
-     if(!m_bShutterSoundPlayed){
-         cbArg.ext2 = true;
-         m_cbNotifier.notifyCallback(cbArg);
-     }
      cbArg.ext2 = false;
      m_cbNotifier.notifyCallback(cbArg);
-     m_bShutterSoundPlayed = false;
 }
 
 /*===========================================================================
diff --git a/QCamera2/HAL/QCamera2HWI.h b/QCamera2/HAL/QCamera2HWI.h
index 7560d96..6abf847 100644
--- a/QCamera2/HAL/QCamera2HWI.h
+++ b/QCamera2/HAL/QCamera2HWI.h
@@ -266,6 +266,7 @@
     int registerFaceImage(void *img_ptr,
                           cam_pp_offline_src_config_t *config,
                           int32_t &faceID);
+    int32_t longShot();
 
     int openCamera();
     int closeCamera();
@@ -357,6 +358,7 @@
     bool isNoDisplayMode() {return mParameters.isNoDisplayMode();};
     bool isZSLMode() {return mParameters.isZSLMode();};
     uint8_t numOfSnapshotsExpected() {return mParameters.getNumOfSnapshots();};
+    bool isLongshotEnabled() { return mLongshotEnabled; };
     uint8_t getBufNumRequired(cam_stream_type_t stream_type);
     bool needFDMetadata(qcamera_ch_type_enum_t channel_type);
 
@@ -463,6 +465,7 @@
     mm_jpeg_exif_params_t mExifParams;
     qcamera_thermal_level_enum_t mThermalLevel;
     bool m_HDRSceneEnabled;
+    bool mLongshotEnabled;
 };
 
 }; // namespace qcamera
diff --git a/QCamera2/HAL/QCamera2HWICallbacks.cpp b/QCamera2/HAL/QCamera2HWICallbacks.cpp
index 5f4711a..6d3311a 100644
--- a/QCamera2/HAL/QCamera2HWICallbacks.cpp
+++ b/QCamera2/HAL/QCamera2HWICallbacks.cpp
@@ -1518,6 +1518,7 @@
     QCameraCbNotifier *pme = (QCameraCbNotifier *)data;
     QCameraCmdThread *cmdThread = &pme->mProcTh;
     uint8_t isSnapshotActive = FALSE;
+    bool longShotEnabled = false;
     uint32_t numOfSnapshotExpected = 0;
     uint32_t numOfSnapshotRcvd = 0;
 
@@ -1539,6 +1540,7 @@
             {
                 isSnapshotActive = TRUE;
                 numOfSnapshotExpected = pme->mParent->numOfSnapshotsExpected();
+                longShotEnabled = pme->mParent->isLongshotEnabled();
                 numOfSnapshotRcvd = 0;
             }
             break;
@@ -1609,12 +1611,14 @@
                         case QCAMERA_DATA_SNAPSHOT_CALLBACK:
                             {
                                 if (TRUE == isSnapshotActive && pme->mDataCb ) {
-                                    numOfSnapshotRcvd++;
-                                    if (numOfSnapshotExpected > 0 &&
-                                        numOfSnapshotExpected == numOfSnapshotRcvd) {
-                                        // notify HWI that snapshot is done
-                                        pme->mParent->processSyncEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE,
-                                                                     NULL);
+                                    if (!longShotEnabled) {
+                                        numOfSnapshotRcvd++;
+                                        if (numOfSnapshotExpected > 0 &&
+                                            numOfSnapshotExpected == numOfSnapshotRcvd) {
+                                            // notify HWI that snapshot is done
+                                            pme->mParent->processSyncEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE,
+                                                                         NULL);
+                                        }
                                     }
                                     pme->mDataCb(cb->msg_type,
                                                  cb->data,
diff --git a/QCamera2/HAL/QCameraChannel.cpp b/QCamera2/HAL/QCameraChannel.cpp
index 28b4892..f08e319 100644
--- a/QCamera2/HAL/QCameraChannel.cpp
+++ b/QCamera2/HAL/QCameraChannel.cpp
@@ -696,7 +696,8 @@
                                                             QCameraChannel *pSrcChannel,
                                                             uint8_t minStreamBufNum,
                                                             cam_padding_info_t *paddingInfo,
-                                                            QCameraParameters &param)
+                                                            QCameraParameters &param,
+                                                            bool contStream)
 {
     int32_t rc = 0;
     QCameraStream *pStream = NULL;
@@ -737,8 +738,13 @@
             streamInfo->stream_type = CAM_STREAM_TYPE_OFFLINE_PROC;
             rc = pStream->getFormat(streamInfo->fmt);
             rc = pStream->getFrameDimension(streamInfo->dim);
-            streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
-            streamInfo->num_of_burst = minStreamBufNum;
+            if ( contStream ) {
+                streamInfo->streaming_mode = CAM_STREAMING_MODE_CONTINUOUS;
+                streamInfo->num_of_burst = 0;
+            } else {
+                streamInfo->streaming_mode = CAM_STREAMING_MODE_BURST;
+                streamInfo->num_of_burst = minStreamBufNum;
+            }
 
             streamInfo->reprocess_config.pp_type = CAM_ONLINE_REPROCESS_TYPE;
             streamInfo->reprocess_config.online.input_stream_id = pStream->getMyServerID();
diff --git a/QCamera2/HAL/QCameraChannel.h b/QCamera2/HAL/QCameraChannel.h
index baa283d..e6f60ef 100644
--- a/QCamera2/HAL/QCameraChannel.h
+++ b/QCamera2/HAL/QCameraChannel.h
@@ -118,7 +118,8 @@
                                        QCameraChannel *pSrcChannel,
                                        uint8_t minStreamBufNum,
                                        cam_padding_info_t *paddingInfo,
-                                       QCameraParameters &param);
+                                       QCameraParameters &param,
+                                       bool contStream);
     // online reprocess
     int32_t doReprocess(mm_camera_super_buf_t *frame);
     // offline reprocess
diff --git a/QCamera2/HAL/QCameraPostProc.cpp b/QCamera2/HAL/QCameraPostProc.cpp
index 30b3ded..182ccf3 100644
--- a/QCamera2/HAL/QCameraPostProc.cpp
+++ b/QCamera2/HAL/QCameraPostProc.cpp
@@ -471,8 +471,10 @@
     }
 
     if (m_parent->needReprocess()) {
-        //play shutter sound
-        m_parent->playShutter();
+        if ( !m_parent->isLongshotEnabled() ) {
+            //play shutter sound
+            m_parent->playShutter();
+        }
 
         ALOGD("%s: need reprocess", __func__);
         // enqueu to post proc input queue
@@ -675,6 +677,14 @@
         return processRawData(frame);
     }
 
+    if ( m_parent->isLongshotEnabled() ) {
+        // play shutter sound for longshot
+        // after reprocess is done
+        // TODO: Move this after CAC done event
+
+        m_parent->playShutter();
+    }
+
     qcamera_jpeg_data_t *jpeg_job =
         (qcamera_jpeg_data_t *)malloc(sizeof(qcamera_jpeg_data_t));
     if (jpeg_job == NULL) {
diff --git a/QCamera2/HAL/QCameraStateMachine.cpp b/QCamera2/HAL/QCameraStateMachine.cpp
index cc72381..07931c1 100644
--- a/QCamera2/HAL/QCameraStateMachine.cpp
+++ b/QCamera2/HAL/QCameraStateMachine.cpp
@@ -2555,6 +2555,10 @@
             rc = m_parent->sendCommand(cmd_payload->cmd,
                                        cmd_payload->arg1,
                                        cmd_payload->arg2);
+            if ( CAMERA_CMD_LONGSHOT_OFF == cmd_payload->cmd ) {
+                // move state to previewing state
+                m_state = QCAMERA_SM_STATE_PREVIEWING;
+            }
             result.status = rc;
             result.request_api = evt;
             result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
@@ -2636,11 +2640,25 @@
             m_parent->signalAPIResult(&result);
         }
         break;
+    case QCAMERA_SM_EVT_TAKE_PICTURE:
+        {
+            if ( m_parent->isLongshotEnabled() ) {
+               rc = m_parent->longShot();
+            } else {
+                ALOGE("%s: cannot handle evt(%d) in state(%d)", __func__, evt, m_state);
+                rc = INVALID_OPERATION;
+            }
+
+            result.status = rc;
+            result.request_api = evt;
+            result.result_type = QCAMERA_API_RESULT_TYPE_DEF;
+            m_parent->signalAPIResult(&result);
+        }
+        break;
+    case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
     case QCAMERA_SM_EVT_STOP_RECORDING:
     case QCAMERA_SM_EVT_START_PREVIEW:
     case QCAMERA_SM_EVT_START_NODISPLAY_PREVIEW:
-    case QCAMERA_SM_EVT_PREPARE_SNAPSHOT:
-    case QCAMERA_SM_EVT_TAKE_PICTURE:
     case QCAMERA_SM_EVT_SET_PREVIEW_WINDOW:
     case QCAMERA_SM_EVT_RELEASE:
         {
@@ -2756,4 +2774,26 @@
     }
 }
 
+/*===========================================================================
+ * FUNCTION   : isCaptureRunning
+ *
+ * DESCRIPTION: check if image capture is in process.
+ *
+ * PARAMETERS : None
+ *
+ * RETURN     : true -- capture running
+ *              false -- capture stopped
+ *==========================================================================*/
+bool QCameraStateMachine::isCaptureRunning()
+{
+    switch (m_state) {
+    case QCAMERA_SM_STATE_PIC_TAKING:
+    case QCAMERA_SM_STATE_VIDEO_PIC_TAKING:
+    case QCAMERA_SM_STATE_PREVIEW_PIC_TAKING:
+        return true;
+    default:
+        return false;
+    }
+}
+
 }; // namespace qcamera
diff --git a/QCamera2/HAL/QCameraStateMachine.h b/QCamera2/HAL/QCameraStateMachine.h
index 4e89346..e9beadc 100644
--- a/QCamera2/HAL/QCameraStateMachine.h
+++ b/QCamera2/HAL/QCameraStateMachine.h
@@ -160,6 +160,7 @@
     int32_t procEvt(qcamera_sm_evt_enum_t evt, void *evt_payload);
 
     bool isPreviewRunning(); // check if preview is running
+    bool isCaptureRunning(); // check if image capture is running
 
 private:
     typedef enum {