Camera: Adding Raw Snapshot support

Support for capturing raw sensor data is enabled
diff --git a/QualcommCameraHardware.cpp b/QualcommCameraHardware.cpp
index a90b089..218c4ea 100755
--- a/QualcommCameraHardware.cpp
+++ b/QualcommCameraHardware.cpp
@@ -189,6 +189,10 @@
 }
 
 namespace android {
+
+static const int PICTURE_FORMAT_JPEG = 1;
+static const int PICTURE_FORMAT_RAW = 2;
+
 // from aeecamera.h
 static const str_map whitebalance[] = {
     { CameraParameters::WHITE_BALANCE_AUTO,            CAMERA_WB_AUTO },
@@ -507,6 +511,11 @@
 
 static SensorType * sensorType;
 
+static const str_map picture_formats[] = {
+        {CameraParameters::PIXEL_FORMAT_JPEG, PICTURE_FORMAT_JPEG},
+        {CameraParameters::PIXEL_FORMAT_RAW, PICTURE_FORMAT_RAW}
+};
+
 static bool parameter_string_initialized = false;
 static String8 preview_size_values;
 static String8 picture_size_values;
@@ -518,6 +527,8 @@
 static String8 focus_mode_values;
 static String8 iso_values;
 static String8 lensshade_values;
+static String8 picture_format_values;
+
 
 static String8 create_sizes_str(const camera_size_type *sizes, int len) {
     String8 str;
@@ -562,6 +573,7 @@
       mPreviewInitialized(false),
       mFrameThreadRunning(false),
       mSnapshotThreadRunning(false),
+      mSnapshotFormat(0),
       mReleasedRecordingFrame(false),
       mPreviewFrameSize(0),
       mRawSize(0),
@@ -613,6 +625,8 @@
             iso,sizeof(iso)/sizeof(str_map));
         lensshade_values = create_values_str(
             lensshade,sizeof(lensshade)/sizeof(str_map));
+        picture_format_values = create_values_str(
+            picture_formats, sizeof(picture_formats)/sizeof(str_map));
         parameter_string_initialized = true;
     }
 
@@ -658,6 +672,8 @@
                     whitebalance_values);
     mParameters.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
                     focus_mode_values);
+    mParameters.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+                    picture_format_values);
 
     if (mSensorInfo.flash_enabled) {
         mParameters.set(CameraParameters::KEY_FLASH_MODE,
@@ -670,6 +686,8 @@
     mParameters.set("zoom-supported", "true");
     mParameters.set("max-zoom", MAX_ZOOM_LEVEL);
     mParameters.set("zoom", 0);
+    mParameters.set(CameraParameters::KEY_PICTURE_FORMAT,
+                    CameraParameters::PIXEL_FORMAT_JPEG);
 
     mParameters.set(CameraParameters::KEY_ISO_MODE,
                     CameraParameters::ISO_AUTO);
@@ -866,6 +884,9 @@
     if (mJpegHeap != 0) {
         mJpegHeap->dump(fd, args);
     }
+    if(mRawSnapshotAshmemHeap != 0 ){
+        mRawSnapshotAshmemHeap->dump(fd, args);
+    }
     mParameters.dump(fd, args);
     return NO_ERROR;
 }
@@ -1018,6 +1039,26 @@
     return true;
 }
 
