CameraFlashlight.cpp revision 3d1c478fc34824db4e68d50c12f283d6b55c272e
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
33namespace android {
34
35/////////////////////////////////////////////////////////////////////
36// CameraFlashlight implementation begins
37// used by camera service to control flashflight.
38/////////////////////////////////////////////////////////////////////
39CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
40        const camera_module_callbacks_t& callbacks) :
41        mCameraModule(&cameraModule),
42        mCallbacks(&callbacks),
43        mFlashlightMapInitialized(false) {
44}
45
46CameraFlashlight::~CameraFlashlight() {
47}
48
49status_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
100status_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
157status_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
195bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
196    Mutex::Autolock l(mLock);
197    return hasFlashUnitLocked(cameraId);
198}
199
200bool 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
217status_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
255status_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
294FlashControlBase::~FlashControlBase() {
295}
296
297/////////////////////////////////////////////////////////////////////
298// ModuleFlashControl implementation begins
299// Flash control for camera module v2.4 and above.
300/////////////////////////////////////////////////////////////////////
301ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
302        const camera_module_callbacks_t& callbacks) :
303        mCameraModule(&cameraModule) {
304    (void) callbacks;
305}
306
307ModuleFlashControl::~ModuleFlashControl() {
308}
309
310status_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
336status_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/////////////////////////////////////////////////////////////////////
349CameraDeviceClientFlashControl::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
359CameraDeviceClientFlashControl::~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
380status_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
419status_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
469status_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
507status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
508    if (mDevice != NULL) {
509        mDevice->disconnect();
510        mDevice.clear();
511    }
512
513    return OK;
514}
515
516
517
518status_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
528status_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
554status_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
590status_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/////////////////////////////////////////////////////////////////////
647CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
648        CameraModule& cameraModule,
649        const camera_module_callbacks_t& callbacks) :
650        mCameraModule(&cameraModule),
651        mCallbacks(&callbacks),
652        mTorchEnabled(false) {
653
654}
655
656CameraHardwareInterfaceFlashControl::~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
674status_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
719status_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
726status_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
770status_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
785status_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
814status_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
849status_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
886status_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