summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/camera/libcameraservice/CameraFlashlight.cpp582
-rw-r--r--services/camera/libcameraservice/CameraFlashlight.h122
-rw-r--r--services/camera/libcameraservice/CameraService.cpp214
-rw-r--r--services/camera/libcameraservice/CameraService.h22
-rw-r--r--services/camera/libcameraservice/common/CameraModule.cpp17
-rw-r--r--services/camera/libcameraservice/common/CameraModule.h2
-rw-r--r--services/camera/libcameraservice/device1/CameraHardwareInterface.h3
-rw-r--r--services/camera/libcameraservice/device2/Camera2Device.cpp3
-rw-r--r--services/camera/libcameraservice/device3/Camera3Device.cpp4
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) {