+static bool native_start_raw_snapshot(int camfd)
+{
+    int ret;
+    struct msm_ctrl_cmd ctrlCmd;
+
+    ctrlCmd.timeout_ms = 1000;
+    ctrlCmd.type = CAMERA_START_RAW_SNAPSHOT;
+    ctrlCmd.length = 0;
+    ctrlCmd.value = NULL;
+    ctrlCmd.resp_fd = camfd;
+
+    if ((ret = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0) {
+        LOGE("native_start_raw_snapshot: ioctl failed. ioctl return value "\
+             "is %d \n", ret);
+        return false;
+    }
+    return true;
+}
+
+
 static bool native_stop_snapshot (int camfd)
 {
     struct msm_ctrl_cmd ctrlCmd;
@@ -1303,6 +1344,51 @@
     LOGI("deinitPreview X");
 }
 
+bool QualcommCameraHardware::initRawSnapshot()
+{
+    LOGV("initRawSnapshot E");
+
+    //get width and height from Dimension Object
+    bool ret = native_set_parm(CAMERA_SET_PARM_DIMENSION,
+                               sizeof(cam_ctrl_dimension_t), &mDimension);
+
+    if(!ret){
+        LOGE("initRawSnapshot X: failed to set dimension");
+        return false;
+    }
+    int rawSnapshotSize = mDimension.raw_picture_height *
+                           mDimension.raw_picture_width;
+
+    LOGV("raw_snapshot_buffer_size = %d, raw_picture_height = %d, "\
+         "raw_picture_width = %d",
+          rawSnapshotSize, mDimension.raw_picture_height,
+          mDimension.raw_picture_width);
+
+    if (mRawSnapShotPmemHeap != NULL) {
+        LOGV("initRawSnapshot: clearing old mRawSnapShotPmemHeap.");
+        mRawSnapShotPmemHeap.clear();
+    }
+
+    //Pmem based pool for Camera Driver
+    mRawSnapShotPmemHeap = new PmemPool("/dev/pmem_adsp",
+                                    MemoryHeapBase::READ_ONLY,
+                                    mCameraControlFd,
+                                    MSM_PMEM_RAW_MAINIMG,
+                                    rawSnapshotSize,
+                                    1,
+                                    rawSnapshotSize,
+                                    "raw pmem snapshot camera");
+
+    if (!mRawSnapShotPmemHeap->initialized()) {
+        mRawSnapShotPmemHeap.clear();
+        LOGE("initRawSnapshot X: error initializing mRawSnapshotHeap");
+        return false;
+    }
+    LOGV("initRawSnapshot X");
+    return true;
+
+}
+
 bool QualcommCameraHardware::initRaw(bool initJpegHeap)
 {
     int rawWidth, rawHeight;
@@ -1409,6 +1495,15 @@
     return true;
 }
 
+
+void QualcommCameraHardware::deinitRawSnapshot()
+{
+    LOGV("deinitRawSnapshot E");
+    mRawSnapShotPmemHeap.clear();
+    mRawSnapshotAshmemHeap.clear();
+    LOGV("deinitRawSnapshot X");
+}
+
 void QualcommCameraHardware::deinitRaw()
 {
     LOGV("deinitRaw E");
@@ -1450,6 +1545,7 @@
 
     LINK_jpeg_encoder_join();
     deinitRaw();
+    deinitRawSnapshot();
 
     ctrlCmd.timeout_ms = 5000;
     ctrlCmd.length = 0;
@@ -1740,10 +1836,20 @@
 void QualcommCameraHardware::runSnapshotThread(void *data)
 {
     LOGV("runSnapshotThread E");
-    if (native_start_snapshot(mCameraControlFd))
-        receiveRawPicture();
-    else
-        LOGE("main: native_start_snapshot failed!");
+    if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
+        if (native_start_snapshot(mCameraControlFd))
+            receiveRawPicture();
+        else
+            LOGE("main: native_start_snapshot failed!");
+    } else if(mSnapshotFormat == PICTURE_FORMAT_RAW){
+        if(native_start_raw_snapshot(mCameraControlFd)){
+           receiveRawSnapshot();
+        } else {
+           LOGE("main: native_start_raw_snapshot failed!");
+        }
+    }
+
+    mSnapshotFormat = 0;
 
     mSnapshotThreadWaitLock.lock();
     mSnapshotThreadRunning = false;
@@ -1778,17 +1884,35 @@
         LOGV("takePicture: old snapshot thread completed.");
     }
 
-    if(!native_prepare_snapshot(mCameraControlFd)) {
-        mSnapshotThreadWaitLock.unlock();
-        return UNKNOWN_ERROR;
+    //mSnapshotFormat is protected by mSnapshotThreadWaitLock
+    if(mParameters.getPictureFormat() != 0 &&
+            !strcmp(mParameters.getPictureFormat(),
+                    CameraParameters::PIXEL_FORMAT_RAW))
+        mSnapshotFormat = PICTURE_FORMAT_RAW;
+    else
+        mSnapshotFormat = PICTURE_FORMAT_JPEG;
+
+    if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
+        if(!native_prepare_snapshot(mCameraControlFd)) {
+            mSnapshotThreadWaitLock.unlock();
+            return UNKNOWN_ERROR;
+        }
     }
 
     stopPreviewInternal();
 
-    if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
-        LOGE("initRaw failed.  Not taking picture.");
-        mSnapshotThreadWaitLock.unlock();
-        return UNKNOWN_ERROR;
+    if(mSnapshotFormat == PICTURE_FORMAT_JPEG){
+        if (!initRaw(mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE))) {
+            LOGE("initRaw failed.  Not taking picture.");
+            mSnapshotThreadWaitLock.unlock();
+            return UNKNOWN_ERROR;
+        }
+    } else if(mSnapshotFormat == PICTURE_FORMAT_RAW ){
+        if(!initRawSnapshot()){
+            LOGE("initRawSnapshot failed. Not taking picture.");
+            mSnapshotThreadWaitLock.unlock();
+            return UNKNOWN_ERROR;
+        }
     }
 
     mShutterLock.lock();
