Add HAL support for face detection feature.

Change-Id: Ic8a307db5e9a68ce696929e91f6442a9986c9830
diff --git a/QualcommCameraHardware.cpp b/QualcommCameraHardware.cpp
index 0c152be..40778ea 100644
--- a/QualcommCameraHardware.cpp
+++ b/QualcommCameraHardware.cpp
@@ -217,11 +217,11 @@
 static unsigned int previewSizeCount;
 
 board_property boardProperties[] = {
-        {TARGET_MSM7625, 0x00000fff, false, false},
-        {TARGET_MSM7627, 0x000006ff, false, false},
-        {TARGET_MSM7630, 0x00000fff, true, true},
-        {TARGET_MSM8660, 0x00001fff, true, true},
-        {TARGET_QSD8250, 0x00000fff, false, false}
+        {TARGET_MSM7625, 0x00000fff, false, false, false},
+        {TARGET_MSM7627, 0x000006ff, false, false, false},
+        {TARGET_MSM7630, 0x00000fff, true, true, false},
+        {TARGET_MSM8660, 0x00001fff, true, true, false},
+        {TARGET_QSD8250, 0x00000fff, false, false, false}
 };
 
 //static const camera_size_type* picture_sizes;
@@ -686,6 +686,11 @@
     { CameraParameters::SELECTABLE_ZONE_AF_FRAME_AVERAGE, AVERAGE }
 };
 
+static const str_map facedetection[] = {
+    { CameraParameters::FACE_DETECTION_OFF, FALSE },
+    { CameraParameters::FACE_DETECTION_ON, TRUE }
+};
+
 #define DONT_CARE_COORDINATE -1
 static const str_map touchafaec[] = {
     { CameraParameters::TOUCH_AF_AEC_OFF, FALSE },
@@ -702,11 +707,6 @@
     int bitMask;
 };
 
-
-/*
- * Values based on aec.c
- */
-
 #define CAMERA_HISTOGRAM_ENABLE 1
 #define CAMERA_HISTOGRAM_DISABLE 0
 #define HISTOGRAM_STATS_SIZE 257
@@ -715,6 +715,9 @@
 #define FOCUS_RECTANGLE_DX 100
 #define FOCUS_RECTANGLE_DY 100
 
+/*
+ * Values based on aec.c
+ */
 #define EXPOSURE_COMPENSATION_MAXIMUM_NUMERATOR 12
 #define EXPOSURE_COMPENSATION_MINIMUM_NUMERATOR -12
 #define EXPOSURE_COMPENSATION_DEFAULT_NUMERATOR 0
@@ -772,8 +775,11 @@
 static String8 scenedetect_values;
 static String8 preview_format_values;
 static String8 selectable_zone_af_values;
+static String8 facedetection_values;
+
 mm_camera_notify mCamNotify;
 mm_camera_ops mCamOps;
+
 static String8 create_sizes_str(const camera_size_type *sizes, int len) {
     String8 str;
     char buffer[32];
@@ -1188,6 +1194,18 @@
    return false;
 }
 
+bool QualcommCameraHardware::supportsFaceDetection() {
+   int prop = 0;
+   for(prop=0; prop<sizeof(boardProperties)/sizeof(board_property); prop++) {
+       if((mCurrentTarget == boardProperties[prop].target)
+          && boardProperties[prop].hasFaceDetect == true) {
+           return true;
+           break;
+       }
+   }
+   return false;
+}
+
 void QualcommCameraHardware::initDefaultParameters()
 {
     LOGI("initDefaultParameters E");
@@ -1285,6 +1303,10 @@
                 selectable_zone_af, sizeof(selectable_zone_af) / sizeof(str_map));
         }
 
+        if(mHasAutoFocusSupport && supportsFaceDetection()) {
+            facedetection_values = create_values_str(
+                facedetection, sizeof(facedetection) / sizeof(str_map));
+        }
         parameter_string_initialized = true;
     }
 
@@ -1479,6 +1501,10 @@
                     CameraParameters::SELECTABLE_ZONE_AF_AUTO);
     mParameters.set(CameraParameters::KEY_SUPPORTED_SELECTABLE_ZONE_AF,
                     selectable_zone_af_values);
