QCamera2: Add HAL support for flashlight
Implemented new API at HAL, allowing framework to turn on flash
devices independently of the sensor. The primary logic is
implemented as a singleton named QCameraFlash, which tracks
the state of any flash devices and interfaces with the driver
to turn them on or off.
Change-Id: I4452e65401140e28aa86184800857a423c9c4b09
diff --git a/camera/QCamera2/Android.mk b/camera/QCamera2/Android.mk
index 2f6149f..2ab12a9 100644
--- a/camera/QCamera2/Android.mk
+++ b/camera/QCamera2/Android.mk
@@ -21,6 +21,7 @@
LOCAL_SRC_FILES := \
util/QCameraCmdThread.cpp \
util/QCameraQueue.cpp \
+ util/QCameraFlash.cpp \
QCamera2Hal.cpp \
QCamera2Factory.cpp
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp
index 6086adb..00a65da 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.cpp
+++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp
@@ -44,6 +44,7 @@
#include <utils/Trace.h>
#include <ui/Fence.h>
#include <gralloc_priv.h>
+#include "util/QCameraFlash.h"
#include "QCamera3HWI.h"
#include "QCamera3Mem.h"
#include "QCamera3Channel.h"
@@ -481,6 +482,15 @@
ALOGE("Failure: Camera already opened");
return ALREADY_EXISTS;
}
+
+ rc = QCameraFlash::getInstance().reserveFlashForCamera(mCameraId);
+ if (rc < 0) {
+ ALOGE("%s: Failed to reserve flash for camera id: %d",
+ __func__,
+ mCameraId);
+ return UNKNOWN_ERROR;
+ }
+
mCameraHandle = camera_open(mCameraId);
if (!mCameraHandle) {
ALOGE("camera_open failed.");
@@ -532,6 +542,12 @@
}
#endif
+ if (QCameraFlash::getInstance().releaseFlashFromCamera(mCameraId) != 0) {
+ CDBG("%s: Failed to release flash for camera id: %d",
+ __func__,
+ mCameraId);
+ }
+
return rc;
}
@@ -6896,4 +6912,34 @@
return;
}
+
+/*===========================================================================
+* FUNCTION : getFlashInfo
+*
+* DESCRIPTION: Retrieve information about whether the device has a flash.
+*
+* PARAMETERS :
+* @cameraId : Camera id to query
+* @hasFlash : Boolean indicating whether there is a flash device
+* associated with given camera
+* @flashNode : If a flash device exists, this will be its device node.
+*
+* RETURN :
+* None
+*==========================================================================*/
+void QCamera3HardwareInterface::getFlashInfo(const int cameraId,
+ bool& hasFlash,
+ char (&flashNode)[QCAMERA_MAX_FILEPATH_LENGTH])
+{
+ cam_capability_t* camCapability = gCamCapability[cameraId];
+ if (NULL == camCapability) {
+ hasFlash = false;
+ flashNode[0] = '\0';
+ } else {
+ hasFlash = camCapability->flash_available;
+ strlcpy(flashNode,
+ (char*)camCapability->flash_dev_name,
+ QCAMERA_MAX_FILEPATH_LENGTH);
+ }
+}
}; //end namespace qcamera
diff --git a/camera/QCamera2/HAL3/QCamera3HWI.h b/camera/QCamera2/HAL3/QCamera3HWI.h
index c2ac724..44484b6 100644
--- a/camera/QCamera2/HAL3/QCamera3HWI.h
+++ b/camera/QCamera2/HAL3/QCamera3HWI.h
@@ -232,6 +232,10 @@
bool needOnlineRotation();
int getJpegQuality();
QCamera3Exif *getExifData();
+ static void getFlashInfo(const int cameraId,
+ bool& hasFlash,
+ char (&flashNode)[QCAMERA_MAX_FILEPATH_LENGTH]);
+
private:
camera3_device_t mCameraDevice;
uint8_t mCameraId;
diff --git a/camera/QCamera2/QCamera2Factory.cpp b/camera/QCamera2/QCamera2Factory.cpp
index cc0be30..e0584b8 100644
--- a/camera/QCamera2/QCamera2Factory.cpp
+++ b/camera/QCamera2/QCamera2Factory.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -38,6 +38,7 @@
#include "HAL/QCamera2HWI.h"
#include "HAL3/QCamera3HWI.h"
+#include "util/QCameraFlash.h"
#include "QCamera2Factory.h"
using namespace android;
@@ -186,6 +187,23 @@
}
/*===========================================================================
+ * FUNCTION : set_torch_mode
+ *
+ * DESCRIPTION: Attempt to turn on or off the torch mode of the flash unit.
+ *
+ * PARAMETERS :
+ * @camera_id : camera ID
+ * @on : Indicates whether to turn the flash on or off
+ *
+ * RETURN : 0 -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCamera2Factory::set_torch_mode(const char* camera_id, bool on)
+{
+ return gQCamera2Factory->setTorchMode(camera_id, on);
+}
+
+/*===========================================================================
* FUNCTION : getNumberOfCameras
*
* DESCRIPTION: query number of cameras detected
@@ -260,6 +278,12 @@
{
int rc = NO_ERROR;
mCallbacks = callbacks;
+
+ rc = QCameraFlash::getInstance().registerCallbacks(callbacks);
+ if (rc != 0) {
+ ALOGE("%s : Failed to register callbacks with flash module!", __func__);
+ }
+
return rc;
}
@@ -353,5 +377,69 @@
open: QCamera2Factory::camera_device_open,
};
+/*===========================================================================
+ * FUNCTION : setTorchMode
+ *
+ * DESCRIPTION: Attempt to turn on or off the torch mode of the flash unit.
+ *
+ * PARAMETERS :
+ * @camera_id : camera ID
+ * @on : Indicates whether to turn the flash on or off
+ *
+ * RETURN : 0 -- success
+ * none-zero failure code
+ *==========================================================================*/
+int QCamera2Factory::setTorchMode(const char* camera_id, bool on)
+{
+ int retVal(0);
+ long cameraIdLong(-1);
+ int cameraIdInt(-1);
+ char* endPointer = NULL;
+ errno = 0;
+ QCameraFlash& flash = QCameraFlash::getInstance();
+
+ cameraIdLong = strtol(camera_id, &endPointer, 10);
+
+ if ((errno == ERANGE) ||
+ (cameraIdLong < 0) ||
+ (cameraIdLong >= static_cast<long>(get_number_of_cameras())) ||
+ (endPointer == camera_id) ||
+ (*endPointer != '\0')) {
+ retVal = -EINVAL;
+ } else if (on) {
+ cameraIdInt = static_cast<int>(cameraIdLong);
+ retVal = flash.initFlash(cameraIdInt);
+
+ if (retVal == 0) {
+ retVal = flash.setFlashMode(cameraIdInt, on);
+ if ((retVal == 0) && (mCallbacks != NULL)) {
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ camera_id,
+ TORCH_MODE_STATUS_AVAILABLE_ON);
+ } else if (retVal == -EALREADY) {
+ // Flash is already on, so treat this as a success.
+ retVal = 0;
+ }
+ }
+ } else {
+ cameraIdInt = static_cast<int>(cameraIdLong);
+ retVal = flash.setFlashMode(cameraIdInt, on);
+
+ if (retVal == 0) {
+ retVal = flash.deinitFlash(cameraIdInt);
+ if ((retVal == 0) && (mCallbacks != NULL)) {
+ mCallbacks->torch_mode_status_change(mCallbacks,
+ camera_id,
+ TORCH_MODE_STATUS_AVAILABLE_OFF);
+ }
+ } else if (retVal == -EALREADY) {
+ // Flash is already off, so treat this as a success.
+ retVal = 0;
+ }
+ }
+
+ return retVal;
+}
+
}; // namespace qcamera
diff --git a/camera/QCamera2/QCamera2Factory.h b/camera/QCamera2/QCamera2Factory.h
index 14dd4ba..d7e3e3d 100644
--- a/camera/QCamera2/QCamera2Factory.h
+++ b/camera/QCamera2/QCamera2Factory.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -52,6 +52,7 @@
static int set_callbacks(const camera_module_callbacks_t *callbacks);
static int open_legacy(const struct hw_module_t* module,
const char* id, uint32_t halVersion, struct hw_device_t** device);
+ static int set_torch_mode(const char* camera_id, bool on);
private:
int getNumberOfCameras();
@@ -60,7 +61,7 @@
int cameraDeviceOpen(int camera_id, struct hw_device_t **hw_device);
static int camera_device_open(const struct hw_module_t *module, const char *id,
struct hw_device_t **hw_device);
-
+ int setTorchMode(const char* camera_id, bool on);
public:
static struct hw_module_methods_t mModuleMethods;
diff --git a/camera/QCamera2/QCamera2Hal.cpp b/camera/QCamera2/QCamera2Hal.cpp
index 6d36778..3fb360a 100644
--- a/camera/QCamera2/QCamera2Hal.cpp
+++ b/camera/QCamera2/QCamera2Hal.cpp
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2012-2015, The Linux Foundataion. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -32,7 +32,7 @@
static hw_module_t camera_common = {
tag: HARDWARE_MODULE_TAG,
- module_api_version: CAMERA_MODULE_API_VERSION_2_3,
+ module_api_version: CAMERA_MODULE_API_VERSION_2_4,
hal_api_version: HARDWARE_HAL_API_VERSION,
id: CAMERA_HARDWARE_MODULE_ID,
name: "QCamera Module",
@@ -49,6 +49,6 @@
set_callbacks: qcamera::QCamera2Factory::set_callbacks,
get_vendor_tag_ops: qcamera::QCamera3VendorTags::get_vendor_tag_ops,
open_legacy: qcamera::QCamera2Factory::open_legacy,
- set_torch_mode: NULL,
+ set_torch_mode: qcamera::QCamera2Factory::set_torch_mode,
reserved: {0}
};
diff --git a/camera/QCamera2/stack/common/cam_types.h b/camera/QCamera2/stack/common/cam_types.h
index 8770b1b..6794eea 100644
--- a/camera/QCamera2/stack/common/cam_types.h
+++ b/camera/QCamera2/stack/common/cam_types.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 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
@@ -119,6 +119,8 @@
#define MAX_INFLIGHT_REQUESTS 6
#define MIN_INFLIGHT_REQUESTS 3
+#define QCAMERA_MAX_FILEPATH_LENGTH 64
+
typedef enum {
CAM_HAL_V1 = 1,
CAM_HAL_V3 = 3
diff --git a/camera/QCamera2/util/QCameraFlash.cpp b/camera/QCamera2/util/QCameraFlash.cpp
new file mode 100644
index 0000000..7b0025c
--- /dev/null
+++ b/camera/QCamera2/util/QCameraFlash.cpp
@@ -0,0 +1,380 @@
+/* Copyright (c) 2015, The Linux Foundataion. 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 <stdio.h>
+#include <fcntl.h>
+#include <linux/media.h>
+#include <media/msmb_camera.h>
+#include <media/msm_cam_sensor.h>
+#include <utils/Log.h>
+
+#include "HAL3/QCamera3HWI.h"
+#include "QCameraFlash.h"
+
+#define STRING_LENGTH_OF_64_BIT_NUMBER 21
+
+volatile uint32_t gCamHal3LogLevel = 1;
+
+namespace qcamera {
+
+/*===========================================================================
+ * FUNCTION : getInstance
+ *
+ * DESCRIPTION: Get and create the QCameraFlash singleton.
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCameraFlash& QCameraFlash::getInstance()
+{
+ static QCameraFlash flashInstance;
+ return flashInstance;
+}
+
+/*===========================================================================
+ * FUNCTION : QCameraFlash
+ *
+ * DESCRIPTION: default constructor of QCameraFlash
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCameraFlash::QCameraFlash() : m_callbacks(NULL)
+{
+ memset(&m_flashOn, 0, sizeof(m_flashOn));
+ memset(&m_cameraOpen, 0, sizeof(m_cameraOpen));
+ for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) {
+ m_flashFds[pos] = -1;
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : ~QCameraFlash
+ *
+ * DESCRIPTION: deconstructor of QCameraFlash
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+QCameraFlash::~QCameraFlash()
+{
+ for (int pos = 0; pos < MM_CAMERA_MAX_NUM_SENSORS; pos++) {
+ if (m_flashFds[pos] >= 0)
+ {
+ setFlashMode(pos, false);
+ close(m_flashFds[pos]);
+ m_flashFds[pos] = -1;
+ }
+ }
+}
+
+/*===========================================================================
+ * FUNCTION : registerCallbacks
+ *
+ * DESCRIPTION: provide flash module with reference to callbacks to framework
+ *
+ * PARAMETERS : None
+ *
+ * RETURN : None
+ *==========================================================================*/
+int32_t QCameraFlash::registerCallbacks(
+ const camera_module_callbacks_t* callbacks)
+{
+ int32_t retVal = 0;
+ m_callbacks = callbacks;
+ return retVal;
+}
+
+/*===========================================================================
+ * FUNCTION : initFlash
+ *
+ * DESCRIPTION: Reserve and initialize the flash unit associated with a
+ * given camera id. This function is blocking until the
+ * operation completes or fails. Each flash unit can be "inited"
+ * by only one process at a time.
+ *
+ * PARAMETERS :
+ * @camera_id : Camera id of the flash.
+ *
+ * RETURN :
+ * 0 : success
+ * -EBUSY : The flash unit or the resource needed to turn on the
+ * the flash is busy, typically because the flash is
+ * already in use.
+ * -EINVAL : No flash present at camera_id.
+ *==========================================================================*/
+int32_t QCameraFlash::initFlash(const int camera_id)
+{
+ int32_t retVal = 0;
+ bool hasFlash = false;
+ char flashNode[QCAMERA_MAX_FILEPATH_LENGTH];
+ char flashPath[QCAMERA_MAX_FILEPATH_LENGTH] = "/dev/";
+
+ if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) {
+ ALOGE("%s: Invalid camera id: %d", __func__, camera_id);
+ return -EINVAL;
+ }
+
+ QCamera3HardwareInterface::getFlashInfo(camera_id,
+ hasFlash,
+ flashNode);
+
+ strlcat(flashPath,
+ flashNode,
+ sizeof(flashPath));
+
+ if (!hasFlash) {
+ ALOGE("%s: No flash available for camera id: %d",
+ __func__,
+ camera_id);
+ retVal = -EINVAL;
+ } else if (m_cameraOpen[camera_id]) {
+ ALOGE("%s: Camera in use for camera id: %d",
+ __func__,
+ camera_id);
+ retVal = -EBUSY;
+ } else if (m_flashFds[camera_id] >= 0) {
+ CDBG("%s: Flash is already inited for camera id: %d",
+ __func__,
+ camera_id);
+ } else {
+ m_flashFds[camera_id] = open(flashPath, O_RDWR | O_NONBLOCK);
+
+ if (m_flashFds[camera_id] < 0) {
+ ALOGE("%s: Unable to open node '%s'",
+ __func__,
+ flashPath);
+ retVal = -EBUSY;
+ } else {
+ struct msm_camera_led_cfg_t cfg;
+ cfg.cfgtype = MSM_CAMERA_LED_INIT;
+ retVal = ioctl(m_flashFds[camera_id],
+ VIDIOC_MSM_FLASH_LED_DATA_CFG,
+ &cfg);
+ if (retVal < 0) {
+ ALOGE("%s: Unable to init flash for camera id: %d",
+ __func__,
+ camera_id);
+ close(m_flashFds[camera_id]);
+ m_flashFds[camera_id] = -1;
+ }
+ }
+ }
+
+ return retVal;
+}
+
+/*===========================================================================
+ * FUNCTION : setFlashMode
+ *
+ * DESCRIPTION: Turn on or off the flash associated with a given handle.
+ * This function is blocking until the operation completes or
+ * fails.
+ *
+ * PARAMETERS :
+ * @camera_id : Camera id of the flash
+ * @on : Whether to turn flash on (true) or off (false)
+ *
+ * RETURN :
+ * 0 : success
+ * -EINVAL : No camera present at camera_id, or it is not inited.
+ * -EALREADY: Flash is already in requested state
+ *==========================================================================*/
+int32_t QCameraFlash::setFlashMode(const int camera_id, const bool mode)
+{
+ int32_t retVal = 0;
+ struct msm_camera_led_cfg_t cfg;
+
+ if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) {
+ ALOGE("%s: Invalid camera id: %d", __func__, camera_id);
+ retVal = -EINVAL;
+ } else if (mode == m_flashOn[camera_id]) {
+ CDBG("%s: flash %d is already in requested state: %d",
+ __func__,
+ camera_id,
+ mode);
+ retVal = -EALREADY;
+ } else if (m_flashFds[camera_id] < 0) {
+ ALOGE("%s: called for uninited flash: %d", __func__, camera_id);
+ retVal = -EINVAL;
+ } else {
+ cfg.cfgtype = mode ? MSM_CAMERA_LED_LOW : MSM_CAMERA_LED_OFF;
+ retVal = ioctl(m_flashFds[camera_id],
+ VIDIOC_MSM_FLASH_LED_DATA_CFG,
+ &cfg);
+ if (retVal == 0) {
+ m_flashOn[camera_id] = mode;
+ }
+ }
+ return retVal;
+}
+
+/*===========================================================================
+ * FUNCTION : deinitFlash
+ *
+ * DESCRIPTION: Release the flash unit associated with a given camera
+ * position. This function is blocking until the operation
+ * completes or fails.
+ *
+ * PARAMETERS :
+ * @camera_id : Camera id of the flash.
+ *
+ * RETURN :
+ * 0 : success
+ * -EINVAL : No camera present at camera_id or not inited.
+ *==========================================================================*/
+int32_t QCameraFlash::deinitFlash(const int camera_id)
+{
+ int32_t retVal = 0;
+
+ if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) {
+ ALOGE("%s: Invalid camera id: %d", __func__, camera_id);
+ retVal = -EINVAL;
+ } else if (m_flashFds[camera_id] < 0) {
+ ALOGE("%s: called deinitFlash for uninited flash", __func__);
+ retVal = -EINVAL;
+ } else {
+ setFlashMode(camera_id, false);
+
+ struct msm_camera_led_cfg_t cfg;
+ cfg.cfgtype = MSM_CAMERA_LED_RELEASE;
+ retVal = ioctl(m_flashFds[camera_id],
+ VIDIOC_MSM_FLASH_LED_DATA_CFG,
+ &cfg);
+ if (retVal < 0) {
+ ALOGE("%s: Failed to release flash for camera id: %d",
+ __func__,
+ camera_id);
+ }
+
+ close(m_flashFds[camera_id]);
+ m_flashFds[camera_id] = -1;
+ }
+
+ return retVal;
+}
+
+/*===========================================================================
+ * FUNCTION : reserveFlashForCamera
+ *
+ * DESCRIPTION: Give control of the flash to the camera, and notify
+ * framework that the flash has become unavailable.
+ *
+ * PARAMETERS :
+ * @camera_id : Camera id of the flash.
+ *
+ * RETURN :
+ * 0 : success
+ * -EINVAL : No camera present at camera_id or not inited.
+ * -ENOSYS : No callback available for torch_mode_status_change.
+ *==========================================================================*/
+int32_t QCameraFlash::reserveFlashForCamera(const int camera_id)
+{
+ int32_t retVal = 0;
+
+ if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) {
+ ALOGE("%s: Invalid camera id: %d", __func__, camera_id);
+ retVal = -EINVAL;
+ } else if (m_cameraOpen[camera_id]) {
+ CDBG("%s: Flash already reserved for camera id: %d",
+ __func__,
+ camera_id);
+ } else {
+ if (m_flashOn[camera_id]) {
+ setFlashMode(camera_id, false);
+ deinitFlash(camera_id);
+ }
+ m_cameraOpen[camera_id] = true;
+
+ if (m_callbacks == NULL ||
+ m_callbacks->torch_mode_status_change == NULL) {
+ ALOGE("%s: Callback is not defined!", __func__);
+ retVal = -ENOSYS;
+ } else {
+ char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER];
+ snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER,
+ "%d", camera_id);
+ m_callbacks->torch_mode_status_change(m_callbacks,
+ cameraIdStr,
+ TORCH_MODE_STATUS_NOT_AVAILABLE);
+ }
+ }
+
+ return retVal;
+}
+
+/*===========================================================================
+ * FUNCTION : releaseFlashFromCamera
+ *
+ * DESCRIPTION: Release control of the flash from the camera, and notify
+ * framework that the flash has become available.
+ *
+ * PARAMETERS :
+ * @camera_id : Camera id of the flash.
+ *
+ * RETURN :
+ * 0 : success
+ * -EINVAL : No camera present at camera_id or not inited.
+ * -ENOSYS : No callback available for torch_mode_status_change.
+ *==========================================================================*/
+int32_t QCameraFlash::releaseFlashFromCamera(const int camera_id)
+{
+ int32_t retVal = 0;
+
+ if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) {
+ ALOGE("%s: Invalid camera id: %d", __func__, camera_id);
+ retVal = -EINVAL;
+ } else if (!m_cameraOpen[camera_id]) {
+ CDBG("%s: Flash not reserved for camera id: %d",
+ __func__,
+ camera_id);
+ } else {
+ m_cameraOpen[camera_id] = false;
+
+ if (m_callbacks == NULL ||
+ m_callbacks->torch_mode_status_change == NULL) {
+ ALOGE("%s: Callback is not defined!", __func__);
+ retVal = -ENOSYS;
+ } else {
+ char cameraIdStr[STRING_LENGTH_OF_64_BIT_NUMBER];
+ snprintf(cameraIdStr, STRING_LENGTH_OF_64_BIT_NUMBER,
+ "%d", camera_id);
+ m_callbacks->torch_mode_status_change(m_callbacks,
+ cameraIdStr,
+ TORCH_MODE_STATUS_AVAILABLE_OFF);
+ }
+ }
+
+ return retVal;
+}
+
+}; // namespace qcamera
diff --git a/camera/QCamera2/util/QCameraFlash.h b/camera/QCamera2/util/QCameraFlash.h
new file mode 100644
index 0000000..f86b6ee
--- /dev/null
+++ b/camera/QCamera2/util/QCameraFlash.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2015, The Linux Foundataion. 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 __QCAMERA_FLASH_H__
+#define __QCAMERA_FLASH_H__
+
+#include <hardware/camera_common.h>
+
+extern "C" {
+#include <mm_camera_interface.h>
+}
+
+namespace qcamera {
+
+class QCameraFlash {
+public:
+ static QCameraFlash& getInstance();
+
+ int32_t registerCallbacks(const camera_module_callbacks_t* callbacks);
+ int32_t initFlash(const int camera_id);
+ int32_t setFlashMode(const int camera_id, const bool on);
+ int32_t deinitFlash(const int camera_id);
+ int32_t reserveFlashForCamera(const int camera_id);
+ int32_t releaseFlashFromCamera(const int camera_id);
+
+private:
+ QCameraFlash();
+ virtual ~QCameraFlash();
+ QCameraFlash(const QCameraFlash&);
+ QCameraFlash& operator=(const QCameraFlash&);
+
+ const camera_module_callbacks_t *m_callbacks;
+ int32_t m_flashFds[MM_CAMERA_MAX_NUM_SENSORS];
+ bool m_flashOn[MM_CAMERA_MAX_NUM_SENSORS];
+ bool m_cameraOpen[MM_CAMERA_MAX_NUM_SENSORS];
+};
+
+}; // namespace qcamera
+
+#endif /* __QCAMERA_FLASH_H__ */