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 __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 status_t res;
197
198 Mutex::Autolock l(mLock);
199 return hasFlashUnitLocked(cameraId);
200 }
201
hasFlashUnitLocked(const String8 & cameraId)202 bool 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
prepareDeviceOpen(const String8 & cameraId)219 status_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
deviceClosed(const String8 & cameraId)257 status_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
~FlashControlBase()296 FlashControlBase::~FlashControlBase() {
297 }
298
299 /////////////////////////////////////////////////////////////////////
300 // ModuleFlashControl implementation begins
301 // Flash control for camera module v2.4 and above.
302 /////////////////////////////////////////////////////////////////////
ModuleFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)303 ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
304 const camera_module_callbacks_t& callbacks) :
305 mCameraModule(&cameraModule) {
306 }
307
~ModuleFlashControl()308 ModuleFlashControl::~ModuleFlashControl() {
309 }
310
hasFlashUnit(const String8 & cameraId,bool * hasFlash)311 status_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
setTorchMode(const String8 & cameraId,bool enabled)337 status_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 /////////////////////////////////////////////////////////////////////
CameraDeviceClientFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)350 CameraDeviceClientFlashControl::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
~CameraDeviceClientFlashControl()360 CameraDeviceClientFlashControl::~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
initializeSurface(sp<CameraDeviceBase> & device,int32_t width,int32_t height)381 status_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
getSmallestSurfaceSize(const camera_info & info,int32_t * width,int32_t * height)420 status_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
connectCameraDevice(const String8 & cameraId)470 status_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
disconnectCameraDevice()508 status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
509 if (mDevice != NULL) {
510 mDevice->disconnect();
511 mDevice.clear();
512 }
513
514 return OK;
515 }
516
517
518
hasFlashUnit(const String8 & cameraId,bool * hasFlash)519 status_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
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash)529 status_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
submitTorchEnabledRequest()555 status_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
setTorchMode(const String8 & cameraId,bool enabled)591 status_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 /////////////////////////////////////////////////////////////////////
CameraHardwareInterfaceFlashControl(CameraModule & cameraModule,const camera_module_callbacks_t & callbacks)648 CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
649 CameraModule& cameraModule,
650 const camera_module_callbacks_t& callbacks) :
651 mCameraModule(&cameraModule),
652 mCallbacks(&callbacks),
653 mTorchEnabled(false) {
654
655 }
656
~CameraHardwareInterfaceFlashControl()657 CameraHardwareInterfaceFlashControl::~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
setTorchMode(const String8 & cameraId,bool enabled)675 status_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
hasFlashUnit(const String8 & cameraId,bool * hasFlash)717 status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
718 const String8& cameraId, bool *hasFlash) {
719 Mutex::Autolock l(mLock);
720 return hasFlashUnitLocked(cameraId, hasFlash);
721 }
722
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash)723 status_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
startPreviewAndTorch()752 status_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
getSmallestSurfaceSize(int32_t * width,int32_t * height)767 status_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
initializePreviewWindow(sp<CameraHardwareInterface> device,int32_t width,int32_t height)796 status_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
connectCameraDevice(const String8 & cameraId)831 status_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
disconnectCameraDevice()868 status_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