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