+    mParameters.set(CameraParameters::KEY_FACE_DETECTION,
+                    CameraParameters::FACE_DETECTION_OFF);
+    mParameters.set(CameraParameters::KEY_SUPPORTED_FACE_DETECTION,
+                    facedetection_values);
     if (setParameters(mParameters) != NO_ERROR) {
         LOGE("Failed to set default parameters?!");
     }
@@ -3596,7 +3622,7 @@
     if ((rc = setContinuousAf(params)))  final_rc = rc;
     if ((rc = setSelectableZoneAf(params)))   final_rc = rc;
     if ((rc = setTouchAfAec(params)))   final_rc = rc;
-    if ((rc = setSceneMode(params)))  final_rc = rc;
+    if ((rc = setSceneMode(params)))    final_rc = rc;
     if ((rc = setContrast(params)))     final_rc = rc;
     if ((rc = setRecordSize(params)))  final_rc = rc;
     if ((rc = setSceneDetect(params)))  final_rc = rc;
@@ -3693,6 +3719,45 @@
 }
 
 
+status_t QualcommCameraHardware::runFaceDetection()
+{
+    bool ret = true;
+
+    const char *str = mParameters.get(CameraParameters::KEY_FACE_DETECTION);
+    if (str != NULL) {
+        int value = attr_lookup(facedetection,
+                sizeof(facedetection) / sizeof(str_map), str);
+
+        mMetaDataWaitLock.lock();
+        if (value == true) {
+            if(mMetaDataHeap != NULL)
+                mMetaDataHeap.clear();
+
+            mMetaDataHeap =
+                new AshmemPool((sizeof(int)*(MAX_ROI*4+1)),
+                        1,
+                        (sizeof(int)*(MAX_ROI*4+1)),
+                        "metadata");
+            if (!mMetaDataHeap->initialized()) {
+                LOGE("Meta Data Heap allocation failed ");
+                mMetaDataHeap.clear();
+                LOGE("runFaceDetection X: error initializing mMetaDataHeap");
+                mMetaDataWaitLock.unlock();
+                return UNKNOWN_ERROR;
+            }
+            mSendMetaData = true;
+        } else {
+            if(mMetaDataHeap != NULL)
+                mMetaDataHeap.clear();
+        }
+        mMetaDataWaitLock.unlock();
+        ret = native_set_parms(CAMERA_PARM_FD, sizeof(int8_t), (void *)&value);
+        return ret ? NO_ERROR : UNKNOWN_ERROR;
+    }
+    LOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
+    return BAD_VALUE;
+}
+
 status_t QualcommCameraHardware::sendCommand(int32_t command, int32_t arg1,
                                              int32_t arg2)
 {
@@ -3713,6 +3778,19 @@
                                        mSendData = true;
                                    mStatsWaitLock.unlock();
                                    return NO_ERROR;
+      case CAMERA_CMD_FACE_DETECTION_ON:
+                                   setFaceDetection("on");
+                                   return runFaceDetection();
+      case CAMERA_CMD_FACE_DETECTION_OFF:
+                                   setFaceDetection("off");
+                                   return runFaceDetection();
+      case CAMERA_CMD_SEND_META_DATA:
+                                   mMetaDataWaitLock.lock();
+                                   if(mFaceDetectOn == true) {
+                                       mSendMetaData = true;
+                                   }
+                                   mMetaDataWaitLock.unlock();
+                                   return NO_ERROR;
    }
     return BAD_VALUE;
 }
@@ -3951,13 +4029,14 @@
     void *pdata = mCallbackCookie;
     data_callback_timestamp rcb = mDataCallbackTimestamp;
     void *rdata = mCallbackCookie;
+    data_callback mcb = mDataCallback;
+    void *mdata = mCallbackCookie;
     mCallbackLock.unlock();
 
     // Find the offset within the heap of the current buffer.
     ssize_t offset_addr =
         (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
     ssize_t offset = offset_addr / mPreviewHeap->mAlignedBufferSize;
-
     common_crop_t *crop = (common_crop_t *) (frame->cropinfo);
 #ifdef DUMP_PREVIEW_FRAMES
     static int frameCnt = 0;
@@ -4067,9 +4146,40 @@
             mReleasedRecordingFrame = false;
         }
     }
