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