diff options
Diffstat (limited to 'services/camera/libcameraservice/CameraFlashlight.cpp')
-rw-r--r-- | services/camera/libcameraservice/CameraFlashlight.cpp | 886 |
1 files changed, 886 insertions, 0 deletions
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp new file mode 100644 index 0000000..8613ac6 --- /dev/null +++ b/services/camera/libcameraservice/CameraFlashlight.cpp @@ -0,0 +1,886 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "CameraFlashlight" +#define ATRACE_TAG ATRACE_TAG_CAMERA +// #define LOG_NDEBUG 0 + +#include <utils/Log.h> +#include <utils/Trace.h> +#include <cutils/properties.h> + +#include "camera/CameraMetadata.h" +#include "CameraFlashlight.h" +#include "gui/IGraphicBufferConsumer.h" +#include "gui/BufferQueue.h" +#include "camera/camera2/CaptureRequest.h" +#include "CameraDeviceFactory.h" + + +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), + mFlashlightMapInitialized(false) { +} + +CameraFlashlight::~CameraFlashlight() { +} + +status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) { + ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__, + cameraId.string()); + if (mFlashControl != NULL) { + return INVALID_OPERATION; + } + + status_t res = OK; + + if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) { + mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks); + if (mFlashControl == NULL) { + ALOGV("%s: cannot create flash control for module api v2.4+", + __FUNCTION__); + return NO_MEMORY; + } + } else { + uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0; + + if (mCameraModule->getModuleApiVersion() >= + CAMERA_MODULE_API_VERSION_2_0) { + camera_info info; + res = mCameraModule->getCameraInfo( + atoi(String8(cameraId).string()), &info); + if (res) { + ALOGE("%s: failed to get camera info for camera %s", + __FUNCTION__, cameraId.string()); + return res; + } + deviceVersion = info.device_version; + } + + if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) { + CameraDeviceClientFlashControl *flashControl = + new CameraDeviceClientFlashControl(*mCameraModule, + *mCallbacks); + if (!flashControl) { + return NO_MEMORY; + } + + mFlashControl = flashControl; + } else { + mFlashControl = + new CameraHardwareInterfaceFlashControl(*mCameraModule, + *mCallbacks); + } + } + + return OK; +} + +status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) { + if (!mFlashlightMapInitialized) { + ALOGE("%s: findFlashUnits() must be called before this method."); + return NO_INIT; + } + + ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__, + cameraId.string(), enabled); + + status_t res = OK; + Mutex::Autolock l(mLock); + + if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) { + // This case is needed to avoid state corruption during the following call sequence: + // CameraService::setTorchMode for camera ID 0 begins, does torch status checks + // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends + // CameraService::setTorchMode for camera ID 0 continues, calls + // CameraFlashlight::setTorchMode + + // TODO: Move torch status checks and state updates behind this CameraFlashlight lock + // to avoid other similar race conditions. + ALOGE("%s: Camera device %s is in use, cannot set torch mode.", + __FUNCTION__, cameraId.string()); + return -EBUSY; + } + + if (mFlashControl == NULL) { + if (enabled == false) { + return OK; + } + + res = createFlashlightControl(cameraId); + if (res) { + return res; + } + res = mFlashControl->setTorchMode(cameraId, enabled); + return res; + } + + // if flash control already exists, turning on torch mode may fail if it's + // tied to another camera device for module v2.3 and below. + res = mFlashControl->setTorchMode(cameraId, enabled); + if (res == BAD_INDEX) { + // flash control is tied to another camera device, need to close it and + // try again. + mFlashControl.clear(); + res = createFlashlightControl(cameraId); + if (res) { + return res; + } + res = mFlashControl->setTorchMode(cameraId, enabled); + } + + return res; +} + +status_t CameraFlashlight::findFlashUnits() { + Mutex::Autolock l(mLock); + status_t res; + int32_t numCameras = mCameraModule->getNumberOfCameras(); + + mHasFlashlightMap.clear(); + mFlashlightMapInitialized = false; + + 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__, + 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); + } + + mFlashlightMapInitialized = true; + return OK; +} + +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 mHasFlashlightMap.valueAt(index); +} + +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->getModuleApiVersion() < 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. + 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()); + + 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->getModuleApiVersion() < 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() { +} + +///////////////////////////////////////////////////////////////////// +// ModuleFlashControl implementation begins +// Flash control for camera module v2.4 and above. +///////////////////////////////////////////////////////////////////// +ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule, + const camera_module_callbacks_t& callbacks) : + mCameraModule(&cameraModule) { +} + +ModuleFlashControl::~ModuleFlashControl() { +} + +status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) { + if (!hasFlash) { + return BAD_VALUE; + } + + *hasFlash = false; + Mutex::Autolock l(mLock); + + camera_info info; + status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), + &info); + if (res != 0) { + return res; + } + + CameraMetadata metadata; + metadata = info.static_camera_characteristics; + camera_metadata_entry flashAvailable = + metadata.find(ANDROID_FLASH_INFO_AVAILABLE); + if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) { + *hasFlash = true; + } + + return OK; +} + +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); + 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), + mStreaming(false) { +} + +CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() { + disconnectCameraDevice(); + if (mMetadata) { + delete mMetadata; + } + + 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 CameraDeviceClientFlashControl::initializeSurface( + sp<CameraDeviceBase> &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 = device->createStream(mAnw, width, height, format, + HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId); + if (res) { + return res; + } + + res = device->configureStreams(); + if (res) { + return res; + } + + return res; +} + +status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize( + const camera_info& info, int32_t *width, int32_t *height) { + if (!width || !height) { + return BAD_VALUE; + } + + int32_t w = INT32_MAX; + int32_t h = 1; + + CameraMetadata metadata; + metadata = info.static_camera_characteristics; + camera_metadata_entry streamConfigs = + metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS); + for (size_t i = 0; i < streamConfigs.count; i += 4) { + int32_t fmt = streamConfigs.data.i32[i]; + if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) { + int32_t ww = streamConfigs.data.i32[i + 1]; + int32_t hh = streamConfigs.data.i32[i + 2]; + + 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; + } + } + } + + if (w == INT32_MAX) { + return NAME_NOT_FOUND; + } + + *width = w; + *height = h; + + return OK; +} + +status_t CameraDeviceClientFlashControl::connectCameraDevice( + const String8& cameraId) { + camera_info info; + status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info); + if (res != 0) { + ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__, + cameraId.string()); + return res; + } + + sp<CameraDeviceBase> device = + CameraDeviceFactory::createDevice(atoi(cameraId.string())); + if (device == NULL) { + return NO_MEMORY; + } + + res = device->initialize(mCameraModule); + if (res) { + return res; + } + + int32_t width, height; + res = getSmallestSurfaceSize(info, &width, &height); + if (res) { + return res; + } + res = initializeSurface(device, width, height); + if (res) { + return res; + } + + mCameraId = cameraId; + mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1); + mDevice = device; + + return OK; +} + +status_t CameraDeviceClientFlashControl::disconnectCameraDevice() { + if (mDevice != NULL) { + mDevice->disconnect(); + mDevice.clear(); + } + + return OK; +} + + + +status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId, + bool *hasFlash) { + ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__, + cameraId.string()); + + Mutex::Autolock l(mLock); + return hasFlashUnitLocked(cameraId, hasFlash); + +} + +status_t CameraDeviceClientFlashControl::hasFlashUnitLocked( + const String8& cameraId, bool *hasFlash) { + if (!hasFlash) { + return BAD_VALUE; + } + + camera_info info; + status_t res = mCameraModule->getCameraInfo( + atoi(cameraId.string()), &info); + if (res != 0) { + ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__, + cameraId.string()); + return res; + } + + CameraMetadata metadata; + metadata = info.static_camera_characteristics; + camera_metadata_entry flashAvailable = + metadata.find(ANDROID_FLASH_INFO_AVAILABLE); + if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) { + *hasFlash = true; + } + + return OK; +} + +status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() { + status_t res; + + if (mMetadata == NULL) { + mMetadata = new CameraMetadata(); + if (mMetadata == NULL) { + return NO_MEMORY; + } + res = mDevice->createDefaultRequest( + CAMERA3_TEMPLATE_PREVIEW, mMetadata); + if (res) { + return res; + } + } + + 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); + + if (mStreaming) { + res = mDevice->setStreamingRequest(*mMetadata); + } else { + res = mDevice->capture(*mMetadata); + } + return res; +} + + + + +status_t CameraDeviceClientFlashControl::setTorchMode( + const String8& cameraId, bool enabled) { + bool hasFlash = false; + + Mutex::Autolock l(mLock); + status_t res = hasFlashUnitLocked(cameraId, &hasFlash); + + // pre-check + if (enabled) { + // invalid camera? + if (res) { + return -EINVAL; + } + // no flash unit? + if (!hasFlash) { + return -ENOSYS; + } + // already opened for a different device? + if (mDevice != NULL && cameraId != mCameraId) { + return BAD_INDEX; + } + } 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) { + res = connectCameraDevice(cameraId); + if (res) { + return res; + } + } + + res = submitTorchEnabledRequest(); + if (res) { + return res; + } + + 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 + +} |