+
+    if ( mCurrentTarget == TARGET_MSM8660 ) {
+        mMetaDataWaitLock.lock();
+        if (mFaceDetectOn == true && mSendMetaData == true) {
+            mSendMetaData = false;
+            fd_roi_t *fd = (fd_roi_t *)(frame->roi_info.info);
+            int faces_detected = fd->rect_num;
+            int max_faces_detected = MAX_ROI * 4;
+            int array[max_faces_detected + 1];
+
+            array[0] = faces_detected * 4;
+            for (int i = 1, j = 0;j < MAX_ROI; j++, i = i + 4) {
+                if (j < faces_detected) {
+                    array[i]   = fd->faces[j].x;
+                    array[i+1] = fd->faces[j].y;
+                    array[i+2] = fd->faces[j].dx;
+                    array[i+3] = fd->faces[j].dx;
+                } else {
+                    array[i]   = -1;
+                    array[i+1] = -1;
+                    array[i+2] = -1;
+                    array[i+3] = -1;
+                }
+            }
+            memcpy((uint32_t *)mMetaDataHeap->mHeap->base(), (uint32_t *)array, (sizeof(int)*(MAX_ROI*4+1)));
+            if  (mcb != NULL && (msgEnabled & CAMERA_MSG_META_DATA)) {
+                mcb(CAMERA_MSG_META_DATA, mMetaDataHeap->mBuffers[0], mdata);
+            }
+        }
+        mMetaDataWaitLock.unlock();
+    }
     mInPreviewCallback = false;
 
-//    LOGV("receivePreviewFrame X");
+//  LOGV("receivePreviewFrame X");
 }
 void QualcommCameraHardware::receiveCameraStats(camstats_type stype, camera_preview_histogram_info* histinfo)
 {
@@ -5430,6 +5540,23 @@
     return NO_ERROR;
 }
 
+status_t QualcommCameraHardware::setFaceDetection(const char *str)
+{
+    if (str != NULL) {
+        int value = attr_lookup(facedetection,
+                                    sizeof(facedetection) / sizeof(str_map), str);
+        if (value != NOT_FOUND) {
+            mMetaDataWaitLock.lock();
+            mFaceDetectOn = value;
+            mMetaDataWaitLock.unlock();
+            mParameters.set(CameraParameters::KEY_FACE_DETECTION, str);
+            return NO_ERROR;
+        }
+    }
+    LOGE("Invalid Face Detection value: %s", (str == NULL) ? "NULL" : str);
+    return BAD_VALUE;
+}
+
 status_t  QualcommCameraHardware::setISOValue(const CameraParameters& params) {
     int8_t temp_hjr;
     if(!mCfgControl.mm_camera_is_supported(CAMERA_PARM_ISO)) {
diff --git a/QualcommCameraHardware.h b/QualcommCameraHardware.h
index 55f4ce3..1efdde6 100644
--- a/QualcommCameraHardware.h
+++ b/QualcommCameraHardware.h
@@ -62,6 +62,7 @@
     unsigned int previewSizeMask;
     bool hasSceneDetect;
     bool hasSelectableZoneAf;
+    bool hasFaceDetect;
 };
 
 namespace android {
@@ -123,6 +124,9 @@
     status_t startPreviewInternal();
     status_t setHistogramOn();
     status_t setHistogramOff();
+    status_t runFaceDetection();
+    status_t setFaceDetection(const char *str);
+
     void stopPreviewInternal();
     friend void *auto_focus_thread(void *user);
     void runAutoFocus();
@@ -208,6 +212,7 @@
     sp<PmemPool> mDisplayHeap;
     sp<AshmemPool> mJpegHeap;
     sp<AshmemPool> mStatHeap;
+    sp<AshmemPool> mMetaDataHeap;
     sp<PmemPool> mRawSnapShotPmemHeap;
     sp<PmemPool> mPostViewHeap;
 
@@ -242,7 +247,10 @@
     Mutex mStatsWaitLock;
     Condition mStatsWait;
 
-
+    //For Face Detection
+    int mFaceDetectOn;
+    bool mSendMetaData;
+    Mutex mMetaDataWaitLock;
 
     bool mShutterPending;
     Mutex mShutterLock;
@@ -274,6 +282,7 @@
     void storeTargetType();
     bool supportsSceneDetection();
     bool supportsSelectableZoneAf();
+    bool supportsFaceDetection();
 
     void initDefaultParameters();
     void findSensorType();