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