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