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 /////////////////////////////////////////////////////////////////////
CameraFlashlight(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)39 CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
40 const camera_module_callbacks_t& callbacks) :
41 mCameraModule(&cameraModule),
42 mCallbacks(&callbacks),
43 mFlashlightMapInitialized(false) {
44 }
45
~CameraFlashlight()46 CameraFlashlight::~CameraFlashlight() {
47 }
48
createFlashlightControl(const String8 & cameraId)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
setTorchMode(const String8 & cameraId,bool enabled)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
findFlashUnits()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
hasFlashUnit(const String8 & cameraId)195 bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
196 Mutex::Autolock l(mLock);
197 return hasFlashUnitLocked(cameraId);
198 }
199
hasFlashUnitLocked(const String8 & cameraId)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
prepareDeviceOpen(const String8 & cameraId)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
deviceClosed(const String8 & cameraId)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
~FlashControlBase()294 FlashControlBase::~FlashControlBase() {
295 }
296
297 /////////////////////////////////////////////////////////////////////
298 // ModuleFlashControl implementation begins
299 // Flash control for camera module v2.4 and above.
300 /////////////////////////////////////////////////////////////////////
ModuleFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)301 ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
302 const camera_module_callbacks_t& callbacks) :
303 mCameraModule(&cameraModule) {
304 (void) callbacks;
305 }
306
~ModuleFlashControl()307 ModuleFlashControl::~ModuleFlashControl() {
308 }
309
hasFlashUnit(const String8 & cameraId,bool * hasFlash)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
setTorchMode(const String8 & cameraId,bool enabled)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 /////////////////////////////////////////////////////////////////////
CameraDeviceClientFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)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
~CameraDeviceClientFlashControl()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
initializeSurface(sp<CameraDeviceBase> & device,int32_t width,int32_t height)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
getSmallestSurfaceSize(const camera_info & info,int32_t * width,int32_t * height)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
connectCameraDevice(const String8 & cameraId)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
disconnectCameraDevice()507 status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
508 if (mDevice != NULL) {
509 mDevice->disconnect();
510 mDevice.clear();
511 }
512
513 return OK;
514 }
515
516
517
hasFlashUnit(const String8 & cameraId,bool * hasFlash)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
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash)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
submitTorchEnabledRequest()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
setTorchMode(const String8 & cameraId,bool enabled)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 /////////////////////////////////////////////////////////////////////
CameraHardwareInterfaceFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)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
~CameraHardwareInterfaceFlashControl()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
setTorchMode(const String8 & cameraId,bool enabled)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
hasFlashUnit(const String8 & cameraId,bool * hasFlash)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
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash,bool keepDeviceOpen)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
startPreviewAndTorch()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
getSmallestSurfaceSize(int32_t * width,int32_t * height)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
initializePreviewWindow(sp<CameraHardwareInterface> device,int32_t width,int32_t height)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
connectCameraDevice(const String8 & cameraId)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
disconnectCameraDevice()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