Home | History | Annotate | Download | only in libcameraservice
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #define LOG_TAG "CameraFlashlight"
     18 #define ATRACE_TAG ATRACE_TAG_CAMERA
     19 // #define LOG_NDEBUG 0
     20 
     21 #include <utils/Log.h>
     22 #include <utils/Trace.h>
     23 #include <cutils/properties.h>
     24 
     25 #include "camera/CameraMetadata.h"
     26 #include "CameraFlashlight.h"
     27 #include "gui/IGraphicBufferConsumer.h"
     28 #include "gui/BufferQueue.h"
     29 #include "camera/camera2/CaptureRequest.h"
     30 #include "CameraDeviceFactory.h"
     31 
     32 
     33 namespace android {
     34 
     35 /////////////////////////////////////////////////////////////////////
     36 // CameraFlashlight implementation begins
     37 // used by camera service to control flashflight.
     38 /////////////////////////////////////////////////////////////////////
     39 CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
     40         const camera_module_callbacks_t& callbacks) :
     41         mCameraModule(&cameraModule),
     42         mCallbacks(&callbacks),
     43         mFlashlightMapInitialized(false) {
     44 }
     45 
     46 CameraFlashlight::~CameraFlashlight() {
     47 }
     48 
     49 status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
     50     ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
     51             cameraId.string());
     52     if (mFlashControl != NULL) {
     53         return INVALID_OPERATION;
     54     }
     55 
     56     status_t res = OK;
     57 
     58     if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
     59         mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
     60         if (mFlashControl == NULL) {
     61             ALOGV("%s: cannot create flash control for module api v2.4+",
     62                      __FUNCTION__);
     63             return NO_MEMORY;
     64         }
     65     } else {
     66         uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
     67 
     68         if (mCameraModule->getModuleApiVersion() >=
     69                     CAMERA_MODULE_API_VERSION_2_0) {
     70             camera_info info;
     71             res = mCameraModule->getCameraInfo(
     72                     atoi(String8(cameraId).string()), &info);
     73             if (res) {
     74                 ALOGE("%s: failed to get camera info for camera %s",
     75                         __FUNCTION__, cameraId.string());
     76                 return res;
     77             }
     78             deviceVersion = info.device_version;
     79         }
     80 
     81         if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
     82             CameraDeviceClientFlashControl *flashControl =
     83                     new CameraDeviceClientFlashControl(*mCameraModule,
     84                                                        *mCallbacks);
     85             if (!flashControl) {
     86                 return NO_MEMORY;
     87             }
     88 
     89             mFlashControl = flashControl;
     90         } else {
     91             mFlashControl =
     92                     new CameraHardwareInterfaceFlashControl(*mCameraModule,
     93                                                             *mCallbacks);
     94         }
     95     }
     96 
     97     return OK;
     98 }
     99 
    100 status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
    101     if (!mFlashlightMapInitialized) {
    102         ALOGE("%s: findFlashUnits() must be called before this method.");
    103         return NO_INIT;
    104     }
    105 
    106     ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
    107             cameraId.string(), enabled);
    108 
    109     status_t res = OK;
    110     Mutex::Autolock l(mLock);
    111 
    112     if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
    113         // This case is needed to avoid state corruption during the following call sequence:
    114         // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
    115         // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
    116         // CameraService::setTorchMode for camera ID 0 continues, calls
    117         //        CameraFlashlight::setTorchMode
    118 
    119         // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
    120         // to avoid other similar race conditions.
    121         ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
    122                 __FUNCTION__, cameraId.string());
    123         return -EBUSY;
    124     }
    125 
    126     if (mFlashControl == NULL) {
    127         if (enabled == false) {
    128             return OK;
    129         }
    130 
    131         res = createFlashlightControl(cameraId);
    132         if (res) {
    133             return res;
    134         }
    135         res =  mFlashControl->setTorchMode(cameraId, enabled);
    136         return res;
    137     }
    138 
    139     // if flash control already exists, turning on torch mode may fail if it's
    140     // tied to another camera device for module v2.3 and below.
    141     res = mFlashControl->setTorchMode(cameraId, enabled);
    142     if (res == BAD_INDEX) {
    143         // flash control is tied to another camera device, need to close it and
    144         // try again.
    145         mFlashControl.clear();
    146         res = createFlashlightControl(cameraId);
    147         if (res) {
    148             return res;
    149         }
    150         res = mFlashControl->setTorchMode(cameraId, enabled);
    151     }
    152 
    153     return res;
    154 }
    155 
    156 status_t CameraFlashlight::findFlashUnits() {
    157     Mutex::Autolock l(mLock);
    158     status_t res;
    159     int32_t numCameras = mCameraModule->getNumberOfCameras();
    160 
    161     mHasFlashlightMap.clear();
    162     mFlashlightMapInitialized = false;
    163 
    164     for (int32_t i = 0; i < numCameras; i++) {
    165         bool hasFlash = false;
    166         String8 id = String8::format("%d", i);
    167 
    168         res = createFlashlightControl(id);
    169         if (res) {
    170             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
    171                     id.string());
    172         } else {
    173             res = mFlashControl->hasFlashUnit(id, &hasFlash);
    174             if (res == -EUSERS || res == -EBUSY) {
    175                 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
    176                         "camera devices may be opened", __FUNCTION__,
    177                         id.string());
    178                 return res;
    179             } else if (res) {
    180                 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
    181                         " (%d)", __FUNCTION__, id.string(), strerror(-res),
    182                         res);
    183             }
    184 
    185             mFlashControl.clear();
    186         }
    187         mHasFlashlightMap.add(id, hasFlash);
    188     }
    189 
    190     mFlashlightMapInitialized = true;
    191     return OK;
    192 }
    193 
    194 bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
    195     status_t res;
    196 
    197     Mutex::Autolock l(mLock);
    198     return hasFlashUnitLocked(cameraId);
    199 }
    200 
    201 bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
    202     if (!mFlashlightMapInitialized) {
    203         ALOGE("%s: findFlashUnits() must be called before this method.");
    204         return false;
    205     }
    206 
    207     ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
    208     if (index == NAME_NOT_FOUND) {
    209         ALOGE("%s: camera %s not present when findFlashUnits() was called",
    210                 __FUNCTION__, cameraId.string());
    211         return false;
    212     }
    213 
    214     return mHasFlashlightMap.valueAt(index);
    215 }
    216 
    217 status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
    218     ALOGV("%s: prepare for device open", __FUNCTION__);
    219 
    220     Mutex::Autolock l(mLock);
    221     if (!mFlashlightMapInitialized) {
    222         ALOGE("%s: findFlashUnits() must be called before this method.");
    223         return NO_INIT;
    224     }
    225 
    226     if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
    227         // framework is going to open a camera device, all flash light control
    228         // should be closed for backward compatible support.
    229         mFlashControl.clear();
    230 
    231         if (mOpenedCameraIds.size() == 0) {
    232             // notify torch unavailable for all cameras with a flash
    233             int numCameras = mCameraModule->getNumberOfCameras();
    234             for (int i = 0; i < numCameras; i++) {
    235                 if (hasFlashUnitLocked(String8::format("%d", i))) {
    236                     mCallbacks->torch_mode_status_change(mCallbacks,
    237                             String8::format("%d", i).string(),
    238                             TORCH_MODE_STATUS_NOT_AVAILABLE);
    239                 }
    240             }
    241         }
    242 
    243         // close flash control that may be opened by calling hasFlashUnitLocked.
    244         mFlashControl.clear();
    245     }
    246 
    247     if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
    248         mOpenedCameraIds.add(cameraId);
    249     }
    250 
    251     return OK;
    252 }
    253 
    254 status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
    255     ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
    256 
    257     Mutex::Autolock l(mLock);
    258     if (!mFlashlightMapInitialized) {
    259         ALOGE("%s: findFlashUnits() must be called before this method.");
    260         return NO_INIT;
    261     }
    262 
    263     ssize_t index = mOpenedCameraIds.indexOf(cameraId);
    264     if (index == NAME_NOT_FOUND) {
    265         ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
    266                 cameraId.string());
    267     } else {
    268         mOpenedCameraIds.removeAt(index);
    269     }
    270 
    271     // Cannot do anything until all cameras are closed.
    272     if (mOpenedCameraIds.size() != 0)
    273         return OK;
    274 
    275     if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
    276         // notify torch available for all cameras with a flash
    277         int numCameras = mCameraModule->getNumberOfCameras();
    278         for (int i = 0; i < numCameras; i++) {
    279             if (hasFlashUnitLocked(String8::format("%d", i))) {
    280                 mCallbacks->torch_mode_status_change(mCallbacks,
    281                         String8::format("%d", i).string(),
    282                         TORCH_MODE_STATUS_AVAILABLE_OFF);
    283             }
    284         }
    285     }
    286 
    287     return OK;
    288 }
    289 // CameraFlashlight implementation ends
    290 
    291 
    292 FlashControlBase::~FlashControlBase() {
    293 }
    294 
    295 /////////////////////////////////////////////////////////////////////
    296 // ModuleFlashControl implementation begins
    297 // Flash control for camera module v2.4 and above.
    298 /////////////////////////////////////////////////////////////////////
    299 ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
    300         const camera_module_callbacks_t& callbacks) :
    301     mCameraModule(&cameraModule) {
    302 }
    303 
    304 ModuleFlashControl::~ModuleFlashControl() {
    305 }
    306 
    307 status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
    308     if (!hasFlash) {
    309         return BAD_VALUE;
    310     }
    311 
    312     *hasFlash = false;
    313     Mutex::Autolock l(mLock);
    314 
    315     camera_info info;
    316     status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
    317             &info);
    318     if (res != 0) {
    319         return res;
    320     }
    321 
    322     CameraMetadata metadata;
    323     metadata = info.static_camera_characteristics;
    324     camera_metadata_entry flashAvailable =
    325             metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
    326     if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
    327         *hasFlash = true;
    328     }
    329 
    330     return OK;
    331 }
    332 
    333 status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
    334     ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
    335             cameraId.string(), enabled);
    336 
    337     Mutex::Autolock l(mLock);
    338     return mCameraModule->setTorchMode(cameraId.string(), enabled);
    339 }
    340 // ModuleFlashControl implementation ends
    341 
    342 /////////////////////////////////////////////////////////////////////
    343 // CameraDeviceClientFlashControl implementation begins
    344 // Flash control for camera module <= v2.3 and camera HAL v2-v3
    345 /////////////////////////////////////////////////////////////////////
    346 CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
    347         CameraModule& cameraModule,
    348         const camera_module_callbacks_t& callbacks) :
    349         mCameraModule(&cameraModule),
    350         mCallbacks(&callbacks),
    351         mTorchEnabled(false),
    352         mMetadata(NULL),
    353         mStreaming(false) {
    354 }
    355 
    356 CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
    357     disconnectCameraDevice();
    358     if (mMetadata) {
    359         delete mMetadata;
    360     }
    361 
    362     mSurface.clear();
    363     mSurfaceTexture.clear();
    364     mProducer.clear();
    365     mConsumer.clear();
    366 
    367     if (mTorchEnabled) {
    368         if (mCallbacks) {
    369             ALOGV("%s: notify the framework that torch was turned off",
    370                     __FUNCTION__);
    371             mCallbacks->torch_mode_status_change(mCallbacks,
    372                     mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
    373         }
    374     }
    375 }
    376 
    377 status_t CameraDeviceClientFlashControl::initializeSurface(
    378         sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
    379     status_t res;
    380     BufferQueue::createBufferQueue(&mProducer, &mConsumer);
    381 
    382     mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
    383             true, true);
    384     if (mSurfaceTexture == NULL) {
    385         return NO_MEMORY;
    386     }
    387 
    388     int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
    389     res = mSurfaceTexture->setDefaultBufferSize(width, height);
    390     if (res) {
    391         return res;
    392     }
    393     res = mSurfaceTexture->setDefaultBufferFormat(format);
    394     if (res) {
    395         return res;
    396     }
    397 
    398     mSurface = new Surface(mProducer, /*useAsync*/ true);
    399     if (mSurface == NULL) {
    400         return NO_MEMORY;
    401     }
    402     res = device->createStream(mSurface, width, height, format,
    403             HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
    404     if (res) {
    405         return res;
    406     }
    407 
    408     res = device->configureStreams();
    409     if (res) {
    410         return res;
    411     }
    412 
    413     return res;
    414 }
    415 
    416 status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
    417         const camera_info& info, int32_t *width, int32_t *height) {
    418     if (!width || !height) {
    419         return BAD_VALUE;
    420     }
    421 
    422     int32_t w = INT32_MAX;
    423     int32_t h = 1;
    424 
    425     CameraMetadata metadata;
    426     metadata = info.static_camera_characteristics;
    427     camera_metadata_entry streamConfigs =
    428             metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
    429     for (size_t i = 0; i < streamConfigs.count; i += 4) {
    430         int32_t fmt = streamConfigs.data.i32[i];
    431         if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
    432             int32_t ww = streamConfigs.data.i32[i + 1];
    433             int32_t hh = streamConfigs.data.i32[i + 2];
    434 
    435             if (w * h > ww * hh) {
    436                 w = ww;
    437                 h = hh;
    438             }
    439         }
    440     }
    441 
    442     // if stream configuration is not found, try available processed sizes.
    443     if (streamConfigs.count == 0) {
    444         camera_metadata_entry availableProcessedSizes =
    445             metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
    446         for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
    447             int32_t ww = availableProcessedSizes.data.i32[i];
    448             int32_t hh = availableProcessedSizes.data.i32[i + 1];
    449             if (w * h > ww * hh) {
    450                 w = ww;
    451                 h = hh;
    452             }
    453         }
    454     }
    455 
    456     if (w == INT32_MAX) {
    457         return NAME_NOT_FOUND;
    458     }
    459 
    460     *width = w;
    461     *height = h;
    462 
    463     return OK;
    464 }
    465 
    466 status_t CameraDeviceClientFlashControl::connectCameraDevice(
    467         const String8& cameraId) {
    468     camera_info info;
    469     status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
    470     if (res != 0) {
    471         ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
    472                 cameraId.string());
    473         return res;
    474     }
    475 
    476     sp<CameraDeviceBase> device =
    477             CameraDeviceFactory::createDevice(atoi(cameraId.string()));
    478     if (device == NULL) {
    479         return NO_MEMORY;
    480     }
    481 
    482     res = device->initialize(mCameraModule);
    483     if (res) {
    484         return res;
    485     }
    486 
    487     int32_t width, height;
    488     res = getSmallestSurfaceSize(info, &width, &height);
    489     if (res) {
    490         return res;
    491     }
    492     res = initializeSurface(device, width, height);
    493     if (res) {
    494         return res;
    495     }
    496 
    497     mCameraId = cameraId;
    498     mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
    499     mDevice = device;
    500 
    501     return OK;
    502 }
    503 
    504 status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
    505     if (mDevice != NULL) {
    506         mDevice->disconnect();
    507         mDevice.clear();
    508     }
    509 
    510     return OK;
    511 }
    512 
    513 
    514 
    515 status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
    516         bool *hasFlash) {
    517     ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
    518             cameraId.string());
    519 
    520     Mutex::Autolock l(mLock);
    521     return hasFlashUnitLocked(cameraId, hasFlash);
    522 
    523 }
    524 
    525 status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
    526         const String8& cameraId, bool *hasFlash) {
    527     if (!hasFlash) {
    528         return BAD_VALUE;
    529     }
    530 
    531     camera_info info;
    532     status_t res = mCameraModule->getCameraInfo(
    533             atoi(cameraId.string()), &info);
    534     if (res != 0) {
    535         ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
    536                 cameraId.string());
    537         return res;
    538     }
    539 
    540     CameraMetadata metadata;
    541     metadata = info.static_camera_characteristics;
    542     camera_metadata_entry flashAvailable =
    543             metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
    544     if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
    545         *hasFlash = true;
    546     }
    547 
    548     return OK;
    549 }
    550 
    551 status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
    552     status_t res;
    553 
    554     if (mMetadata == NULL) {
    555         mMetadata = new CameraMetadata();
    556         if (mMetadata == NULL) {
    557             return NO_MEMORY;
    558         }
    559         res = mDevice->createDefaultRequest(
    560                 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
    561         if (res) {
    562             return res;
    563         }
    564     }
    565 
    566     uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
    567     mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
    568     mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
    569 
    570     uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
    571     mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
    572 
    573     int32_t requestId = 0;
    574     mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
    575 
    576     if (mStreaming) {
    577         res = mDevice->setStreamingRequest(*mMetadata);
    578     } else {
    579         res = mDevice->capture(*mMetadata);
    580     }
    581     return res;
    582 }
    583 
    584 
    585 
    586 
    587 status_t CameraDeviceClientFlashControl::setTorchMode(
    588         const String8& cameraId, bool enabled) {
    589     bool hasFlash = false;
    590 
    591     Mutex::Autolock l(mLock);
    592     status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
    593 
    594     // pre-check
    595     if (enabled) {
    596         // invalid camera?
    597         if (res) {
    598             return -EINVAL;
    599         }
    600         // no flash unit?
    601         if (!hasFlash) {
    602             return -ENOSYS;
    603         }
    604         // already opened for a different device?
    605         if (mDevice != NULL && cameraId != mCameraId) {
    606             return BAD_INDEX;
    607         }
    608     } else if (mDevice == NULL || cameraId != mCameraId) {
    609         // disabling the torch mode of an un-opened or different device.
    610         return OK;
    611     } else {
    612         // disabling the torch mode of currently opened device
    613         disconnectCameraDevice();
    614         mTorchEnabled = false;
    615         mCallbacks->torch_mode_status_change(mCallbacks,
    616             cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
    617         return OK;
    618     }
    619 
    620     if (mDevice == NULL) {
    621         res = connectCameraDevice(cameraId);
    622         if (res) {
    623             return res;
    624         }
    625     }
    626 
    627     res = submitTorchEnabledRequest();
    628     if (res) {
    629         return res;
    630     }
    631 
    632     mTorchEnabled = true;
    633     mCallbacks->torch_mode_status_change(mCallbacks,
    634             cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
    635     return OK;
    636 }
    637 // CameraDeviceClientFlashControl implementation ends
    638 
    639 
    640 /////////////////////////////////////////////////////////////////////
    641 // CameraHardwareInterfaceFlashControl implementation begins
    642 // Flash control for camera module <= v2.3 and camera HAL v1
    643 /////////////////////////////////////////////////////////////////////
    644 CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
    645         CameraModule& cameraModule,
    646         const camera_module_callbacks_t& callbacks) :
    647         mCameraModule(&cameraModule),
    648         mCallbacks(&callbacks),
    649         mTorchEnabled(false) {
    650 
    651 }
    652 
    653 CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
    654     disconnectCameraDevice();
    655 
    656     mSurface.clear();
    657     mSurfaceTexture.clear();
    658     mProducer.clear();
    659     mConsumer.clear();
    660 
    661     if (mTorchEnabled) {
    662         if (mCallbacks) {
    663             ALOGV("%s: notify the framework that torch was turned off",
    664                     __FUNCTION__);
    665             mCallbacks->torch_mode_status_change(mCallbacks,
    666                     mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
    667         }
    668     }
    669 }
    670 
    671 status_t CameraHardwareInterfaceFlashControl::setTorchMode(
    672         const String8& cameraId, bool enabled) {
    673     Mutex::Autolock l(mLock);
    674 
    675     // pre-check
    676     status_t res;
    677     if (enabled) {
    678         bool hasFlash = false;
    679         res = hasFlashUnitLocked(cameraId, &hasFlash);
    680         // invalid camera?
    681         if (res) {
    682             // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
    683             // another camera device.
    684             return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
    685         }
    686         // no flash unit?
    687         if (!hasFlash) {
    688             return -ENOSYS;
    689         }
    690     } else if (mDevice == NULL || cameraId != mCameraId) {
    691         // disabling the torch mode of an un-opened or different device.
    692         return OK;
    693     } else {
    694         // disabling the torch mode of currently opened device
    695         disconnectCameraDevice();
    696         mTorchEnabled = false;
    697         mCallbacks->torch_mode_status_change(mCallbacks,
    698             cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
    699         return OK;
    700     }
    701 
    702     res = startPreviewAndTorch();
    703     if (res) {
    704         return res;
    705     }
    706 
    707     mTorchEnabled = true;
    708     mCallbacks->torch_mode_status_change(mCallbacks,
    709             cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
    710     return OK;
    711 }
    712 
    713 status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
    714         const String8& cameraId, bool *hasFlash) {
    715     Mutex::Autolock l(mLock);
    716     return hasFlashUnitLocked(cameraId, hasFlash);
    717 }
    718 
    719 status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
    720         const String8& cameraId, bool *hasFlash) {
    721     if (!hasFlash) {
    722         return BAD_VALUE;
    723     }
    724 
    725     status_t res;
    726     if (mDevice == NULL) {
    727         res = connectCameraDevice(cameraId);
    728         if (res) {
    729             return res;
    730         }
    731     }
    732 
    733     if (cameraId != mCameraId) {
    734         return BAD_INDEX;
    735     }
    736 
    737     const char *flashMode =
    738             mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
    739     if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
    740         *hasFlash = true;
    741     } else {
    742         *hasFlash = false;
    743     }
    744 
    745     return OK;
    746 }
    747 
    748 status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
    749     status_t res = OK;
    750     res = mDevice->startPreview();
    751     if (res) {
    752         ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
    753                 strerror(-res), res);
    754         return res;
    755     }
    756 
    757     mParameters.set(CameraParameters::KEY_FLASH_MODE,
    758             CameraParameters::FLASH_MODE_TORCH);
    759 
    760     return mDevice->setParameters(mParameters);
    761 }
    762 
    763 status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
    764         int32_t *width, int32_t *height) {
    765     if (!width || !height) {
    766         return BAD_VALUE;
    767     }
    768 
    769     int32_t w = INT32_MAX;
    770     int32_t h = 1;
    771     Vector<Size> sizes;
    772 
    773     mParameters.getSupportedPreviewSizes(sizes);
    774     for (size_t i = 0; i < sizes.size(); i++) {
    775         Size s = sizes[i];
    776         if (w * h > s.width * s.height) {
    777             w = s.width;
    778             h = s.height;
    779         }
    780     }
    781 
    782     if (w == INT32_MAX) {
    783         return NAME_NOT_FOUND;
    784     }
    785 
    786     *width = w;
    787     *height = h;
    788 
    789     return OK;
    790 }
    791 
    792 status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
    793         sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
    794     status_t res;
    795     BufferQueue::createBufferQueue(&mProducer, &mConsumer);
    796 
    797     mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
    798             true, true);
    799     if (mSurfaceTexture == NULL) {
    800         return NO_MEMORY;
    801     }
    802 
    803     int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
    804     res = mSurfaceTexture->setDefaultBufferSize(width, height);
    805     if (res) {
    806         return res;
    807     }
    808     res = mSurfaceTexture->setDefaultBufferFormat(format);
    809     if (res) {
    810         return res;
    811     }
    812 
    813     mSurface = new Surface(mProducer, /*useAsync*/ true);
    814     if (mSurface == NULL) {
    815         return NO_MEMORY;
    816     }
    817 
    818     res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
    819     if (res) {
    820         ALOGE("%s: Unable to connect to native window", __FUNCTION__);
    821         return res;
    822     }
    823 
    824     return device->setPreviewWindow(mSurface);
    825 }
    826 
    827 status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
    828         const String8& cameraId) {
    829     sp<CameraHardwareInterface> device =
    830             new CameraHardwareInterface(cameraId.string());
    831 
    832     status_t res = device->initialize(mCameraModule);
    833     if (res) {
    834         ALOGE("%s: initializing camera %s failed", __FUNCTION__,
    835                 cameraId.string());
    836         return res;
    837     }
    838 
    839     // need to set __get_memory in set_callbacks().
    840     device->setCallbacks(NULL, NULL, NULL, NULL);
    841 
    842     mParameters = device->getParameters();
    843 
    844     int32_t width, height;
    845     res = getSmallestSurfaceSize(&width, &height);
    846     if (res) {
    847         ALOGE("%s: failed to get smallest surface size for camera %s",
    848                 __FUNCTION__, cameraId.string());
    849         return res;
    850     }
    851 
    852     res = initializePreviewWindow(device, width, height);
    853     if (res) {
    854         ALOGE("%s: failed to initialize preview window for camera %s",
    855                 __FUNCTION__, cameraId.string());
    856         return res;
    857     }
    858 
    859     mCameraId = cameraId;
    860     mDevice = device;
    861     return OK;
    862 }
    863 
    864 status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
    865     if (mDevice == NULL) {
    866         return OK;
    867     }
    868 
    869     mParameters.set(CameraParameters::KEY_FLASH_MODE,
    870             CameraParameters::FLASH_MODE_OFF);
    871     mDevice->setParameters(mParameters);
    872     mDevice->stopPreview();
    873     status_t res = native_window_api_disconnect(mSurface.get(),
    874             NATIVE_WINDOW_API_CAMERA);
    875     if (res) {
    876         ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
    877                 __FUNCTION__, strerror(-res), res);
    878     }
    879     mDevice->setPreviewWindow(NULL);
    880     mDevice->release();
    881 
    882     return OK;
    883 }
    884 // CameraHardwareInterfaceFlashControl implementation ends
    885 
    886 }
    887