From bffc23d76e30bc092e40064e34d230a254b33317 Mon Sep 17 00:00:00 2001 From: cb Date: Thu, 9 Mar 2017 10:58:21 +0800 Subject: [PATCH] msm8956-common: Camera: HAL flashlight control [SQUASH] msm8956-common: QCamera2: Control longshot via parameters msm8956-common: QCamera2: Add HAL support for flashlight msm8956-common: QCamera2: Prevent fail if flashlight control not used msm8956-common: QCamera2: flashlight control via camera flash device msm8956-common: camera: Add HAL support for flashlight msm8956-common: camera: flashlight control via camera flash device --- BoardConfigCommon.mk | 5 + camera/QCamera2/Android.mk | 22 ++ camera/QCamera2/HAL/QCamera2HWI.cpp | 122 +++++++- camera/QCamera2/HAL/QCamera2HWI.h | 5 + camera/QCamera2/HAL/QCameraMuxer.cpp | 12 +- camera/QCamera2/HAL/QCameraMuxer.h | 4 +- camera/QCamera2/HAL3/QCamera3HWI.cpp | 21 ++ camera/QCamera2/QCamera2Factory.cpp | 107 ++++++- camera/QCamera2/QCamera2Factory.h | 5 +- camera/QCamera2/QCamera2Hal.cpp | 10 +- camera/QCamera2/util/QCameraFlash.cpp | 412 ++++++++++++++++++++++++++ camera/QCamera2/util/QCameraFlash.h | 68 +++++ rootdir/etc/init.qcom.rc | 1 + sepolicy/cameraserver.te | 2 + sepolicy/file_contexts | 3 + 15 files changed, 772 insertions(+), 27 deletions(-) create mode 100644 camera/QCamera2/util/QCameraFlash.cpp create mode 100644 camera/QCamera2/util/QCameraFlash.h create mode 100644 sepolicy/cameraserver.te diff --git a/BoardConfigCommon.mk b/BoardConfigCommon.mk index 7c4ca44..a5940bf 100644 --- a/BoardConfigCommon.mk +++ b/BoardConfigCommon.mk @@ -100,6 +100,11 @@ QCOM_BT_USE_SMD_TTY := true BOARD_QTI_CAMERA_32BIT_ONLY := true USE_DEVICE_SPECIFIC_CAMERA := true TARGET_TS_MAKEUP := true +TARGET_FLASHLIGHT_CONTROL := true +TARGET_FLASHLIGHT_CONTROL_ID := 0 +TARGET_FLASHLIGHT_CONTROL_PATH := /dev/v4l-subdev7 +TARGET_FLASHLIGHT_CURRENT_VALUE0 := 195 +TARGET_FLASHLIGHT_CURRENT_VALUE1 := 78 # Charger BOARD_CHARGER_ENABLE_SUSPEND := true diff --git a/camera/QCamera2/Android.mk b/camera/QCamera2/Android.mk index 562a015..1401119 100644 --- a/camera/QCamera2/Android.mk +++ b/camera/QCamera2/Android.mk @@ -11,6 +11,7 @@ LOCAL_SRC_FILES := \ util/QCameraCmdThread.cpp \ util/QCameraQueue.cpp \ util/QCameraBufferMaps.cpp \ + util/QCameraFlash.cpp \ QCamera2Hal.cpp \ QCamera2Factory.cpp @@ -58,6 +59,7 @@ LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/../mm-image-codec/qomx_core \ $(LOCAL_PATH)/util \ hardware/qcom/media-caf/msm8952/mm-core/inc \ + $(LOCAL_PATH)/HAL3 #HAL 1.0 Include paths LOCAL_C_INCLUDES += \ @@ -71,6 +73,26 @@ ifeq ($(TARGET_TS_MAKEUP),true) LOCAL_CFLAGS += -DTARGET_TS_MAKEUP LOCAL_C_INCLUDES += $(LOCAL_PATH)/HAL/tsMakeuplib/include endif + +ifeq ($(TARGET_FLASHLIGHT_CONTROL),true) +LOCAL_CFLAGS += -DFLASHLIGHT_CONTROL +ifdef TARGET_FLASHLIGHT_CONTROL_ID +LOCAL_CFLAGS += -DFLASHLIGHT_CONTROL_ID=$(TARGET_FLASHLIGHT_CONTROL_ID) +endif +ifdef TARGET_FLASHLIGHT_CONTROL_PATH +LOCAL_CFLAGS += -DFLASHLIGHT_CONTROL_PATH=\"$(TARGET_FLASHLIGHT_CONTROL_PATH)\" +endif +ifdef TARGET_FLASHLIGHT_CURRENT_VALUE0 +LOCAL_CFLAGS += -DFLASHLIGHT_CURRENT_VALUE0=$(TARGET_FLASHLIGHT_CURRENT_VALUE0) +endif +ifdef TARGET_FLASHLIGHT_CURRENT_VALUE1 +LOCAL_CFLAGS += -DFLASHLIGHT_CURRENT_VALUE1=$(TARGET_FLASHLIGHT_CURRENT_VALUE1) +endif +ifdef TARGET_FLASHLIGHT_CURRENT_VALUE2 +LOCAL_CFLAGS += -DFLASHLIGHT_CURRENT_VALUE2=$(TARGET_FLASHLIGHT_CURRENT_VALUE2) +endif +endif + ifneq (,$(filter msm8974 msm8916 msm8226 msm8610 msm8916 apq8084 msm8084 msm8994 msm8992 msm8952 msm8996,$(TARGET_BOARD_PLATFORM))) LOCAL_CFLAGS += -DVENUS_PRESENT endif diff --git a/camera/QCamera2/HAL/QCamera2HWI.cpp b/camera/QCamera2/HAL/QCamera2HWI.cpp index 4ed8b27..632771d 100644 --- a/camera/QCamera2/HAL/QCamera2HWI.cpp +++ b/camera/QCamera2/HAL/QCamera2HWI.cpp @@ -36,6 +36,7 @@ #include #include #include +#include "util/QCameraFlash.h" #include #include #include @@ -1804,6 +1805,14 @@ int QCamera2HardwareInterface::openCamera() 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; + } + // alloc param buffer DeferWorkArgs args; memset(&args, 0, sizeof(args)); @@ -2183,6 +2192,13 @@ int QCamera2HardwareInterface::closeCamera() free(mExifParams.debug_params); mExifParams.debug_params = NULL; } + + if (QCameraFlash::getInstance().releaseFlashFromCamera(mCameraId) != 0) { + CDBG("%s: Failed to release flash for camera id: %d", + __func__, + mCameraId); + } + ALOGI("[KPI Perf] %s: X PROFILE_CLOSE_CAMERA camera id %d, rc: %d", __func__, mCameraId, rc); @@ -5307,6 +5323,83 @@ int QCamera2HardwareInterface::sendCommand(int32_t command, CDBG_HIGH("%s: Histogram -> %s", __func__, mParameters.isHistogramEnabled() ? "Enabled" : "Disabled"); break; +#else + case CAMERA_CMD_LONGSHOT_ON: + arg1 = arg2 = 0; + // Longshot can only be enabled when image capture + // is not active. + if ( !m_stateMachine.isCaptureRunning() && m_stateMachine.isPreviewRunning() ) { + if (!mLongshotEnabled) { + CDBG_HIGH("%s: Longshot Enabled", __func__); + mLongshotEnabled = true; + pthread_mutex_lock(&m_parm_lock); + rc = mParameters.setLongshotEnable(mLongshotEnabled); + pthread_mutex_unlock(&m_parm_lock); + + // Due to recent buffer count optimizations + // ZSL might run with considerably less buffers + // when not in longshot mode. Preview needs to + // restart in this case. + if (isZSLMode()) { + QCameraChannel *pChannel = NULL; + QCameraStream *pSnapStream = NULL; + pChannel = m_channels[QCAMERA_CH_TYPE_ZSL]; + if (NULL != pChannel) { + QCameraStream *pStream = NULL; + for (uint32_t i = 0; i < pChannel->getNumOfStreams(); i++) { + pStream = pChannel->getStreamByIndex(i); + if (pStream != NULL) { + if (pStream->isTypeOf(CAM_STREAM_TYPE_SNAPSHOT)) { + pSnapStream = pStream; + break; + } + } + } + if (NULL != pSnapStream) { + uint8_t required = 0; + required = getBufNumRequired(CAM_STREAM_TYPE_SNAPSHOT); + if (pSnapStream->getBufferCount() < required) { + // We restart here, to reset the FPS and no + // of buffers as per the requirement of longshot usecase. + arg1 = QCAMERA_SM_EVT_RESTART_PERVIEW; + if (getRelatedCamSyncInfo()->sync_control == + CAM_SYNC_RELATED_SENSORS_ON) { + arg2 = QCAMERA_SM_EVT_DELAYED_RESTART; + } + } + } + } + } + // + mPrepSnapRun = false; + mCACDoneReceived = FALSE; + } + } else { + rc = NO_INIT; + } + break; + case CAMERA_CMD_LONGSHOT_OFF: + arg1 = arg2 = 0; + if ( mLongshotEnabled ) { + if ( m_stateMachine.isCaptureRunning() ) { + cancelPicture(); + processEvt(QCAMERA_SM_EVT_SNAPSHOT_DONE, NULL); + QCameraChannel *pZSLChannel = m_channels[QCAMERA_CH_TYPE_ZSL]; + if (isZSLMode() && (NULL != pZSLChannel) && mPrepSnapRun) { + mCameraHandle->ops->stop_zsl_snapshot( + mCameraHandle->camera_handle, + pZSLChannel->getMyHandle()); + } + } + mPrepSnapRun = false; + CDBG_HIGH("%s: Longshot Disabled", __func__); + mLongshotEnabled = false; + pthread_mutex_lock(&m_parm_lock); + rc = mParameters.setLongshotEnable(mLongshotEnabled); + pthread_mutex_unlock(&m_parm_lock); + mCACDoneReceived = FALSE; + } + break; #endif case CAMERA_CMD_START_FACE_DETECTION: case CAMERA_CMD_STOP_FACE_DETECTION: @@ -8368,12 +8461,33 @@ int QCamera2HardwareInterface::updateThermalLevel(void *thermal_level) *==========================================================================*/ int QCamera2HardwareInterface::updateParameters(const char *parms, bool &needRestart) { - int rc = NO_ERROR; + int final_rc = NO_ERROR; + int rc; - pthread_mutex_lock(&m_parm_lock); String8 str = String8(parms); QCameraParameters param(str); - rc = mParameters.updateParameters(param, needRestart); + +#ifdef VANILLA_HAL + const char *longshot = param.get(QCameraParameters::KEY_QC_LONG_SHOT); + int32_t arg1 = 0, arg2 = 0; + if (longshot != NULL) { + if (!strcmp(longshot, QCameraParameters::VALUE_ON)) + rc = sendCommand(CAMERA_CMD_LONGSHOT_ON, arg1, arg2); + else + rc = sendCommand(CAMERA_CMD_LONGSHOT_OFF, arg1, arg2); + if (rc == NO_ERROR) { + if (arg1 == QCAMERA_SM_EVT_RESTART_PERVIEW) + needRestart = true; + } else { + param.remove(QCameraParameters::KEY_QC_LONG_SHOT); + final_rc = rc; + } + } +#endif + + pthread_mutex_lock(&m_parm_lock); + if ((rc = mParameters.updateParameters(param, needRestart))) + final_rc = rc; // update stream based parameter settings for (int i = 0; i < QCAMERA_CH_TYPE_MAX; i++) { @@ -8383,7 +8497,7 @@ int QCamera2HardwareInterface::updateParameters(const char *parms, bool &needRes } pthread_mutex_unlock(&m_parm_lock); - return rc; + return final_rc; } /*=========================================================================== diff --git a/camera/QCamera2/HAL/QCamera2HWI.h b/camera/QCamera2/HAL/QCamera2HWI.h index e0e2b64..2a7c7e6 100644 --- a/camera/QCamera2/HAL/QCamera2HWI.h +++ b/camera/QCamera2/HAL/QCamera2HWI.h @@ -135,6 +135,11 @@ typedef struct { #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#ifdef VANILLA_HAL +#define CAMERA_CMD_LONGSHOT_ON 23 +#define CAMERA_CMD_LONGSHOT_OFF 24 +#endif + extern volatile uint32_t gCamHalLogLevel; typedef enum { diff --git a/camera/QCamera2/HAL/QCameraMuxer.cpp b/camera/QCamera2/HAL/QCameraMuxer.cpp index 4433ea3..5dc7f1d 100755 --- a/camera/QCamera2/HAL/QCameraMuxer.cpp +++ b/camera/QCamera2/HAL/QCameraMuxer.cpp @@ -40,6 +40,7 @@ #include "QCameraMuxer.h" #include "QCamera2HWI.h" +#include "QCamera3HWI.h" #include "QCameraPostProc.h" #include @@ -223,13 +224,12 @@ int QCameraMuxer::get_camera_info(int camera_id, struct camera_info *info) { int rc = NO_ERROR; CDBG_HIGH("%s: E", __func__); - cam_sync_type_t type; if ((camera_id < 0) || (camera_id >= gMuxer->getNumberOfCameras())) { ALOGE("%s : Camera id %d not found!", __func__, camera_id); return -ENODEV; } if(info) { - rc = gMuxer->getCameraInfo(camera_id, info, &type); + rc = gMuxer->getCameraInfo(camera_id, info); } CDBG_HIGH("%s: X, rc: %d", __func__, rc); return rc; @@ -1905,8 +1905,7 @@ int QCameraMuxer::getNumberOfCameras() * NO_ERROR -- success * none-zero failure code *==========================================================================*/ -int QCameraMuxer::getCameraInfo(int camera_id, - struct camera_info *info, cam_sync_type_t *p_cam_type) +int QCameraMuxer::getCameraInfo(int camera_id, struct camera_info *info) { int rc = NO_ERROR; CDBG_HIGH("%s: E, camera_id = %d", __func__, camera_id); @@ -1926,7 +1925,10 @@ int QCameraMuxer::getCameraInfo(int camera_id, uint32_t phy_id = m_pLogicalCamera[camera_id].pId[ m_pLogicalCamera[camera_id].nPrimaryPhyCamIndex]; - rc = QCamera2HardwareInterface::getCapabilities(phy_id, info, &cam_type); + // Call HAL3 getCamInfo to get the flash light info through static metatdata + // regardless of HAL version + rc = QCamera3HardwareInterface::getCamInfo(phy_id, info); + info->device_version = CAMERA_DEVICE_API_VERSION_1_0; // Hardcode the HAL to HAL1 CDBG_HIGH("%s: X", __func__); return rc; } diff --git a/camera/QCamera2/HAL/QCameraMuxer.h b/camera/QCamera2/HAL/QCameraMuxer.h index a6a4338..cb24004 100755 --- a/camera/QCamera2/HAL/QCameraMuxer.h +++ b/camera/QCamera2/HAL/QCameraMuxer.h @@ -32,6 +32,7 @@ #include #include #include "QCamera2HWI.h" +#include "QCamera3HWI.h" namespace qcamera { @@ -255,8 +256,7 @@ class QCameraMuxer { int setupLogicalCameras(); int cameraDeviceOpen(int camera_id, struct hw_device_t **hw_device); int getNumberOfCameras(); - int getCameraInfo(int camera_id, struct camera_info *info, - cam_sync_type_t *p_cam_type); + int getCameraInfo(int camera_id, struct camera_info *info); int32_t setCallbacks(const camera_module_callbacks_t *callbacks); int32_t setDataCallback(camera_data_callback data_cb); int32_t setMemoryCallback(camera_request_memory get_memory); diff --git a/camera/QCamera2/HAL3/QCamera3HWI.cpp b/camera/QCamera2/HAL3/QCamera3HWI.cpp index d035d5b..e8fddcd 100644 --- a/camera/QCamera2/HAL3/QCamera3HWI.cpp +++ b/camera/QCamera2/HAL3/QCamera3HWI.cpp @@ -42,6 +42,7 @@ #include #include #include +#include "util/QCameraFlash.h" #include "QCamera3HWI.h" #include "QCamera3Mem.h" #include "QCamera3Channel.h" @@ -599,11 +600,21 @@ int QCamera3HardwareInterface::openCamera() 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; + } + rc = camera_open((uint8_t)mCameraId, &mCameraHandle); if (rc) { ALOGE("camera_open failed. rc = %d, mCameraHandle = %p", rc, mCameraHandle); return rc; } + if (!mCameraHandle) { ALOGE("camera_open failed. mCameraHandle = %p", mCameraHandle); return -ENODEV; @@ -703,6 +714,11 @@ int QCamera3HardwareInterface::closeCamera() free(mExifParams.debug_params); mExifParams.debug_params = NULL; } + if (QCameraFlash::getInstance().releaseFlashFromCamera(mCameraId) != 0) { + CDBG("%s: Failed to release flash for camera id: %d", + __func__, + mCameraId); + } return rc; } @@ -6438,6 +6454,11 @@ int QCamera3HardwareInterface::getCamInfo(uint32_t cameraId, info->device_version = CAMERA_DEVICE_API_VERSION_3_2; info->static_camera_characteristics = gStaticMetadata[cameraId]; + //assume both cameras cannot operate independently. + info->resource_cost = 100; + info->conflicting_devices = NULL; + info->conflicting_devices_length = 0; + pthread_mutex_unlock(&gCamLock); return rc; diff --git a/camera/QCamera2/QCamera2Factory.cpp b/camera/QCamera2/QCamera2Factory.cpp index deee696..6e66c90 100644 --- a/camera/QCamera2/QCamera2Factory.cpp +++ b/camera/QCamera2/QCamera2Factory.cpp @@ -38,6 +38,7 @@ #include "HAL/QCamera2HWI.h" #include "HAL3/QCamera3HWI.h" +#include "util/QCameraFlash.h" #include "QCamera2Factory.h" #include "QCameraMuxer.h" @@ -252,6 +253,23 @@ int QCamera2Factory::open_legacy(const struct hw_module_t* module, return rc; } +/*=========================================================================== + * 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 * @@ -297,20 +315,13 @@ int QCamera2Factory::getCameraInfo(int camera_id, struct camera_info *info) return NO_INIT; } - if ( mHalDescriptors[camera_id].device_version == - CAMERA_DEVICE_API_VERSION_3_0 ) { - rc = QCamera3HardwareInterface::getCamInfo( - mHalDescriptors[camera_id].cameraId, info); - } else if (mHalDescriptors[camera_id].device_version == + // Need ANDROID_FLASH_INFO_AVAILABLE property for flashlight widget to + // work and so get the static data regardless of HAL version + rc = QCamera3HardwareInterface::getCamInfo( + mHalDescriptors[camera_id].cameraId, info); + if (mHalDescriptors[camera_id].device_version == CAMERA_DEVICE_API_VERSION_1_0) { - rc = QCamera2HardwareInterface::getCapabilities( - mHalDescriptors[camera_id].cameraId, info, &cam_type); - } else { - ALOGE("%s: Device version for camera id %d invalid %d", - __func__, - camera_id, - mHalDescriptors[camera_id].device_version); - return BAD_VALUE; + info->device_version = CAMERA_DEVICE_API_VERSION_1_0; } return rc; @@ -333,6 +344,12 @@ int QCamera2Factory::setCallbacks(const camera_module_callbacks_t *callbacks) { 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; } @@ -484,6 +501,70 @@ int QCamera2Factory::openLegacy( return rc; } +/*=========================================================================== + * 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(get_number_of_cameras())) || + (endPointer == camera_id) || + (*endPointer != '\0')) { + retVal = -EINVAL; + } else if (on) { + cameraIdInt = static_cast(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(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; +} + /*=========================================================================== * FUNCTION : isDualCamAvailable * diff --git a/camera/QCamera2/QCamera2Factory.h b/camera/QCamera2/QCamera2Factory.h index 49efe27..d7aa4e0 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 @@ class QCamera2Factory 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); bool isDualCamAvailable(int hal3Enabled); private: @@ -63,7 +64,7 @@ class QCamera2Factory struct hw_device_t **hw_device); static int openLegacy( int32_t cameraId, uint32_t halVersion, 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 c4601a9..5a58049 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,11 @@ static hw_module_t camera_common = { tag: HARDWARE_MODULE_TAG, +#ifdef FLASHLIGHT_CONTROL + module_api_version: CAMERA_MODULE_API_VERSION_2_4, +#else module_api_version: CAMERA_MODULE_API_VERSION_2_3, +#endif hal_api_version: HARDWARE_HAL_API_VERSION, id: CAMERA_HARDWARE_MODULE_ID, name: "QCamera Module", @@ -50,7 +54,11 @@ camera_module_t HAL_MODULE_INFO_SYM = { get_vendor_tag_ops: qcamera::QCamera3VendorTags::get_vendor_tag_ops, open_legacy: qcamera::QCamera2Factory::open_legacy, #ifndef USE_L_MR1 +#ifdef FLASHLIGHT_CONTROL + set_torch_mode: qcamera::QCamera2Factory::set_torch_mode, +#else set_torch_mode: NULL, +#endif init : NULL, #endif reserved: {0} diff --git a/camera/QCamera2/util/QCameraFlash.cpp b/camera/QCamera2/util/QCameraFlash.cpp new file mode 100644 index 0000000..c48e3f0 --- /dev/null +++ b/camera/QCamera2/util/QCameraFlash.cpp @@ -0,0 +1,412 @@ +/* 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 +#include +#include +#include +#include +#include + +#include "HAL3/QCamera3HWI.h" +#include "QCameraFlash.h" + +#define STRING_LENGTH_OF_64_BIT_NUMBER 21 + +#ifndef FLASHLIGHT_CONTROL_ID + #define FLASHLIGHT_CONTROL_ID -1 +#endif + +#ifndef FLASHLIGHT_CONTROL_PATH + #define FLASHLIGHT_CONTROL_PATH "" + #define FLASHLIGHT_CONTROL_ID -1 +#endif + +#ifndef FLASHLIGHT_CURRENT_VALUE0 + #define FLASHLIGHT_CURRENT_VALUE0 QCAMERA_TORCH_CURRENT_VALUE +#endif +#ifndef FLASHLIGHT_CURRENT_VALUE1 + #define FLASHLIGHT_CURRENT_VALUE1 QCAMERA_TORCH_CURRENT_VALUE +#endif +#ifndef FLASHLIGHT_CURRENT_VALUE2 + #define FLASHLIGHT_CURRENT_VALUE2 QCAMERA_TORCH_CURRENT_VALUE +#endif + +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; + + if (camera_id < 0 || camera_id >= MM_CAMERA_MAX_NUM_SENSORS) { + ALOGE("%s: Invalid camera id: %d", __func__, camera_id); + return -EINVAL; + } + + if (camera_id != FLASHLIGHT_CONTROL_ID) { + 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(FLASHLIGHT_CONTROL_PATH, O_RDWR | O_NONBLOCK); + + if (m_flashFds[camera_id] < 0) { + ALOGE("%s: Unable to open node '%s'", + __func__, + FLASHLIGHT_CONTROL_PATH); + retVal = -EBUSY; + } else { + struct msm_flash_cfg_data_t cfg; + struct msm_flash_init_info_t init_info; + memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); + memset(&init_info, 0, sizeof(struct msm_flash_init_info_t)); + init_info.flash_driver_type = FLASH_DRIVER_DEFAULT; + cfg.cfg.flash_init_info = &init_info; + cfg.cfg_type = CFG_FLASH_INIT; + retVal = ioctl(m_flashFds[camera_id], + VIDIOC_MSM_FLASH_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; + } + + /* wait for PMIC to init */ + usleep(5000); + } + } + + CDBG("%s: X, retVal = %d", __func__, retVal); + 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; + + 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 { + struct msm_flash_cfg_data_t cfg; + + memset(&cfg, 0, sizeof(struct msm_flash_cfg_data_t)); + cfg.flash_current[0] = FLASHLIGHT_CURRENT_VALUE0; + cfg.flash_current[1] = FLASHLIGHT_CURRENT_VALUE1; + cfg.flash_current[2] = FLASHLIGHT_CURRENT_VALUE2; + cfg.cfg_type = mode ? CFG_FLASH_LOW: CFG_FLASH_OFF; + + retVal = ioctl(m_flashFds[camera_id], + VIDIOC_MSM_FLASH_CFG, + &cfg); + if (retVal < 0) + ALOGE("%s: Unable to change flash mode to %d for camera id: %d", + __func__, mode, camera_id); + else + 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_flash_cfg_data_t cfg; + cfg.cfg_type = CFG_FLASH_RELEASE; + retVal = ioctl(m_flashFds[camera_id], + VIDIOC_MSM_FLASH_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 (camera_id != FLASHLIGHT_CONTROL_ID) { + CDBG("%s: Suppressing callback " + "because no flash exists for camera id: %d", + __func__, + camera_id); + } else 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 (camera_id != FLASHLIGHT_CONTROL_ID) { + CDBG("%s: Suppressing callback " + "because no flash exists for camera id: %d", + __func__, + camera_id); + } else 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..16cab03 --- /dev/null +++ b/camera/QCamera2/util/QCameraFlash.h @@ -0,0 +1,68 @@ +/* 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 + +extern "C" { +#include +} + +namespace qcamera { + +#define QCAMERA_TORCH_CURRENT_VALUE 200 + +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__ */ diff --git a/rootdir/etc/init.qcom.rc b/rootdir/etc/init.qcom.rc index 3bc56b4..3d039c8 100644 --- a/rootdir/etc/init.qcom.rc +++ b/rootdir/etc/init.qcom.rc @@ -208,6 +208,7 @@ on boot chmod 0666 /sys/class/leds/led:torch_0/brightness chmod 0666 /sys/class/leds/led:torch_1/brightness chmod 0666 /sys/class/leds/led:switch/brightness + chmod 0666 /sys/class/leds/flashlight/brightness chown system system /sys/class/leds/red/blink chown system system /sys/class/leds/green/blink chown system system /sys/class/leds/blue/blink diff --git a/sepolicy/cameraserver.te b/sepolicy/cameraserver.te new file mode 100644 index 0000000..4a7ac8c --- /dev/null +++ b/sepolicy/cameraserver.te @@ -0,0 +1,2 @@ +type sysfs_flashlight, sysfs_type, fs_type; +allow cameraserver sysfs_flashlight:file rw_file_perms; \ No newline at end of file diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts index 844b5ee..0687bae 100644 --- a/sepolicy/file_contexts +++ b/sepolicy/file_contexts @@ -9,3 +9,6 @@ # IR Blaster /dev/lirc[0-9]* u:object_r:lirc_device:s0 + +# flashlight +/sys/devices/soc.0/qpnp-flash-led-23/leds/flashlight/brightness u:object_r:sysfs_flashlight:s0