CameraFlashlight.cpp revision cc776718c0be7c31fe5ab4fc1446d377be60369f
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->getRawModule()->module_api_version >=
59            CAMERA_MODULE_API_VERSION_2_4) {
60        mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
61        if (mFlashControl == NULL) {
62            ALOGV("%s: cannot create flash control for module api v2.4+",
63                     __FUNCTION__);
64            return NO_MEMORY;
65        }
66    } else {
67        uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
68
69        if (mCameraModule->getRawModule()->module_api_version >=
70                CAMERA_MODULE_API_VERSION_2_0) {
71            camera_info info;
72            res = mCameraModule->getCameraInfo(
73                    atoi(String8(cameraId).string()), &info);
74            if (res) {
75                ALOGE("%s: failed to get camera info for camera %s",
76                        __FUNCTION__, cameraId.string());
77                return res;
78            }
79            deviceVersion = info.device_version;
80        }
81
82        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
83            CameraDeviceClientFlashControl *flashControl =
84                    new CameraDeviceClientFlashControl(*mCameraModule,
85                                                       *mCallbacks);
86            if (!flashControl) {
87                return NO_MEMORY;
88            }
89
90            mFlashControl = flashControl;
91        } else {
92            mFlashControl =
93                    new CameraHardwareInterfaceFlashControl(*mCameraModule,
94                                                            *mCallbacks);
95        }
96    }
97
98    return OK;
99}
100
101status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
102    if (!mFlashlightMapInitialized) {
103        ALOGE("%s: findFlashUnits() must be called before this method.");
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    status_t res;
197
198    Mutex::Autolock l(mLock);
199    return hasFlashUnitLocked(cameraId);
200}
201
202bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
203    if (!mFlashlightMapInitialized) {
204        ALOGE("%s: findFlashUnits() must be called before this method.");
205        return false;
206    }
207
208    ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
209    if (index == NAME_NOT_FOUND) {
210        ALOGE("%s: camera %s not present when findFlashUnits() was called",
211                __FUNCTION__, cameraId.string());
212        return false;
213    }
214
215    return mHasFlashlightMap.valueAt(index);
216}
217
218status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
219    ALOGV("%s: prepare for device open", __FUNCTION__);
220
221    Mutex::Autolock l(mLock);
222    if (!mFlashlightMapInitialized) {
223        ALOGE("%s: findFlashUnits() must be called before this method.");
224        return NO_INIT;
225    }
226
227    if (mCameraModule->getRawModule()->module_api_version <
228            CAMERA_MODULE_API_VERSION_2_4) {
229        // framework is going to open a camera device, all flash light control
230        // should be closed for backward compatible support.
231        mFlashControl.clear();
232
233        if (mOpenedCameraIds.size() == 0) {
234            // notify torch unavailable for all cameras with a flash
235            int numCameras = mCameraModule->getNumberOfCameras();
236            for (int i = 0; i < numCameras; i++) {
237                if (hasFlashUnitLocked(String8::format("%d", i))) {
238                    mCallbacks->torch_mode_status_change(mCallbacks,
239                            String8::format("%d", i).string(),
240                            TORCH_MODE_STATUS_NOT_AVAILABLE);
241                }
242            }
243        }
244
245        // close flash control that may be opened by calling hasFlashUnitLocked.
246        mFlashControl.clear();
247    }
248
249    if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
250        mOpenedCameraIds.add(cameraId);
251    }
252
253    return OK;
254}
255
256status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
257    ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
258
259    Mutex::Autolock l(mLock);
260    if (!mFlashlightMapInitialized) {
261        ALOGE("%s: findFlashUnits() must be called before this method.");
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->getRawModule()->module_api_version <
278            CAMERA_MODULE_API_VERSION_2_4) {
279        // notify torch available for all cameras with a flash
280        int numCameras = mCameraModule->getNumberOfCameras();
281        for (int i = 0; i < numCameras; i++) {
282            if (hasFlashUnitLocked(String8::format("%d", i))) {
283                mCallbacks->torch_mode_status_change(mCallbacks,
284                        String8::format("%d", i).string(),
285                        TORCH_MODE_STATUS_AVAILABLE_OFF);
286            }
287        }
288    }
289
290    return OK;
291}
292// CameraFlashlight implementation ends
293
294
295FlashControlBase::~FlashControlBase() {
296}
297
298/////////////////////////////////////////////////////////////////////
299// ModuleFlashControl implementation begins
300// Flash control for camera module v2.4 and above.
301/////////////////////////////////////////////////////////////////////
302ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
303        const camera_module_callbacks_t& callbacks) :
304    mCameraModule(&cameraModule) {
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    mAnw.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    mAnw = new Surface(mProducer, /*useAsync*/ true);
402    if (mAnw == NULL) {
403        return NO_MEMORY;
404    }
405    res = device->createStream(mAnw, width, height, format, &mStreamId);
406    if (res) {
407        return res;
408    }
409
410    res = device->configureStreams();
411    if (res) {
412        return res;
413    }
414
415    return res;
416}
417
418status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
419        const camera_info& info, int32_t *width, int32_t *height) {
420    if (!width || !height) {
421        return BAD_VALUE;
422    }
423
424    int32_t w = INT32_MAX;
425    int32_t h = 1;
426
427    CameraMetadata metadata;
428    metadata = info.static_camera_characteristics;
429    camera_metadata_entry streamConfigs =
430            metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
431    for (size_t i = 0; i < streamConfigs.count; i += 4) {
432        int32_t fmt = streamConfigs.data.i32[i];
433        if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
434            int32_t ww = streamConfigs.data.i32[i + 1];
435            int32_t hh = streamConfigs.data.i32[i + 2];
436
437            if (w * h > ww * hh) {
438                w = ww;
439                h = hh;
440            }
441        }
442    }
443
444    // if stream configuration is not found, try available processed sizes.
445    if (streamConfigs.count == 0) {
446        camera_metadata_entry availableProcessedSizes =
447            metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
448        for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
449            int32_t ww = availableProcessedSizes.data.i32[i];
450            int32_t hh = availableProcessedSizes.data.i32[i + 1];
451            if (w * h > ww * hh) {
452                w = ww;
453                h = hh;
454            }
455        }
456    }
457
458    if (w == INT32_MAX) {
459        return NAME_NOT_FOUND;
460    }
461
462    *width = w;
463    *height = h;
464
465    return OK;
466}
467
468status_t CameraDeviceClientFlashControl::connectCameraDevice(
469        const String8& cameraId) {
470    camera_info info;
471    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
472    if (res != 0) {
473        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
474                cameraId.string());
475        return res;
476    }
477
478    sp<CameraDeviceBase> device =
479            CameraDeviceFactory::createDevice(atoi(cameraId.string()));
480    if (device == NULL) {
481        return NO_MEMORY;
482    }
483
484    res = device->initialize(mCameraModule);
485    if (res) {
486        return res;
487    }
488
489    int32_t width, height;
490    res = getSmallestSurfaceSize(info, &width, &height);
491    if (res) {
492        return res;
493    }
494    res = initializeSurface(device, width, height);
495    if (res) {
496        return res;
497    }
498
499    mCameraId = cameraId;
500    mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
501    mDevice = device;
502
503    return OK;
504}
505
506status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
507    if (mDevice != NULL) {
508        mDevice->disconnect();
509        mDevice.clear();
510    }
511
512    return OK;
513}
514
515
516
517status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
518        bool *hasFlash) {
519    ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
520            cameraId.string());
521
522    Mutex::Autolock l(mLock);
523    return hasFlashUnitLocked(cameraId, hasFlash);
524
525}
526
527status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
528        const String8& cameraId, bool *hasFlash) {
529    if (!hasFlash) {
530        return BAD_VALUE;
531    }
532
533    camera_info info;
534    status_t res = mCameraModule->getCameraInfo(
535            atoi(cameraId.string()), &info);
536    if (res != 0) {
537        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
538                cameraId.string());
539        return res;
540    }
541
542    CameraMetadata metadata;
543    metadata = info.static_camera_characteristics;
544    camera_metadata_entry flashAvailable =
545            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
546    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
547        *hasFlash = true;
548    }
549
550    return OK;
551}
552
553status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
554    status_t res;
555
556    if (mMetadata == NULL) {
557        mMetadata = new CameraMetadata();
558        if (mMetadata == NULL) {
559            return NO_MEMORY;
560        }
561        res = mDevice->createDefaultRequest(
562                CAMERA3_TEMPLATE_PREVIEW, mMetadata);
563        if (res) {
564            return res;
565        }
566    }
567
568    uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
569    mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
570    mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
571
572    uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
573    mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
574
575    int32_t requestId = 0;
576    mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
577
578    if (mStreaming) {
579        res = mDevice->setStreamingRequest(*mMetadata);
580    } else {
581        res = mDevice->capture(*mMetadata);
582    }
583    return res;
584}
585
586
587
588
589status_t CameraDeviceClientFlashControl::setTorchMode(
590        const String8& cameraId, bool enabled) {
591    bool hasFlash = false;
592
593    Mutex::Autolock l(mLock);
594    status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
595
596    // pre-check
597    if (enabled) {
598        // invalid camera?
599        if (res) {
600            return -EINVAL;
601        }
602        // no flash unit?
603        if (!hasFlash) {
604            return -ENOSYS;
605        }
606        // already opened for a different device?
607        if (mDevice != NULL && cameraId != mCameraId) {
608            return BAD_INDEX;
609        }
610    } else if (mDevice == NULL || cameraId != mCameraId) {
611        // disabling the torch mode of an un-opened or different device.
612        return OK;
613    } else {
614        // disabling the torch mode of currently opened device
615        disconnectCameraDevice();
616        mTorchEnabled = false;
617        mCallbacks->torch_mode_status_change(mCallbacks,
618            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
619        return OK;
620    }
621
622    if (mDevice == NULL) {
623        res = connectCameraDevice(cameraId);
624        if (res) {
625            return res;
626        }
627    }
628
629    res = submitTorchEnabledRequest();
630    if (res) {
631        return res;
632    }
633
634    mTorchEnabled = true;
635    mCallbacks->torch_mode_status_change(mCallbacks,
636            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
637    return OK;
638}
639// CameraDeviceClientFlashControl implementation ends
640
641
642/////////////////////////////////////////////////////////////////////
643// CameraHardwareInterfaceFlashControl implementation begins
644// Flash control for camera module <= v2.3 and camera HAL v1
645/////////////////////////////////////////////////////////////////////
646CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
647        CameraModule& cameraModule,
648        const camera_module_callbacks_t& callbacks) :
649        mCameraModule(&cameraModule),
650        mCallbacks(&callbacks),
651        mTorchEnabled(false) {
652
653}
654
655CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
656    disconnectCameraDevice();
657
658    mAnw.clear();
659    mSurfaceTexture.clear();
660    mProducer.clear();
661    mConsumer.clear();
662
663    if (mTorchEnabled) {
664        if (mCallbacks) {
665            ALOGV("%s: notify the framework that torch was turned off",
666                    __FUNCTION__);
667            mCallbacks->torch_mode_status_change(mCallbacks,
668                    mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
669        }
670    }
671}
672
673status_t CameraHardwareInterfaceFlashControl::setTorchMode(
674        const String8& cameraId, bool enabled) {
675    Mutex::Autolock l(mLock);
676
677    // pre-check
678    status_t res;
679    if (enabled) {
680        bool hasFlash = false;
681        res = hasFlashUnitLocked(cameraId, &hasFlash);
682        // invalid camera?
683        if (res) {
684            // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
685            // another camera device.
686            return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
687        }
688        // no flash unit?
689        if (!hasFlash) {
690            return -ENOSYS;
691        }
692    } else if (mDevice == NULL || cameraId != mCameraId) {
693        // disabling the torch mode of an un-opened or different device.
694        return OK;
695    } else {
696        // disabling the torch mode of currently opened device
697        disconnectCameraDevice();
698        mTorchEnabled = false;
699        mCallbacks->torch_mode_status_change(mCallbacks,
700            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
701        return OK;
702    }
703
704    res = startPreviewAndTorch();
705    if (res) {
706        return res;
707    }
708
709    mTorchEnabled = true;
710    mCallbacks->torch_mode_status_change(mCallbacks,
711            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
712    return OK;
713}
714
715status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
716        const String8& cameraId, bool *hasFlash) {
717    Mutex::Autolock l(mLock);
718    return hasFlashUnitLocked(cameraId, hasFlash);
719}
720
721status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
722        const String8& cameraId, bool *hasFlash) {
723    if (!hasFlash) {
724        return BAD_VALUE;
725    }
726
727    status_t res;
728    if (mDevice == NULL) {
729        res = connectCameraDevice(cameraId);
730        if (res) {
731            return res;
732        }
733    }
734
735    if (cameraId != mCameraId) {
736        return BAD_INDEX;
737    }
738
739    const char *flashMode =
740            mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
741    if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
742        *hasFlash = true;
743    } else {
744        *hasFlash = false;
745    }
746
747    return OK;
748}
749
750status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
751    status_t res = OK;
752    res = mDevice->startPreview();
753    if (res) {
754        ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
755                strerror(-res), res);
756        return res;
757    }
758
759    mParameters.set(CameraParameters::KEY_FLASH_MODE,
760            CameraParameters::FLASH_MODE_TORCH);
761
762    return mDevice->setParameters(mParameters);
763}
764
765status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
766        int32_t *width, int32_t *height) {
767    if (!width || !height) {
768        return BAD_VALUE;
769    }
770
771    int32_t w = INT32_MAX;
772    int32_t h = 1;
773    Vector<Size> sizes;
774
775    mParameters.getSupportedPreviewSizes(sizes);
776    for (size_t i = 0; i < sizes.size(); i++) {
777        Size s = sizes[i];
778        if (w * h > s.width * s.height) {
779            w = s.width;
780            h = s.height;
781        }
782    }
783
784    if (w == INT32_MAX) {
785        return NAME_NOT_FOUND;
786    }
787
788    *width = w;
789    *height = h;
790
791    return OK;
792}
793
794status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
795        sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
796    status_t res;
797    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
798
799    mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
800            true, true);
801    if (mSurfaceTexture == NULL) {
802        return NO_MEMORY;
803    }
804
805    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
806    res = mSurfaceTexture->setDefaultBufferSize(width, height);
807    if (res) {
808        return res;
809    }
810    res = mSurfaceTexture->setDefaultBufferFormat(format);
811    if (res) {
812        return res;
813    }
814
815    mAnw = new Surface(mProducer, /*useAsync*/ true);
816    if (mAnw == NULL) {
817        return NO_MEMORY;
818    }
819
820    res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA);
821    if (res) {
822        ALOGE("%s: Unable to connect to native window", __FUNCTION__);
823        return res;
824    }
825
826    return device->setPreviewWindow(mAnw);
827}
828
829status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
830        const String8& cameraId) {
831    sp<CameraHardwareInterface> device =
832            new CameraHardwareInterface(cameraId.string());
833
834    status_t res = device->initialize(mCameraModule);
835    if (res) {
836        ALOGE("%s: initializing camera %s failed", __FUNCTION__,
837                cameraId.string());
838        return res;
839    }
840
841    // need to set __get_memory in set_callbacks().
842    device->setCallbacks(NULL, NULL, NULL, NULL);
843
844    mParameters = device->getParameters();
845
846    int32_t width, height;
847    res = getSmallestSurfaceSize(&width, &height);
848    if (res) {
849        ALOGE("%s: failed to get smallest surface size for camera %s",
850                __FUNCTION__, cameraId.string());
851        return res;
852    }
853
854    res = initializePreviewWindow(device, width, height);
855    if (res) {
856        ALOGE("%s: failed to initialize preview window for camera %s",
857                __FUNCTION__, cameraId.string());
858        return res;
859    }
860
861    mCameraId = cameraId;
862    mDevice = device;
863    return OK;
864}
865
866status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
867    if (mDevice == NULL) {
868        return OK;
869    }
870
871    mParameters.set(CameraParameters::KEY_FLASH_MODE,
872            CameraParameters::FLASH_MODE_OFF);
873    mDevice->setParameters(mParameters);
874    mDevice->stopPreview();
875    status_t res = native_window_api_disconnect(mAnw.get(),
876            NATIVE_WINDOW_API_CAMERA);
877    if (res) {
878        ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
879                __FUNCTION__, strerror(-res), res);
880    }
881    mDevice->setPreviewWindow(NULL);
882    mDevice->release();
883
884    return OK;
885}
886// CameraHardwareInterfaceFlashControl implementation ends
887
888}
889