@@ -1840,6 +1964,7 @@
     if ((rc = setBrightness(params)))   final_rc = rc;
     if ((rc = setLensshadeValue(params)))  final_rc = rc;
     if ((rc = setISOValue(params)))  final_rc = rc;
+    if ((rc = setPictureFormat(params))) final_rc = rc;
 
     LOGV("setParameters: X");
     return final_rc;
@@ -2105,6 +2230,54 @@
                cropped_width);
 }
 
+
+void QualcommCameraHardware::receiveRawSnapshot(){
+    LOGV("receiveRawSnapshot E");
+
+    Mutex::Autolock cbLock(&mCallbackLock);
+
+    notifyShutter(&mCrop);
+
+    if (mDataCallback && (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE)) {
+
+        if(native_get_picture(mCameraControlFd, &mCrop) == false) {
+            LOGE("receiveRawSnapshot X: native_get_picture failed!");
+            return;
+        }
+
+        //Create a Ashmem heap to copy data from PMem heap for application layer
+        if(mRawSnapshotAshmemHeap != NULL){
+            LOGV("receiveRawSnapshot: clearing old mRawSnapShotAshmemHeap.");
+            mRawSnapshotAshmemHeap.clear();
+        }
+        mRawSnapshotAshmemHeap = new AshmemPool(
+                                        mRawSnapShotPmemHeap->mBufferSize,
+                                        mRawSnapShotPmemHeap->mNumBuffers,
+                                        mRawSnapShotPmemHeap->mFrameSize,
+                                        "raw ashmem snapshot camera"
+                                        );
+
+        if(!mRawSnapshotAshmemHeap->initialized()){
+            LOGE("receiveRawSnapshot X: error initializing mRawSnapshotHeap");
+            deinitRawSnapshot();
+            return;
+        }
+
+        memcpy(mRawSnapshotAshmemHeap->mHeap->base(),
+                mRawSnapShotPmemHeap->mHeap->base(),
+                mRawSnapShotPmemHeap->mHeap->getSize());
+
+        mDataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mRawSnapshotAshmemHeap->mBuffers[0],
+                mCallbackCookie);
+
+    }
+
+    //cleanup
+    deinitRawSnapshot();
+
+    LOGV("receiveRawSnapshot X");
+}
+
 void QualcommCameraHardware::receiveRawPicture()
 {
     LOGV("receiveRawPicture: E");
@@ -2513,6 +2686,23 @@
     return NO_ERROR;
 }
 
+status_t QualcommCameraHardware::setPictureFormat(const CameraParameters& params)
+{
+    const char * str = params.get(CameraParameters::KEY_PICTURE_FORMAT);
+
+    if(str != NULL){
+        int32_t value = attr_lookup(picture_formats,
+                                    sizeof(picture_formats) / sizeof(str_map), str);
+        if(value != NOT_FOUND){
+            mParameters.set(CameraParameters::KEY_PICTURE_FORMAT, str);
+        } else {
+            LOGE("Invalid Picture Format value: %s", str);
+            return BAD_VALUE;
+        }
+    }
+    return NO_ERROR;
+}
+
 QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
                                          int frame_size,
                                          const char *name) :