CameraFlashlight.cpp revision 676b21b30edbd74d7b9aae247961a1ffde1b8993
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
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_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
100status_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
156status_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
194bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
195    status_t res;
196
197    Mutex::Autolock l(mLock);
198    return hasFlashUnitLocked(cameraId);
199}
200
201bool 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
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        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
254status_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
292FlashControlBase::~FlashControlBase() {
293}
294
295/////////////////////////////////////////////////////////////////////
296// ModuleFlashControl implementation begins
297// Flash control for camera module v2.4 and above.
298/////////////////////////////////////////////////////////////////////
299ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
300        const camera_module_callbacks_t& callbacks) :
301    mCameraModule(&cameraModule) {
302}
303
304ModuleFlashControl::~ModuleFlashControl() {
305}
306
307status_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
333status_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/////////////////////////////////////////////////////////////////////
346CameraDeviceClientFlashControl::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
356CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
357    disconnectCameraDevice();
358    if (mMetadata) {
359        delete mMetadata;
360    }
361
362    mAnw.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
377status_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    mAnw = new Surface(mProducer, /*useAsync*/ true);
399    if (mAnw == NULL) {
400        return NO_MEMORY;
401    }
402    res = device->createStream(mAnw, 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
416status_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
466status_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
504status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
505    if (mDevice != NULL) {
506        mDevice->disconnect();
507        mDevice.clear();
508    }
509
510    return OK;
511}
512
513
514
515status_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
525status_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
551status_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
587status_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/////////////////////////////////////////////////////////////////////
644CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
645        CameraModule& cameraModule,
646        const camera_module_callbacks_t& callbacks) :
647        mCameraModule(&cameraModule),
648        mCallbacks(&callbacks),
649        mTorchEnabled(false) {
650
651}
652
653CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
654    disconnectCameraDevice();
655
656    mAnw.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
671status_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
713status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
714        const String8& cameraId, bool *hasFlash) {
715    Mutex::Autolock l(mLock);
716    return hasFlashUnitLocked(cameraId, hasFlash);
717}
718
719status_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
748status_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
763status_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
792status_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    mAnw = new Surface(mProducer, /*useAsync*/ true);
814    if (mAnw == NULL) {
815        return NO_MEMORY;
816    }
817
818    res = native_window_api_connect(mAnw.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(mAnw);
825}
826
827status_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
864status_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(mAnw.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