• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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