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