diff options
Diffstat (limited to 'services')
9 files changed, 745 insertions, 224 deletions
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp index 00a70eb..8e894cd 100644 --- a/services/camera/libcameraservice/CameraFlashlight.cpp +++ b/services/camera/libcameraservice/CameraFlashlight.cpp @@ -16,7 +16,7 @@ #define LOG_TAG "CameraFlashlight" #define ATRACE_TAG ATRACE_TAG_CAMERA -#define LOG_NDEBUG 0 +// #define LOG_NDEBUG 0 #include <utils/Log.h> #include <utils/Trace.h> @@ -32,16 +32,21 @@ namespace android { +///////////////////////////////////////////////////////////////////// +// CameraFlashlight implementation begins +// used by camera service to control flashflight. +///////////////////////////////////////////////////////////////////// CameraFlashlight::CameraFlashlight(CameraModule& cameraModule, const camera_module_callbacks_t& callbacks) : mCameraModule(&cameraModule), - mCallbacks(&callbacks) { + mCallbacks(&callbacks), + mFlashlightMapInitialized(false) { } CameraFlashlight::~CameraFlashlight() { } -status_t CameraFlashlight::createFlashlightControl(const String16& cameraId) { +status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) { ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__, cameraId.string()); if (mFlashControl != NULL) { @@ -52,7 +57,7 @@ status_t CameraFlashlight::createFlashlightControl(const String16& cameraId) { if (mCameraModule->getRawModule()->module_api_version >= CAMERA_MODULE_API_VERSION_2_4) { - mFlashControl = new FlashControl(*mCameraModule, *mCallbacks); + mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks); if (mFlashControl == NULL) { ALOGV("%s: cannot create flash control for module api v2.4+", __FUNCTION__); @@ -67,7 +72,7 @@ status_t CameraFlashlight::createFlashlightControl(const String16& cameraId) { res = mCameraModule->getCameraInfo( atoi(String8(cameraId).string()), &info); if (res) { - ALOGV("%s: failed to get camera info for camera %s", + ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__, cameraId.string()); return res; } @@ -83,18 +88,19 @@ status_t CameraFlashlight::createFlashlightControl(const String16& cameraId) { } mFlashControl = flashControl; - } - else { - // todo: implement for device api 1 - return INVALID_OPERATION; + } else { + mFlashControl = + new CameraHardwareInterfaceFlashControl(*mCameraModule, + *mCallbacks); } } return OK; } -status_t CameraFlashlight::setTorchMode(const String16& cameraId, bool enabled) { - if (!mCameraModule) { +status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) { + if (!mFlashlightMapInitialized) { + ALOGE("%s: findFlashUnits() must be called before this method."); return NO_INIT; } @@ -105,6 +111,10 @@ status_t CameraFlashlight::setTorchMode(const String16& cameraId, bool enabled) Mutex::Autolock l(mLock); if (mFlashControl == NULL) { + if (enabled == false) { + return OK; + } + res = createFlashlightControl(cameraId); if (res) { return res; @@ -130,88 +140,169 @@ status_t CameraFlashlight::setTorchMode(const String16& cameraId, bool enabled) return res; } -bool CameraFlashlight::hasFlashUnit(const String16& cameraId) { +status_t CameraFlashlight::findFlashUnits() { + Mutex::Autolock l(mLock); status_t res; + int32_t numCameras = mCameraModule->getNumberOfCameras(); - Mutex::Autolock l(mLock); + mHasFlashlightMap.clear(); + mFlashlightMapInitialized = false; - if (mFlashControl == NULL) { - res = createFlashlightControl(cameraId); + for (int32_t i = 0; i < numCameras; i++) { + bool hasFlash = false; + String8 id = String8::format("%d", i); + + res = createFlashlightControl(id); if (res) { - ALOGE("%s: failed to create flash control for %s ", - __FUNCTION__, cameraId.string()); - return false; + ALOGE("%s: failed to create flash control for %s", __FUNCTION__, + id.string()); + } else { + res = mFlashControl->hasFlashUnit(id, &hasFlash); + if (res == -EUSERS || res == -EBUSY) { + ALOGE("%s: failed to check if camera %s has a flash unit. Some " + "camera devices may be opened", __FUNCTION__, + id.string()); + return res; + } else if (res) { + ALOGE("%s: failed to check if camera %s has a flash unit. %s" + " (%d)", __FUNCTION__, id.string(), strerror(-res), + res); + } + + mFlashControl.clear(); } + mHasFlashlightMap.add(id, hasFlash); } - bool flashUnit = false; + mFlashlightMapInitialized = true; + return OK; +} - // if flash control already exists, querying if a camera device has a flash - // unit may fail if it's module v1 - res = mFlashControl->hasFlashUnit(cameraId, &flashUnit); - if (res == BAD_INDEX) { - // need to close the flash control before query. - mFlashControl.clear(); - res = createFlashlightControl(cameraId); - if (res) { - ALOGE("%s: failed to create flash control for %s ", __FUNCTION__, - cameraId.string()); - return false; - } - res = mFlashControl->hasFlashUnit(cameraId, &flashUnit); - if (res) { - flashUnit = false; - } +bool CameraFlashlight::hasFlashUnit(const String8& cameraId) { + status_t res; + + Mutex::Autolock l(mLock); + return hasFlashUnitLocked(cameraId); +} + +bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) { + if (!mFlashlightMapInitialized) { + ALOGE("%s: findFlashUnits() must be called before this method."); + return false; + } + + ssize_t index = mHasFlashlightMap.indexOfKey(cameraId); + if (index == NAME_NOT_FOUND) { + ALOGE("%s: camera %s not present when findFlashUnits() was called", + __FUNCTION__, cameraId.string()); + return false; } - return flashUnit; + return mHasFlashlightMap.valueAt(index); } -status_t CameraFlashlight::prepareDeviceOpen() { +status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) { ALOGV("%s: prepare for device open", __FUNCTION__); Mutex::Autolock l(mLock); + if (!mFlashlightMapInitialized) { + ALOGE("%s: findFlashUnits() must be called before this method."); + return NO_INIT; + } - if (mCameraModule && mCameraModule->getRawModule()->module_api_version < + if (mCameraModule->getRawModule()->module_api_version < CAMERA_MODULE_API_VERSION_2_4) { // framework is going to open a camera device, all flash light control // should be closed for backward compatible support. - if (mFlashControl != NULL) { - mFlashControl.clear(); + mFlashControl.clear(); + + if (mOpenedCameraIds.size() == 0) { + // notify torch unavailable for all cameras with a flash + int numCameras = mCameraModule->getNumberOfCameras(); + for (int i = 0; i < numCameras; i++) { + if (hasFlashUnitLocked(String8::format("%d", i))) { + mCallbacks->torch_mode_status_change(mCallbacks, + String8::format("%d", i).string(), + TORCH_MODE_STATUS_NOT_AVAILABLE); + } + } } + + // close flash control that may be opened by calling hasFlashUnitLocked. + mFlashControl.clear(); + } + + if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) { + mOpenedCameraIds.add(cameraId); } return OK; } +status_t CameraFlashlight::deviceClosed(const String8& cameraId) { + ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string()); -FlashControlBase::~FlashControlBase() { + Mutex::Autolock l(mLock); + if (!mFlashlightMapInitialized) { + ALOGE("%s: findFlashUnits() must be called before this method."); + return NO_INIT; + } + + ssize_t index = mOpenedCameraIds.indexOf(cameraId); + if (index == NAME_NOT_FOUND) { + ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__, + cameraId.string()); + } else { + mOpenedCameraIds.removeAt(index); + } + + // Cannot do anything until all cameras are closed. + if (mOpenedCameraIds.size() != 0) + return OK; + + if (mCameraModule->getRawModule()->module_api_version < + CAMERA_MODULE_API_VERSION_2_4) { + // notify torch available for all cameras with a flash + int numCameras = mCameraModule->getNumberOfCameras(); + for (int i = 0; i < numCameras; i++) { + if (hasFlashUnitLocked(String8::format("%d", i))) { + mCallbacks->torch_mode_status_change(mCallbacks, + String8::format("%d", i).string(), + TORCH_MODE_STATUS_AVAILABLE_OFF); + } + } + } + + return OK; } +// CameraFlashlight implementation ends + +FlashControlBase::~FlashControlBase() { +} -FlashControl::FlashControl(CameraModule& cameraModule, +///////////////////////////////////////////////////////////////////// +// ModuleFlashControl implementation begins +// Flash control for camera module v2.4 and above. +///////////////////////////////////////////////////////////////////// +ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule, const camera_module_callbacks_t& callbacks) : mCameraModule(&cameraModule) { } -FlashControl::~FlashControl() { +ModuleFlashControl::~ModuleFlashControl() { } -status_t FlashControl::hasFlashUnit(const String16& cameraId, bool *hasFlash) { +status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) { if (!hasFlash) { return BAD_VALUE; } *hasFlash = false; - Mutex::Autolock l(mLock); - if (!mCameraModule) { - return NO_INIT; - } - camera_info info; - status_t res = mCameraModule->getCameraInfo(atoi(String8(cameraId).string()), + status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info); if (res != 0) { return res; @@ -228,33 +319,31 @@ status_t FlashControl::hasFlashUnit(const String16& cameraId, bool *hasFlash) { return OK; } -status_t FlashControl::setTorchMode(const String16& cameraId, bool enabled) { +status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) { ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__, cameraId.string(), enabled); Mutex::Autolock l(mLock); - if (!mCameraModule) { - return NO_INIT; - } - - return mCameraModule->setTorchMode(String8(cameraId).string(), enabled); + return mCameraModule->setTorchMode(cameraId.string(), enabled); } +// ModuleFlashControl implementation ends +///////////////////////////////////////////////////////////////////// +// CameraDeviceClientFlashControl implementation begins +// Flash control for camera module <= v2.3 and camera HAL v2-v3 +///////////////////////////////////////////////////////////////////// CameraDeviceClientFlashControl::CameraDeviceClientFlashControl( CameraModule& cameraModule, const camera_module_callbacks_t& callbacks) : mCameraModule(&cameraModule), mCallbacks(&callbacks), mTorchEnabled(false), - mMetadata(NULL) { + mMetadata(NULL), + mStreaming(false) { } CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() { - if (mDevice != NULL) { - mDevice->flush(); - mDevice->deleteStream(mStreamId); - mDevice.clear(); - } + disconnectCameraDevice(); if (mMetadata) { delete mMetadata; } @@ -269,13 +358,13 @@ CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() { ALOGV("%s: notify the framework that torch was turned off", __FUNCTION__); mCallbacks->torch_mode_status_change(mCallbacks, - String8(mCameraId).string(), TORCH_MODE_STATUS_OFF); + mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF); } } } -status_t CameraDeviceClientFlashControl::initializeSurface(int32_t width, - int32_t height) { +status_t CameraDeviceClientFlashControl::initializeSurface( + sp<CameraDeviceBase> &device, int32_t width, int32_t height) { status_t res; BufferQueue::createBufferQueue(&mProducer, &mConsumer); @@ -295,27 +384,16 @@ status_t CameraDeviceClientFlashControl::initializeSurface(int32_t width, return res; } - bool useAsync = false; - int32_t consumerUsage; - res = mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage); - if (res) { - return res; - } - - if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) { - useAsync = true; - } - - mAnw = new Surface(mProducer, useAsync); + mAnw = new Surface(mProducer, /*useAsync*/ true); if (mAnw == NULL) { return NO_MEMORY; } - res = mDevice->createStream(mAnw, width, height, format, &mStreamId); + res = device->createStream(mAnw, width, height, format, &mStreamId); if (res) { return res; } - res = mDevice->configureStreams(); + res = device->configureStreams(); if (res) { return res; } @@ -342,7 +420,21 @@ status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize( int32_t ww = streamConfigs.data.i32[i + 1]; int32_t hh = streamConfigs.data.i32[i + 2]; - if (w* h > ww * hh) { + if (w * h > ww * hh) { + w = ww; + h = hh; + } + } + } + + // if stream configuration is not found, try available processed sizes. + if (streamConfigs.count == 0) { + camera_metadata_entry availableProcessedSizes = + metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES); + for (size_t i = 0; i < availableProcessedSizes.count; i += 2) { + int32_t ww = availableProcessedSizes.data.i32[i]; + int32_t hh = availableProcessedSizes.data.i32[i + 1]; + if (w * h > ww * hh) { w = ww; h = hh; } @@ -360,24 +452,24 @@ status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize( } status_t CameraDeviceClientFlashControl::connectCameraDevice( - const String16& cameraId) { - String8 id = String8(cameraId); + const String8& cameraId) { camera_info info; - status_t res = mCameraModule->getCameraInfo(atoi(id.string()), &info); + status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info); if (res != 0) { ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__, - mCameraId.string()); + cameraId.string()); return res; } - mDevice = CameraDeviceFactory::createDevice(atoi(id.string())); - if (mDevice == NULL) { + sp<CameraDeviceBase> device = + CameraDeviceFactory::createDevice(atoi(cameraId.string())); + if (device == NULL) { return NO_MEMORY; } - res = mDevice->initialize(mCameraModule); + res = device->initialize(mCameraModule); if (res) { - goto fail; + return res; } int32_t width, height; @@ -385,22 +477,30 @@ status_t CameraDeviceClientFlashControl::connectCameraDevice( if (res) { return res; } - res = initializeSurface(width, height); + res = initializeSurface(device, width, height); if (res) { - goto fail; + return res; } mCameraId = cameraId; + mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1); + mDevice = device; return OK; +} -fail: - mDevice.clear(); - return res; +status_t CameraDeviceClientFlashControl::disconnectCameraDevice() { + if (mDevice != NULL) { + mDevice->disconnect(); + mDevice.clear(); + } + + return OK; } -status_t CameraDeviceClientFlashControl::hasFlashUnit(const String16& cameraId, + +status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) { ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__, cameraId.string()); @@ -411,19 +511,14 @@ status_t CameraDeviceClientFlashControl::hasFlashUnit(const String16& cameraId, } status_t CameraDeviceClientFlashControl::hasFlashUnitLocked( - const String16& cameraId, bool *hasFlash) { - if (!mCameraModule) { - ALOGE("%s: camera module is NULL", __FUNCTION__); - return NO_INIT; - } - + const String8& cameraId, bool *hasFlash) { if (!hasFlash) { return BAD_VALUE; } camera_info info; status_t res = mCameraModule->getCameraInfo( - atoi(String8(cameraId).string()), &info); + atoi(cameraId.string()), &info); if (res != 0) { ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__, cameraId.string()); @@ -441,7 +536,7 @@ status_t CameraDeviceClientFlashControl::hasFlashUnitLocked( return OK; } -status_t CameraDeviceClientFlashControl::submitTorchRequest(bool enabled) { +status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() { status_t res; if (mMetadata == NULL) { @@ -456,27 +551,29 @@ status_t CameraDeviceClientFlashControl::submitTorchRequest(bool enabled) { } } - uint8_t torchOn = enabled ? ANDROID_FLASH_MODE_TORCH : - ANDROID_FLASH_MODE_OFF; - + uint8_t torchOn = ANDROID_FLASH_MODE_TORCH; mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1); mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1); + uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON; + mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1); + int32_t requestId = 0; mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1); - List<const CameraMetadata> metadataRequestList; - metadataRequestList.push_back(*mMetadata); - - int64_t lastFrameNumber = 0; - res = mDevice->captureList(metadataRequestList, &lastFrameNumber); - + if (mStreaming) { + res = mDevice->setStreamingRequest(*mMetadata); + } else { + res = mDevice->capture(*mMetadata); + } return res; } + + status_t CameraDeviceClientFlashControl::setTorchMode( - const String16& cameraId, bool enabled) { + const String8& cameraId, bool enabled) { bool hasFlash = false; Mutex::Autolock l(mLock); @@ -499,6 +596,13 @@ status_t CameraDeviceClientFlashControl::setTorchMode( } else if (mDevice == NULL || cameraId != mCameraId) { // disabling the torch mode of an un-opened or different device. return OK; + } else { + // disabling the torch mode of currently opened device + disconnectCameraDevice(); + mTorchEnabled = false; + mCallbacks->torch_mode_status_change(mCallbacks, + cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF); + return OK; } if (mDevice == NULL) { @@ -508,13 +612,263 @@ status_t CameraDeviceClientFlashControl::setTorchMode( } } - res = submitTorchRequest(enabled); + res = submitTorchEnabledRequest(); if (res) { return res; } - mTorchEnabled = enabled; + mTorchEnabled = true; + mCallbacks->torch_mode_status_change(mCallbacks, + cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON); + return OK; +} +// CameraDeviceClientFlashControl implementation ends + + +///////////////////////////////////////////////////////////////////// +// CameraHardwareInterfaceFlashControl implementation begins +// Flash control for camera module <= v2.3 and camera HAL v1 +///////////////////////////////////////////////////////////////////// +CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl( + CameraModule& cameraModule, + const camera_module_callbacks_t& callbacks) : + mCameraModule(&cameraModule), + mCallbacks(&callbacks), + mTorchEnabled(false) { + +} + +CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() { + disconnectCameraDevice(); + + mAnw.clear(); + mSurfaceTexture.clear(); + mProducer.clear(); + mConsumer.clear(); + + if (mTorchEnabled) { + if (mCallbacks) { + ALOGV("%s: notify the framework that torch was turned off", + __FUNCTION__); + mCallbacks->torch_mode_status_change(mCallbacks, + mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF); + } + } +} + +status_t CameraHardwareInterfaceFlashControl::setTorchMode( + const String8& cameraId, bool enabled) { + Mutex::Autolock l(mLock); + + // pre-check + status_t res; + if (enabled) { + bool hasFlash = false; + res = hasFlashUnitLocked(cameraId, &hasFlash); + // invalid camera? + if (res) { + // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to + // another camera device. + return res == BAD_INDEX ? BAD_INDEX : -EINVAL; + } + // no flash unit? + if (!hasFlash) { + return -ENOSYS; + } + } else if (mDevice == NULL || cameraId != mCameraId) { + // disabling the torch mode of an un-opened or different device. + return OK; + } else { + // disabling the torch mode of currently opened device + disconnectCameraDevice(); + mTorchEnabled = false; + mCallbacks->torch_mode_status_change(mCallbacks, + cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF); + return OK; + } + + res = startPreviewAndTorch(); + if (res) { + return res; + } + + mTorchEnabled = true; + mCallbacks->torch_mode_status_change(mCallbacks, + cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON); + return OK; +} + +status_t CameraHardwareInterfaceFlashControl::hasFlashUnit( + const String8& cameraId, bool *hasFlash) { + Mutex::Autolock l(mLock); + return hasFlashUnitLocked(cameraId, hasFlash); +} + +status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked( + const String8& cameraId, bool *hasFlash) { + if (!hasFlash) { + return BAD_VALUE; + } + + status_t res; + if (mDevice == NULL) { + res = connectCameraDevice(cameraId); + if (res) { + return res; + } + } + + if (cameraId != mCameraId) { + return BAD_INDEX; + } + + const char *flashMode = + mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES); + if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) { + *hasFlash = true; + } else { + *hasFlash = false; + } + + return OK; +} + +status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() { + status_t res = OK; + res = mDevice->startPreview(); + if (res) { + ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__, + strerror(-res), res); + return res; + } + + mParameters.set(CameraParameters::KEY_FLASH_MODE, + CameraParameters::FLASH_MODE_TORCH); + + return mDevice->setParameters(mParameters); +} + +status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize( + int32_t *width, int32_t *height) { + if (!width || !height) { + return BAD_VALUE; + } + + int32_t w = INT32_MAX; + int32_t h = 1; + Vector<Size> sizes; + + mParameters.getSupportedPreviewSizes(sizes); + for (size_t i = 0; i < sizes.size(); i++) { + Size s = sizes[i]; + if (w * h > s.width * s.height) { + w = s.width; + h = s.height; + } + } + + if (w == INT32_MAX) { + return NAME_NOT_FOUND; + } + + *width = w; + *height = h; + + return OK; +} + +status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow( + sp<CameraHardwareInterface> device, int32_t width, int32_t height) { + status_t res; + BufferQueue::createBufferQueue(&mProducer, &mConsumer); + + mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL, + true, true); + if (mSurfaceTexture == NULL) { + return NO_MEMORY; + } + + int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; + res = mSurfaceTexture->setDefaultBufferSize(width, height); + if (res) { + return res; + } + res = mSurfaceTexture->setDefaultBufferFormat(format); + if (res) { + return res; + } + + mAnw = new Surface(mProducer, /*useAsync*/ true); + if (mAnw == NULL) { + return NO_MEMORY; + } + + res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA); + if (res) { + ALOGE("%s: Unable to connect to native window", __FUNCTION__); + return res; + } + + return device->setPreviewWindow(mAnw); +} + +status_t CameraHardwareInterfaceFlashControl::connectCameraDevice( + const String8& cameraId) { + sp<CameraHardwareInterface> device = + new CameraHardwareInterface(cameraId.string()); + + status_t res = device->initialize(mCameraModule); + if (res) { + ALOGE("%s: initializing camera %s failed", __FUNCTION__, + cameraId.string()); + return res; + } + + // need to set __get_memory in set_callbacks(). + device->setCallbacks(NULL, NULL, NULL, NULL); + + mParameters = device->getParameters(); + + int32_t width, height; + res = getSmallestSurfaceSize(&width, &height); + if (res) { + ALOGE("%s: failed to get smallest surface size for camera %s", + __FUNCTION__, cameraId.string()); + return res; + } + + res = initializePreviewWindow(device, width, height); + if (res) { + ALOGE("%s: failed to initialize preview window for camera %s", + __FUNCTION__, cameraId.string()); + return res; + } + + mCameraId = cameraId; + mDevice = device; + return OK; +} + +status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() { + if (mDevice == NULL) { + return OK; + } + + mParameters.set(CameraParameters::KEY_FLASH_MODE, + CameraParameters::FLASH_MODE_OFF); + mDevice->setParameters(mParameters); + mDevice->stopPreview(); + status_t res = native_window_api_disconnect(mAnw.get(), + NATIVE_WINDOW_API_CAMERA); + if (res) { + ALOGW("%s: native_window_api_disconnect failed: %s (%d)", + __FUNCTION__, strerror(-res), res); + } + mDevice->setPreviewWindow(NULL); + mDevice->release(); + return OK; } +// CameraHardwareInterfaceFlashControl implementation ends } diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h index a0de0b0..30f01f0 100644 --- a/services/camera/libcameraservice/CameraFlashlight.h +++ b/services/camera/libcameraservice/CameraFlashlight.h @@ -19,9 +19,11 @@ #include "hardware/camera_common.h" #include "utils/KeyedVector.h" +#include "utils/SortedVector.h" #include "gui/GLConsumer.h" #include "gui/Surface.h" #include "common/CameraDeviceBase.h" +#include "device1/CameraHardwareInterface.h" namespace android { @@ -37,11 +39,11 @@ class FlashControlBase : public virtual VirtualLightRefBase { // cause the torch mode to be turned off in HAL v1 devices. If // previously-on torch mode is turned off, // callbacks.torch_mode_status_change() should be invoked. - virtual status_t hasFlashUnit(const String16& cameraId, + virtual status_t hasFlashUnit(const String8& cameraId, bool *hasFlash) = 0; // set the torch mode to on or off. - virtual status_t setTorchMode(const String16& cameraId, + virtual status_t setTorchMode(const String8& cameraId, bool enabled) = 0; }; @@ -54,43 +56,61 @@ class CameraFlashlight : public virtual VirtualLightRefBase { const camera_module_callbacks_t& callbacks); virtual ~CameraFlashlight(); - // set the torch mode to on or off. - status_t setTorchMode(const String16& cameraId, bool enabled); + // Find all flash units. This must be called before other methods. All + // camera devices must be closed when it's called because HAL v1 devices + // need to be opened to query available flash modes. + status_t findFlashUnits(); - // Whether a camera device has a flash unit. Calling this function may - // cause the torch mode to be turned off in HAL v1 devices. - bool hasFlashUnit(const String16& cameraId); + // Whether a camera device has a flash unit. Before findFlashUnits() is + // called, this function always returns false. + bool hasFlashUnit(const String8& cameraId); + + // set the torch mode to on or off. + status_t setTorchMode(const String8& cameraId, bool enabled); // Notify CameraFlashlight that camera service is going to open a camera // device. CameraFlashlight will free the resources that may cause the // camera open to fail. Camera service must call this function before // opening a camera device. - status_t prepareDeviceOpen(); + status_t prepareDeviceOpen(const String8& cameraId); + + // Notify CameraFlashlight that camera service has closed a camera + // device. CameraFlashlight may invoke callbacks for torch mode + // available depending on the implementation. + status_t deviceClosed(const String8& cameraId); private: // create flashlight control based on camera module API and camera // device API versions. - status_t createFlashlightControl(const String16& cameraId); + status_t createFlashlightControl(const String8& cameraId); + + // mLock should be locked. + bool hasFlashUnitLocked(const String8& cameraId); sp<FlashControlBase> mFlashControl; CameraModule *mCameraModule; const camera_module_callbacks_t *mCallbacks; + SortedVector<String8> mOpenedCameraIds; - Mutex mLock; + // camera id -> if it has a flash unit + KeyedVector<String8, bool> mHasFlashlightMap; + bool mFlashlightMapInitialized; + + Mutex mLock; // protect CameraFlashlight API }; /** * Flash control for camera module v2.4 and above. */ -class FlashControl : public FlashControlBase { +class ModuleFlashControl : public FlashControlBase { public: - FlashControl(CameraModule& cameraModule, + ModuleFlashControl(CameraModule& cameraModule, const camera_module_callbacks_t& callbacks); - virtual ~FlashControl(); + virtual ~ModuleFlashControl(); // FlashControlBase - status_t hasFlashUnit(const String16& cameraId, bool *hasFlash); - status_t setTorchMode(const String16& cameraId, bool enabled); + status_t hasFlashUnit(const String8& cameraId, bool *hasFlash); + status_t setTorchMode(const String8& cameraId, bool enabled); private: CameraModule *mCameraModule; @@ -108,30 +128,38 @@ class CameraDeviceClientFlashControl : public FlashControlBase { virtual ~CameraDeviceClientFlashControl(); // FlashControlBase - status_t setTorchMode(const String16& cameraId, bool enabled); - status_t hasFlashUnit(const String16& cameraId, bool *hasFlash); + status_t setTorchMode(const String8& cameraId, bool enabled); + status_t hasFlashUnit(const String8& cameraId, bool *hasFlash); private: // connect to a camera device - status_t connectCameraDevice(const String16& cameraId); + status_t connectCameraDevice(const String8& cameraId); + // disconnect and free mDevice + status_t disconnectCameraDevice(); // initialize a surface - status_t initializeSurface(int32_t width, int32_t height); + status_t initializeSurface(sp<CameraDeviceBase>& device, int32_t width, + int32_t height); - // submit a request with the given torch mode - status_t submitTorchRequest(bool enabled); + // submit a request to enable the torch mode + status_t submitTorchEnabledRequest(); // get the smallest surface size of IMPLEMENTATION_DEFINED status_t getSmallestSurfaceSize(const camera_info& info, int32_t *width, int32_t *height); - status_t hasFlashUnitLocked(const String16& cameraId, bool *hasFlash); + // protected by mLock + status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash); CameraModule *mCameraModule; const camera_module_callbacks_t *mCallbacks; - String16 mCameraId; + String8 mCameraId; bool mTorchEnabled; CameraMetadata *mMetadata; + // WORKAROUND: will be set to true for HAL v2 devices where + // setStreamingRequest() needs to be call for torch mode settings to + // take effect. + bool mStreaming; sp<CameraDeviceBase> mDevice; @@ -144,6 +172,54 @@ class CameraDeviceClientFlashControl : public FlashControlBase { Mutex mLock; }; +/** + * Flash control for camera module <= v2.3 and camera HAL v1 + */ +class CameraHardwareInterfaceFlashControl : public FlashControlBase { + public: + CameraHardwareInterfaceFlashControl(CameraModule& cameraModule, + const camera_module_callbacks_t& callbacks); + virtual ~CameraHardwareInterfaceFlashControl(); + + // FlashControlBase + status_t setTorchMode(const String8& cameraId, bool enabled); + status_t hasFlashUnit(const String8& cameraId, bool *hasFlash); + + private: + // connect to a camera device + status_t connectCameraDevice(const String8& cameraId); + + // disconnect and free mDevice + status_t disconnectCameraDevice(); + + // initialize the preview window + status_t initializePreviewWindow(sp<CameraHardwareInterface> device, + int32_t width, int32_t height); + + // start preview and enable torch + status_t startPreviewAndTorch(); + + // get the smallest surface + status_t getSmallestSurfaceSize(int32_t *width, int32_t *height); + + // protected by mLock + status_t hasFlashUnitLocked(const String8& cameraId, bool *hasFlash); + + CameraModule *mCameraModule; + const camera_module_callbacks_t *mCallbacks; + sp<CameraHardwareInterface> mDevice; + String8 mCameraId; + CameraParameters mParameters; + bool mTorchEnabled; + + sp<IGraphicBufferProducer> mProducer; + sp<IGraphicBufferConsumer> mConsumer; + sp<GLConsumer> mSurfaceTexture; + sp<ANativeWindow> mAnw; + + Mutex mLock; +}; + } // namespace android #endif diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index d65ac21..6f37f16 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -101,14 +101,14 @@ static void torch_mode_status_change( ICameraServiceListener::TorchStatus status; switch (new_status) { - case TORCH_MODE_STATUS_AVAILABLE: - status = ICameraServiceListener::TORCH_STATUS_AVAILABLE; - break; - case TORCH_MODE_STATUS_RESOURCE_BUSY: + case TORCH_MODE_STATUS_NOT_AVAILABLE: status = ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE; break; - case TORCH_MODE_STATUS_OFF: - status = ICameraServiceListener::TORCH_STATUS_OFF; + case TORCH_MODE_STATUS_AVAILABLE_OFF: + status = ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF; + break; + case TORCH_MODE_STATUS_AVAILABLE_ON: + status = ICameraServiceListener::TORCH_STATUS_AVAILABLE_ON; break; default: ALOGE("Unknown torch status %d", new_status); @@ -116,7 +116,7 @@ static void torch_mode_status_change( } cs->onTorchStatusChanged( - String16(camera_id), + String8(camera_id), status); } } // extern "C" @@ -156,23 +156,29 @@ void CameraService::onFirstRef() } else { mModule = new CameraModule(rawModule); - mFlashlight = new CameraFlashlight(*mModule, *this); - const hw_module_t *common = mModule->getRawModule(); - ALOGI("Loaded \"%s\" camera module", common->name); + ALOGI("Loaded \"%s\" cameraCa module", common->name); mNumberOfCameras = mModule->getNumberOfCameras(); if (mNumberOfCameras > MAX_CAMERAS) { ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).", mNumberOfCameras, MAX_CAMERAS); mNumberOfCameras = MAX_CAMERAS; } + + mFlashlight = new CameraFlashlight(*mModule, *this); + status_t res = mFlashlight->findFlashUnits(); + if (res) { + // impossible because we haven't open any camera devices. + ALOGE("failed to find flash units."); + } + for (int i = 0; i < mNumberOfCameras; i++) { setCameraFree(i); - String16 cameraName = String16(String8::format("%d", i)); + String8 cameraName = String8::format("%d", i); if (mFlashlight->hasFlashUnit(cameraName)) { mTorchStatusMap.add(cameraName, - ICameraServiceListener::TORCH_STATUS_AVAILABLE); + ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF); } } @@ -207,7 +213,7 @@ CameraService::~CameraService() { void CameraService::onDeviceStatusChanged(int cameraId, int newStatus) { - ALOGI("%s: Status changed for cameraId=%d, newStatus=%d", __FUNCTION__, + ALOGV("%s: Status changed for cameraId=%d, newStatus=%d", __FUNCTION__, cameraId, newStatus); if (cameraId < 0 || cameraId >= MAX_CAMERAS) { @@ -268,24 +274,30 @@ void CameraService::onDeviceStatusChanged(int cameraId, } -void CameraService::onTorchStatusChanged(const String16& cameraId, +void CameraService::onTorchStatusChanged(const String8& cameraId, ICameraServiceListener::TorchStatus newStatus) { Mutex::Autolock al(mTorchStatusMutex); onTorchStatusChangedLocked(cameraId, newStatus); } -void CameraService::onTorchStatusChangedLocked(const String16& cameraId, +void CameraService::onTorchStatusChangedLocked(const String8& cameraId, ICameraServiceListener::TorchStatus newStatus) { ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d", __FUNCTION__, cameraId.string(), newStatus); - if (getTorchStatusLocked(cameraId) == newStatus) { + ICameraServiceListener::TorchStatus status; + status_t res = getTorchStatusLocked(cameraId, &status); + if (res) { + ALOGE("%s: cannot get torch status of camera %s", cameraId.string()); + return; + } + if (status == newStatus) { ALOGE("%s: Torch state transition to the same status 0x%x not allowed", __FUNCTION__, (uint32_t)newStatus); return; } - status_t res = setTorchStatusLocked(cameraId, newStatus); + res = setTorchStatusLocked(cameraId, newStatus); if (res) { ALOGE("%s: Failed to set the torch status", __FUNCTION__, (uint32_t)newStatus); @@ -294,7 +306,7 @@ void CameraService::onTorchStatusChangedLocked(const String16& cameraId, Vector<sp<ICameraServiceListener> >::const_iterator it; for (it = mListenerList.begin(); it != mListenerList.end(); ++it) { - (*it)->onTorchStatusChanged(newStatus, cameraId); + (*it)->onTorchStatusChanged(newStatus, String16(cameraId.string())); } } @@ -484,19 +496,6 @@ int CameraService::getDeviceVersion(int cameraId, int* facing) { return deviceVersion; } -status_t CameraService::filterOpenErrorCode(status_t err) { - switch(err) { - case NO_ERROR: - case -EBUSY: - case -EINVAL: - case -EUSERS: - return err; - default: - break; - } - return -ENODEV; -} - status_t CameraService::filterGetInfoErrorCode(status_t err) { switch(err) { case NO_ERROR: @@ -754,7 +753,7 @@ status_t CameraService::connectHelperLocked( bool legacyMode) { // give flashlight a chance to close devices if necessary. - mFlashlight->prepareDeviceOpen(); + mFlashlight->prepareDeviceOpen(String8::format("%d", cameraId)); int facing = -1; int deviceVersion = getDeviceVersion(cameraId, &facing); @@ -932,44 +931,94 @@ status_t CameraService::connectLegacy( return OK; } +bool CameraService::validCameraIdForSetTorchMode(const String8& cameraId) { + // invalid string for int + if (cameraId.string() == NULL) { + return false; + } + errno = 0; + char *endptr; + long id = strtol(cameraId.string(), &endptr, 10); // base 10 + if (errno || id > INT_MAX || id < INT_MIN || *endptr != 0) { + return false; + } + + // id matches one of the plugged-in devices? + ICameraServiceListener::Status deviceStatus = getStatus(id); + if (deviceStatus != ICameraServiceListener::STATUS_PRESENT && + deviceStatus != ICameraServiceListener::STATUS_NOT_AVAILABLE) { + return false; + } + + return true; +} + status_t CameraService::setTorchMode(const String16& cameraId, bool enabled, const sp<IBinder>& clientBinder) { if (enabled && clientBinder == NULL) { ALOGE("%s: torch client binder is NULL", __FUNCTION__); - return -ENOSYS; + return -EINVAL; } - Mutex::Autolock al(mTorchStatusMutex); - status_t res = mFlashlight->setTorchMode(cameraId, enabled); + String8 id = String8(cameraId.string()); + + // verify id is valid. + if (validCameraIdForSetTorchMode(id) == false) { + ALOGE("%s: camera id is invalid %s", id.string()); + return -EINVAL; + } + + { + Mutex::Autolock al(mTorchStatusMutex); + ICameraServiceListener::TorchStatus status; + status_t res = getTorchStatusLocked(id, &status); + if (res) { + ALOGE("%s: getting current torch status failed for camera %s", + __FUNCTION__, id.string()); + return -EINVAL; + } + + if (status == ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE) { + if (getStatus(atoi(id.string())) == + ICameraServiceListener::STATUS_NOT_AVAILABLE) { + ALOGE("%s: torch mode of camera %s is not available because " + "camera is in use", __FUNCTION__, id.string()); + return -EBUSY; + } else { + ALOGE("%s: torch mode of camera %s is not available due to " + "insufficient resources", __FUNCTION__, id.string()); + return -EUSERS; + } + } + } + + status_t res = mFlashlight->setTorchMode(id, enabled); if (res) { - ALOGE("%s: setting torch mode of camera %s to %d failed", __FUNCTION__, - cameraId.string(), enabled); + ALOGE("%s: setting torch mode of camera %s to %d failed. %s (%d)", + __FUNCTION__, id.string(), enabled, strerror(-res), res); return res; } - // update the link to client's death - ssize_t index = mTorchClientMap.indexOfKey(cameraId); - if (enabled) { - if (index == NAME_NOT_FOUND) { - mTorchClientMap.add(cameraId, clientBinder); - } else { - const sp<IBinder> oldBinder = mTorchClientMap.valueAt(index); - oldBinder->unlinkToDeath(this); + { + // update the link to client's death + Mutex::Autolock al(mTorchClientMapMutex); + ssize_t index = mTorchClientMap.indexOfKey(id); + if (enabled) { + if (index == NAME_NOT_FOUND) { + mTorchClientMap.add(id, clientBinder); + } else { + const sp<IBinder> oldBinder = mTorchClientMap.valueAt(index); + oldBinder->unlinkToDeath(this); - mTorchClientMap.replaceValueAt(index, clientBinder); + mTorchClientMap.replaceValueAt(index, clientBinder); + } + clientBinder->linkToDeath(this); + } else if (index != NAME_NOT_FOUND) { + sp<IBinder> oldBinder = mTorchClientMap.valueAt(index); + oldBinder->unlinkToDeath(this); } - clientBinder->linkToDeath(this); - } else if (index != NAME_NOT_FOUND) { - sp<IBinder> oldBinder = mTorchClientMap.valueAt(index); - oldBinder->unlinkToDeath(this); } - // notify the listeners the change. - ICameraServiceListener::TorchStatus status = enabled ? - ICameraServiceListener::TORCH_STATUS_ON : - ICameraServiceListener::TORCH_STATUS_OFF; - onTorchStatusChangedLocked(cameraId, status); - return OK; } @@ -1099,7 +1148,7 @@ status_t CameraService::connectDevice( int deviceVersion = getDeviceVersion(cameraId, &facing); // give flashlight a chance to close devices if necessary. - mFlashlight->prepareDeviceOpen(); + mFlashlight->prepareDeviceOpen(String8::format("%d", cameraId)); switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: @@ -1176,8 +1225,8 @@ status_t CameraService::addListener( { Mutex::Autolock al(mTorchStatusMutex); for (size_t i = 0; i < mTorchStatusMap.size(); i++ ) { - listener->onTorchStatusChanged(mTorchStatusMap.valueAt(i), - mTorchStatusMap.keyAt(i)); + String16 id = String16(mTorchStatusMap.keyAt(i).string()); + listener->onTorchStatusChanged(mTorchStatusMap.valueAt(i), id); } } @@ -1616,6 +1665,9 @@ status_t CameraService::BasicClient::finishCameraOps() { mCameraId, &rejectSourceStates); + // Notify flashlight that a camera device is closed. + mCameraService->mFlashlight->deviceClosed( + String8::format("%d", mCameraId)); } // Always stop watching, even if no camera op is active if (mOpsCallback != NULL) { @@ -1862,17 +1914,18 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) { } void CameraService::handleTorchClientBinderDied(const wp<IBinder> &who) { - Mutex::Autolock al(mTorchStatusMutex); + Mutex::Autolock al(mTorchClientMapMutex); for (size_t i = 0; i < mTorchClientMap.size(); i++) { if (mTorchClientMap[i] == who) { // turn off the torch mode that was turned on by dead client - String16 cameraId = mTorchClientMap.keyAt(i); - mFlashlight->setTorchMode(cameraId, false); + String8 cameraId = mTorchClientMap.keyAt(i); + status_t res = mFlashlight->setTorchMode(cameraId, false); + if (res) { + ALOGE("%s: torch client died but couldn't turn off torch: " + "%s (%d)", __FUNCTION__, strerror(-res), res); + return; + } mTorchClientMap.removeItemsAt(i); - - // notify torch mode was turned off - onTorchStatusChangedLocked(cameraId, - ICameraServiceListener::TORCH_STATUS_OFF); break; } } @@ -1968,6 +2021,19 @@ void CameraService::updateStatus(ICameraServiceListener::Status status, } } + if (status == ICameraServiceListener::STATUS_NOT_PRESENT || + status == ICameraServiceListener::STATUS_NOT_AVAILABLE) { + // update torch status to not available when the camera device + // becomes not present or not available. + onTorchStatusChanged(String8::format("%d", cameraId), + ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE); + } else if (status == ICameraServiceListener::STATUS_PRESENT) { + // update torch status to available when the camera device becomes + // present or available + onTorchStatusChanged(String8::format("%d", cameraId), + ICameraServiceListener::TORCH_STATUS_AVAILABLE_OFF); + } + Vector<sp<ICameraServiceListener> >::const_iterator it; for (it = mListenerList.begin(); it != mListenerList.end(); ++it) { (*it)->onStatusChanged(status, cameraId); @@ -1985,17 +2051,23 @@ ICameraServiceListener::Status CameraService::getStatus(int cameraId) const { return mStatusList[cameraId]; } -ICameraServiceListener::TorchStatus CameraService::getTorchStatusLocked( - const String16& cameraId) const { +status_t CameraService::getTorchStatusLocked( + const String8& cameraId, + ICameraServiceListener::TorchStatus *status) const { + if (!status) { + return BAD_VALUE; + } ssize_t index = mTorchStatusMap.indexOfKey(cameraId); if (index == NAME_NOT_FOUND) { - return ICameraServiceListener::TORCH_STATUS_NOT_AVAILABLE; + // invalid camera ID or the camera doesn't have a flash unit + return NAME_NOT_FOUND; } - return mTorchStatusMap.valueAt(index); + *status = mTorchStatusMap.valueAt(index); + return OK; } -status_t CameraService::setTorchStatusLocked(const String16& cameraId, +status_t CameraService::setTorchStatusLocked(const String8& cameraId, ICameraServiceListener::TorchStatus status) { ssize_t index = mTorchStatusMap.indexOfKey(cameraId); if (index == NAME_NOT_FOUND) { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 84bcdb8..22afc8c 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -72,7 +72,7 @@ public: // HAL Callbacks virtual void onDeviceStatusChanged(int cameraId, int newStatus); - virtual void onTorchStatusChanged(const String16& cameraId, + virtual void onTorchStatusChanged(const String8& cameraId, ICameraServiceListener::TorchStatus newStatus); @@ -150,7 +150,6 @@ public: ///////////////////////////////////////////////////////////////////// // Shared utilities - static status_t filterOpenErrorCode(status_t err); static status_t filterGetInfoErrorCode(status_t err); ///////////////////////////////////////////////////////////////////// @@ -418,28 +417,33 @@ private: // flashlight control sp<CameraFlashlight> mFlashlight; - // guard mTorchStatusMap and mTorchClientMap + // guard mTorchStatusMap Mutex mTorchStatusMutex; + // guard mTorchClientMap + Mutex mTorchClientMapMutex; // camera id -> torch status - KeyedVector<String16, ICameraServiceListener::TorchStatus> mTorchStatusMap; + KeyedVector<String8, ICameraServiceListener::TorchStatus> mTorchStatusMap; // camera id -> torch client binder // only store the last client that turns on each camera's torch mode - KeyedVector<String16, sp<IBinder> > mTorchClientMap; + KeyedVector<String8, sp<IBinder> > mTorchClientMap; // check and handle if torch client's process has died void handleTorchClientBinderDied(const wp<IBinder> &who); // handle torch mode status change and invoke callbacks. mTorchStatusMutex // should be locked. - void onTorchStatusChangedLocked(const String16& cameraId, + void onTorchStatusChangedLocked(const String8& cameraId, ICameraServiceListener::TorchStatus newStatus); + // validate the camera id for use of setting a torch mode. + bool validCameraIdForSetTorchMode(const String8& cameraId); + // get a camera's torch status. mTorchStatusMutex should be locked. - ICameraServiceListener::TorchStatus getTorchStatusLocked( - const String16 &cameraId) const; + status_t getTorchStatusLocked(const String8 &cameraId, + ICameraServiceListener::TorchStatus *status) const; // set a camera's torch status. mTorchStatusMutex should be locked. - status_t setTorchStatusLocked(const String16 &cameraId, + status_t setTorchStatusLocked(const String8 &cameraId, ICameraServiceListener::TorchStatus status); // IBinder::DeathRecipient implementation diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp index 85a4df9..5f767ad 100644 --- a/services/camera/libcameraservice/common/CameraModule.cpp +++ b/services/camera/libcameraservice/common/CameraModule.cpp @@ -91,7 +91,7 @@ int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) { } int CameraModule::open(const char* id, struct hw_device_t** device) { - return mModule->common.methods->open(&mModule->common, id, device); + return filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device)); } int CameraModule::openLegacy( @@ -125,5 +125,20 @@ int CameraModule::setTorchMode(const char* camera_id, bool enable) { return mModule->set_torch_mode(camera_id, enable); } + +status_t CameraModule::filterOpenErrorCode(status_t err) { + switch(err) { + case NO_ERROR: + case -EBUSY: + case -EINVAL: + case -EUSERS: + return err; + default: + break; + } + return -ENODEV; +} + + }; // namespace android diff --git a/services/camera/libcameraservice/common/CameraModule.h b/services/camera/libcameraservice/common/CameraModule.h index 31b9ae2..16207aa 100644 --- a/services/camera/libcameraservice/common/CameraModule.h +++ b/services/camera/libcameraservice/common/CameraModule.h @@ -50,6 +50,8 @@ public: private: // Derive camera characteristics keys defined after HAL device version static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars); + status_t filterOpenErrorCode(status_t err); + camera_module_t *mModule; CameraMetadata mCameraCharacteristics[MAX_CAMERAS_PER_MODULE]; camera_info mCameraInfo[MAX_CAMERAS_PER_MODULE]; diff --git a/services/camera/libcameraservice/device1/CameraHardwareInterface.h b/services/camera/libcameraservice/device1/CameraHardwareInterface.h index 9e1cdc9..f5ebbf8 100644 --- a/services/camera/libcameraservice/device1/CameraHardwareInterface.h +++ b/services/camera/libcameraservice/device1/CameraHardwareInterface.h @@ -104,8 +104,7 @@ public: CAMERA_DEVICE_API_VERSION_1_0, (hw_device_t **)&mDevice); } else { - rc = CameraService::filterOpenErrorCode(module->open( - mName.string(), (hw_device_t **)&mDevice)); + rc = module->open(mName.string(), (hw_device_t **)&mDevice); } if (rc != OK) { ALOGE("Could not open camera %s: %d", mName.string(), rc); diff --git a/services/camera/libcameraservice/device2/Camera2Device.cpp b/services/camera/libcameraservice/device2/Camera2Device.cpp index be66c4d..43c8307 100644 --- a/services/camera/libcameraservice/device2/Camera2Device.cpp +++ b/services/camera/libcameraservice/device2/Camera2Device.cpp @@ -68,8 +68,7 @@ status_t Camera2Device::initialize(CameraModule *module) camera2_device_t *device; - res = CameraService::filterOpenErrorCode(module->open( - name, reinterpret_cast<hw_device_t**>(&device))); + res = module->open(name, reinterpret_cast<hw_device_t**>(&device)); if (res != OK) { ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__, diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp index 9a4e5ac..bca9bfd 100644 --- a/services/camera/libcameraservice/device3/Camera3Device.cpp +++ b/services/camera/libcameraservice/device3/Camera3Device.cpp @@ -106,8 +106,8 @@ status_t Camera3Device::initialize(CameraModule *module) camera3_device_t *device; ATRACE_BEGIN("camera3->open"); - res = CameraService::filterOpenErrorCode(module->open( - deviceName.string(), reinterpret_cast<hw_device_t**>(&device))); + res = module->open(deviceName.string(), + reinterpret_cast<hw_device_t**>(&device)); ATRACE_END(); if (res != OK) { |