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