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