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 /////////////////////////////////////////////////////////////////////
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_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
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 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
findFlashUnits()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
hasFlashUnit(const String8 & cameraId)194 bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
195 status_t res;
196
197 Mutex::Autolock l(mLock);
198 return hasFlashUnitLocked(cameraId);
199 }
200
hasFlashUnitLocked(const String8 & cameraId)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
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 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
deviceClosed(const String8 & cameraId)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
~FlashControlBase()292 FlashControlBase::~FlashControlBase() {
293 }
294
295 /////////////////////////////////////////////////////////////////////
296 // ModuleFlashControl implementation begins
297 // Flash control for camera module v2.4 and above.
298 /////////////////////////////////////////////////////////////////////
ModuleFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)299 ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
300 const camera_module_callbacks_t& callbacks) :
301 mCameraModule(&cameraModule) {
302 }
303
~ModuleFlashControl()304 ModuleFlashControl::~ModuleFlashControl() {
305 }
306
hasFlashUnit(const String8 & cameraId,bool * hasFlash)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
setTorchMode(const String8 & cameraId,bool enabled)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 /////////////////////////////////////////////////////////////////////
CameraDeviceClientFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)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
~CameraDeviceClientFlashControl()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
initializeSurface(sp<CameraDeviceBase> & device,int32_t width,int32_t height)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
getSmallestSurfaceSize(const camera_info & info,int32_t * width,int32_t * height)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
connectCameraDevice(const String8 & cameraId)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
disconnectCameraDevice()504 status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
505 if (mDevice != NULL) {
506 mDevice->disconnect();
507 mDevice.clear();
508 }
509
510 return OK;
511 }
512
513
514
hasFlashUnit(const String8 & cameraId,bool * hasFlash)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
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash)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
submitTorchEnabledRequest()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
setTorchMode(const String8 & cameraId,bool enabled)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 /////////////////////////////////////////////////////////////////////
CameraHardwareInterfaceFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)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
~CameraHardwareInterfaceFlashControl()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
setTorchMode(const String8 & cameraId,bool enabled)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
hasFlashUnit(const String8 & cameraId,bool * hasFlash)713 status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
714 const String8& cameraId, bool *hasFlash) {
715 Mutex::Autolock l(mLock);
716 return hasFlashUnitLocked(cameraId, hasFlash);
717 }
718
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash)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
startPreviewAndTorch()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
getSmallestSurfaceSize(int32_t * width,int32_t * height)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
initializePreviewWindow(sp<CameraHardwareInterface> device,int32_t width,int32_t height)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
connectCameraDevice(const String8 & cameraId)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
disconnectCameraDevice()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