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 "device3/Camera3Device.h"
     31 
     32 
     33 namespace android {
     34 
     35 using hardware::camera::common::V1_0::TorchModeStatus;
     36 
     37 /////////////////////////////////////////////////////////////////////
     38 // CameraFlashlight implementation begins
     39 // used by camera service to control flashflight.
     40 /////////////////////////////////////////////////////////////////////
     41 
     42 CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
     43         CameraProviderManager::StatusListener* callbacks) :
     44         mProviderManager(providerManager),
     45         mCallbacks(callbacks),
     46         mFlashlightMapInitialized(false) {
     47 }
     48 
     49 CameraFlashlight::~CameraFlashlight() {
     50 }
     51 
     52 status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
     53     ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
     54             cameraId.string());
     55     if (mFlashControl != NULL) {
     56         return INVALID_OPERATION;
     57     }
     58 
     59     if (mProviderManager->supportSetTorchMode(cameraId.string())) {
     60         mFlashControl = new ProviderFlashControl(mProviderManager);
     61     } else {
     62         // Only HAL1 devices do not support setTorchMode
     63         mFlashControl =
     64                 new CameraHardwareInterfaceFlashControl(mProviderManager, mCallbacks);
     65     }
     66 
     67     return OK;
     68 }
     69 
     70 status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
     71     if (!mFlashlightMapInitialized) {
     72         ALOGE("%s: findFlashUnits() must be called before this method.",
     73                __FUNCTION__);
     74         return NO_INIT;
     75     }
     76 
     77     ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
     78             cameraId.string(), enabled);
     79 
     80     status_t res = OK;
     81     Mutex::Autolock l(mLock);
     82 
     83     if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
     84         // This case is needed to avoid state corruption during the following call sequence:
     85         // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
     86         // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
     87         // CameraService::setTorchMode for camera ID 0 continues, calls
     88         //        CameraFlashlight::setTorchMode
     89 
     90         // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
     91         // to avoid other similar race conditions.
     92         ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
     93                 __FUNCTION__, cameraId.string());
     94         return -EBUSY;
     95     }
     96 
     97     if (mFlashControl == NULL) {
     98         res = createFlashlightControl(cameraId);
     99         if (res) {
    100             return res;
    101         }
    102         res =  mFlashControl->setTorchMode(cameraId, enabled);
    103         return res;
    104     }
    105 
    106     // if flash control already exists, turning on torch mode may fail if it's
    107     // tied to another camera device for module v2.3 and below.
    108     res = mFlashControl->setTorchMode(cameraId, enabled);
    109     if (res == BAD_INDEX) {
    110         // flash control is tied to another camera device, need to close it and
    111         // try again.
    112         mFlashControl.clear();
    113         res = createFlashlightControl(cameraId);
    114         if (res) {
    115             return res;
    116         }
    117         res = mFlashControl->setTorchMode(cameraId, enabled);
    118     }
    119 
    120     return res;
    121 }
    122 
    123 status_t CameraFlashlight::findFlashUnits() {
    124     Mutex::Autolock l(mLock);
    125     status_t res;
    126 
    127     std::vector<String8> cameraIds;
    128     std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
    129     int numberOfCameras = static_cast<int>(ids.size());
    130     cameraIds.resize(numberOfCameras);
    131     // No module, must be provider
    132     for (size_t i = 0; i < cameraIds.size(); i++) {
    133         cameraIds[i] = String8(ids[i].c_str());
    134     }
    135 
    136     mFlashControl.clear();
    137 
    138     for (auto &id : cameraIds) {
    139         ssize_t index = mHasFlashlightMap.indexOfKey(id);
    140         if (0 <= index) {
    141             continue;
    142         }
    143 
    144         bool hasFlash = false;
    145         res = createFlashlightControl(id);
    146         if (res) {
    147             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
    148                     id.string());
    149         } else {
    150             res = mFlashControl->hasFlashUnit(id, &hasFlash);
    151             if (res == -EUSERS || res == -EBUSY) {
    152                 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
    153                         "camera devices may be opened", __FUNCTION__,
    154                         id.string());
    155                 return res;
    156             } else if (res) {
    157                 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
    158                         " (%d)", __FUNCTION__, id.string(), strerror(-res),
    159                         res);
    160             }
    161 
    162             mFlashControl.clear();
    163         }
    164         mHasFlashlightMap.add(id, hasFlash);
    165     }
    166 
    167     mFlashlightMapInitialized = true;
    168     return OK;
    169 }
    170 
    171 bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
    172     Mutex::Autolock l(mLock);
    173     return hasFlashUnitLocked(cameraId);
    174 }
    175 
    176 bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
    177     if (!mFlashlightMapInitialized) {
    178         ALOGE("%s: findFlashUnits() must be called before this method.",
    179                __FUNCTION__);
    180         return false;
    181     }
    182 
    183     ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
    184     if (index == NAME_NOT_FOUND) {
    185         // Might be external camera
    186         ALOGW("%s: camera %s not present when findFlashUnits() was called",
    187                 __FUNCTION__, cameraId.string());
    188         return false;
    189     }
    190 
    191     return mHasFlashlightMap.valueAt(index);
    192 }
    193 
    194 bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
    195     bool backwardCompatibleMode = false;
    196     if (mProviderManager != nullptr &&
    197             !mProviderManager->supportSetTorchMode(cameraId.string())) {
    198         backwardCompatibleMode = true;
    199     }
    200     return backwardCompatibleMode;
    201 }
    202 
    203 status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
    204     ALOGV("%s: prepare for device open", __FUNCTION__);
    205 
    206     Mutex::Autolock l(mLock);
    207     if (!mFlashlightMapInitialized) {
    208         ALOGE("%s: findFlashUnits() must be called before this method.",
    209                __FUNCTION__);
    210         return NO_INIT;
    211     }
    212 
    213     if (isBackwardCompatibleMode(cameraId)) {
    214         // framework is going to open a camera device, all flash light control
    215         // should be closed for backward compatible support.
    216         mFlashControl.clear();
    217 
    218         if (mOpenedCameraIds.size() == 0) {
    219             // notify torch unavailable for all cameras with a flash
    220             std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
    221             int numCameras = static_cast<int>(ids.size());
    222             for (int i = 0; i < numCameras; i++) {
    223                 String8 id8(ids[i].c_str());
    224                 if (hasFlashUnitLocked(id8)) {
    225                     mCallbacks->onTorchStatusChanged(
    226                             id8, TorchModeStatus::NOT_AVAILABLE);
    227                 }
    228             }
    229         }
    230 
    231         // close flash control that may be opened by calling hasFlashUnitLocked.
    232         mFlashControl.clear();
    233     }
    234 
    235     if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
    236         mOpenedCameraIds.add(cameraId);
    237     }
    238 
    239     return OK;
    240 }
    241 
    242 status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
    243     ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
    244 
    245     Mutex::Autolock l(mLock);
    246     if (!mFlashlightMapInitialized) {
    247         ALOGE("%s: findFlashUnits() must be called before this method.",
    248                __FUNCTION__);
    249         return NO_INIT;
    250     }
    251 
    252     ssize_t index = mOpenedCameraIds.indexOf(cameraId);
    253     if (index == NAME_NOT_FOUND) {
    254         ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
    255                 cameraId.string());
    256     } else {
    257         mOpenedCameraIds.removeAt(index);
    258     }
    259 
    260     // Cannot do anything until all cameras are closed.
    261     if (mOpenedCameraIds.size() != 0)
    262         return OK;
    263 
    264     if (isBackwardCompatibleMode(cameraId)) {
    265         // notify torch available for all cameras with a flash
    266         std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
    267         int numCameras = static_cast<int>(ids.size());
    268         for (int i = 0; i < numCameras; i++) {
    269             String8 id8(ids[i].c_str());
    270             if (hasFlashUnitLocked(id8)) {
    271                 mCallbacks->onTorchStatusChanged(
    272                         id8, TorchModeStatus::AVAILABLE_OFF);
    273             }
    274         }
    275     }
    276 
    277     return OK;
    278 }
    279 // CameraFlashlight implementation ends
    280 
    281 
    282 FlashControlBase::~FlashControlBase() {
    283 }
    284 
    285 /////////////////////////////////////////////////////////////////////
    286 // ModuleFlashControl implementation begins
    287 // Flash control for camera module v2.4 and above.
    288 /////////////////////////////////////////////////////////////////////
    289 ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
    290         mProviderManager(providerManager) {
    291 }
    292 
    293 ProviderFlashControl::~ProviderFlashControl() {
    294 }
    295 
    296 status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
    297     if (!hasFlash) {
    298         return BAD_VALUE;
    299     }
    300     *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
    301     return OK;
    302 }
    303 
    304 status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
    305     ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
    306             cameraId.string(), enabled);
    307 
    308     return mProviderManager->setTorchMode(cameraId.string(), enabled);
    309 }
    310 // ProviderFlashControl implementation ends
    311 
    312 /////////////////////////////////////////////////////////////////////
    313 // CameraHardwareInterfaceFlashControl implementation begins
    314 // Flash control for camera module <= v2.3 and camera HAL v1
    315 /////////////////////////////////////////////////////////////////////
    316 
    317 CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
    318         sp<CameraProviderManager> manager,
    319         CameraProviderManager::StatusListener* callbacks) :
    320         mProviderManager(manager),
    321         mCallbacks(callbacks),
    322         mTorchEnabled(false) {
    323 }
    324 
    325 CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
    326     disconnectCameraDevice();
    327 
    328     mSurface.clear();
    329     mSurfaceTexture.clear();
    330     mProducer.clear();
    331     mConsumer.clear();
    332 
    333     if (mTorchEnabled) {
    334         if (mCallbacks) {
    335             ALOGV("%s: notify the framework that torch was turned off",
    336                     __FUNCTION__);
    337             mCallbacks->onTorchStatusChanged(mCameraId, TorchModeStatus::AVAILABLE_OFF);
    338         }
    339     }
    340 }
    341 
    342 status_t CameraHardwareInterfaceFlashControl::setTorchMode(
    343         const String8& cameraId, bool enabled) {
    344     Mutex::Autolock l(mLock);
    345 
    346     // pre-check
    347     status_t res;
    348     if (enabled) {
    349         bool hasFlash = false;
    350         // Check if it has a flash unit and leave camera device open.
    351         res = hasFlashUnitLocked(cameraId, &hasFlash, /*keepDeviceOpen*/true);
    352         // invalid camera?
    353         if (res) {
    354             // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
    355             // another camera device.
    356             return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
    357         }
    358         // no flash unit?
    359         if (!hasFlash) {
    360             // Disconnect camera device if it has no flash.
    361             disconnectCameraDevice();
    362             return -ENOSYS;
    363         }
    364     } else if (mDevice == NULL || cameraId != mCameraId) {
    365         // disabling the torch mode of an un-opened or different device.
    366         return OK;
    367     } else {
    368         // disabling the torch mode of currently opened device
    369         disconnectCameraDevice();
    370         mTorchEnabled = false;
    371         mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_OFF);
    372         return OK;
    373     }
    374 
    375     res = startPreviewAndTorch();
    376     if (res) {
    377         return res;
    378     }
    379 
    380     mTorchEnabled = true;
    381     mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_ON);
    382     return OK;
    383 }
    384 
    385 status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
    386         const String8& cameraId, bool *hasFlash) {
    387     Mutex::Autolock l(mLock);
    388     // Close device after checking if it has a flash unit.
    389     return hasFlashUnitLocked(cameraId, hasFlash, /*keepDeviceOpen*/false);
    390 }
    391 
    392 status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
    393         const String8& cameraId, bool *hasFlash, bool keepDeviceOpen) {
    394     bool closeCameraDevice = false;
    395 
    396     if (!hasFlash) {
    397         return BAD_VALUE;
    398     }
    399 
    400     status_t res;
    401     if (mDevice == NULL) {
    402         // Connect to camera device to query if it has a flash unit.
    403         res = connectCameraDevice(cameraId);
    404         if (res) {
    405             return res;
    406         }
    407         // Close camera device only when it is just opened and the caller doesn't want to keep
    408         // the camera device open.
    409         closeCameraDevice = !keepDeviceOpen;
    410     }
    411 
    412     if (cameraId != mCameraId) {
    413         return BAD_INDEX;
    414     }
    415 
    416     const char *flashMode =
    417             mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
    418     if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
    419         *hasFlash = true;
    420     } else {
    421         *hasFlash = false;
    422     }
    423 
    424     if (closeCameraDevice) {
    425         res = disconnectCameraDevice();
    426         if (res != OK) {
    427             ALOGE("%s: Failed to disconnect camera device. %s (%d)", __FUNCTION__,
    428                     strerror(-res), res);
    429             return res;
    430         }
    431     }
    432 
    433     return OK;
    434 }
    435 
    436 status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
    437     status_t res = OK;
    438     res = mDevice->startPreview();
    439     if (res) {
    440         ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
    441                 strerror(-res), res);
    442         return res;
    443     }
    444 
    445     mParameters.set(CameraParameters::KEY_FLASH_MODE,
    446             CameraParameters::FLASH_MODE_TORCH);
    447 
    448     return mDevice->setParameters(mParameters);
    449 }
    450 
    451 status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
    452         int32_t *width, int32_t *height) {
    453     if (!width || !height) {
    454         return BAD_VALUE;
    455     }
    456 
    457     int32_t w = INT32_MAX;
    458     int32_t h = 1;
    459     Vector<Size> sizes;
    460 
    461     mParameters.getSupportedPreviewSizes(sizes);
    462     for (size_t i = 0; i < sizes.size(); i++) {
    463         Size s = sizes[i];
    464         if (w * h > s.width * s.height) {
    465             w = s.width;
    466             h = s.height;
    467         }
    468     }
    469 
    470     if (w == INT32_MAX) {
    471         return NAME_NOT_FOUND;
    472     }
    473 
    474     *width = w;
    475     *height = h;
    476 
    477     return OK;
    478 }
    479 
    480 status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
    481         const sp<CameraHardwareInterface>& device, int32_t width, int32_t height) {
    482     status_t res;
    483     BufferQueue::createBufferQueue(&mProducer, &mConsumer);
    484 
    485     mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
    486             true, true);
    487     if (mSurfaceTexture == NULL) {
    488         return NO_MEMORY;
    489     }
    490 
    491     int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
    492     res = mSurfaceTexture->setDefaultBufferSize(width, height);
    493     if (res) {
    494         return res;
    495     }
    496     res = mSurfaceTexture->setDefaultBufferFormat(format);
    497     if (res) {
    498         return res;
    499     }
    500 
    501     mSurface = new Surface(mProducer, /*useAsync*/ true);
    502     if (mSurface == NULL) {
    503         return NO_MEMORY;
    504     }
    505 
    506     res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
    507     if (res) {
    508         ALOGE("%s: Unable to connect to native window", __FUNCTION__);
    509         return res;
    510     }
    511 
    512     return device->setPreviewWindow(mSurface);
    513 }
    514 
    515 status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
    516         const String8& cameraId) {
    517     sp<CameraHardwareInterface> device =
    518             new CameraHardwareInterface(cameraId.string());
    519 
    520     status_t res = device->initialize(mProviderManager);
    521     if (res) {
    522         ALOGE("%s: initializing camera %s failed", __FUNCTION__,
    523                 cameraId.string());
    524         return res;
    525     }
    526 
    527     // need to set __get_memory in set_callbacks().
    528     device->setCallbacks(NULL, NULL, NULL, NULL, NULL);
    529 
    530     mParameters = device->getParameters();
    531 
    532     int32_t width, height;
    533     res = getSmallestSurfaceSize(&width, &height);
    534     if (res) {
    535         ALOGE("%s: failed to get smallest surface size for camera %s",
    536                 __FUNCTION__, cameraId.string());
    537         return res;
    538     }
    539 
    540     res = initializePreviewWindow(device, width, height);
    541     if (res) {
    542         ALOGE("%s: failed to initialize preview window for camera %s",
    543                 __FUNCTION__, cameraId.string());
    544         return res;
    545     }
    546 
    547     mCameraId = cameraId;
    548     mDevice = device;
    549     return OK;
    550 }
    551 
    552 status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
    553     if (mDevice == NULL) {
    554         return OK;
    555     }
    556 
    557     if (mParameters.get(CameraParameters::KEY_FLASH_MODE)) {
    558         // There is a flash, turn if off.
    559         // (If there isn't one, leave the parameter null)
    560         mParameters.set(CameraParameters::KEY_FLASH_MODE,
    561                 CameraParameters::FLASH_MODE_OFF);
    562         mDevice->setParameters(mParameters);
    563     }
    564     mDevice->stopPreview();
    565     status_t res = native_window_api_disconnect(mSurface.get(),
    566             NATIVE_WINDOW_API_CAMERA);
    567     if (res) {
    568         ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
    569                 __FUNCTION__, strerror(-res), res);
    570     }
    571     mDevice->setPreviewWindow(NULL);
    572     mDevice->release();
    573     mDevice = NULL;
    574 
    575     return OK;
    576 }
    577 // CameraHardwareInterfaceFlashControl implementation ends
    578 
    579 }
    580