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