CameraFlashlight.cpp revision b97babb8c08969b55af3b6456d15f764c8873d3f
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 (mFlashControl == NULL) {
114        if (enabled == false) {
115            return OK;
116        }
117
118        res = createFlashlightControl(cameraId);
119        if (res) {
120            return res;
121        }
122        res =  mFlashControl->setTorchMode(cameraId, enabled);
123        return res;
124    }
125
126    // if flash control already exists, turning on torch mode may fail if it's
127    // tied to another camera device for module v2.3 and below.
128    res = mFlashControl->setTorchMode(cameraId, enabled);
129    if (res == BAD_INDEX) {
130        // flash control is tied to another camera device, need to close it and
131        // try again.
132        mFlashControl.clear();
133        res = createFlashlightControl(cameraId);
134        if (res) {
135            return res;
136        }
137        res = mFlashControl->setTorchMode(cameraId, enabled);
138    }
139
140    return res;
141}
142
143status_t CameraFlashlight::findFlashUnits() {
144    Mutex::Autolock l(mLock);
145    status_t res;
146    int32_t numCameras = mCameraModule->getNumberOfCameras();
147
148    mHasFlashlightMap.clear();
149    mFlashlightMapInitialized = false;
150
151    for (int32_t i = 0; i < numCameras; i++) {
152        bool hasFlash = false;
153        String8 id = String8::format("%d", i);
154
155        res = createFlashlightControl(id);
156        if (res) {
157            ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
158                    id.string());
159        } else {
160            res = mFlashControl->hasFlashUnit(id, &hasFlash);
161            if (res == -EUSERS || res == -EBUSY) {
162                ALOGE("%s: failed to check if camera %s has a flash unit. Some "
163                        "camera devices may be opened", __FUNCTION__,
164                        id.string());
165                return res;
166            } else if (res) {
167                ALOGE("%s: failed to check if camera %s has a flash unit. %s"
168                        " (%d)", __FUNCTION__, id.string(), strerror(-res),
169                        res);
170            }
171
172            mFlashControl.clear();
173        }
174        mHasFlashlightMap.add(id, hasFlash);
175    }
176
177    mFlashlightMapInitialized = true;
178    return OK;
179}
180
181bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
182    status_t res;
183
184    Mutex::Autolock l(mLock);
185    return hasFlashUnitLocked(cameraId);
186}
187
188bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
189    if (!mFlashlightMapInitialized) {
190        ALOGE("%s: findFlashUnits() must be called before this method.");
191        return false;
192    }
193
194    ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
195    if (index == NAME_NOT_FOUND) {
196        ALOGE("%s: camera %s not present when findFlashUnits() was called",
197                __FUNCTION__, cameraId.string());
198        return false;
199    }
200
201    return mHasFlashlightMap.valueAt(index);
202}
203
204status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
205    ALOGV("%s: prepare for device open", __FUNCTION__);
206
207    Mutex::Autolock l(mLock);
208    if (!mFlashlightMapInitialized) {
209        ALOGE("%s: findFlashUnits() must be called before this method.");
210        return NO_INIT;
211    }
212
213    if (mCameraModule->getRawModule()->module_api_version <
214            CAMERA_MODULE_API_VERSION_2_4) {
215        // framework is going to open a camera device, all flash light control
216        // should be closed for backward compatible support.
217        mFlashControl.clear();
218
219        if (mOpenedCameraIds.size() == 0) {
220            // notify torch unavailable for all cameras with a flash
221            int numCameras = mCameraModule->getNumberOfCameras();
222            for (int i = 0; i < numCameras; i++) {
223                if (hasFlashUnitLocked(String8::format("%d", i))) {
224                    mCallbacks->torch_mode_status_change(mCallbacks,
225                            String8::format("%d", i).string(),
226                            TORCH_MODE_STATUS_NOT_AVAILABLE);
227                }
228            }
229        }
230
231        // close flash control that may be opened by calling hasFlashUnitLocked.
232        mFlashControl.clear();
233    }
234
235    if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
236        mOpenedCameraIds.add(cameraId);
237    }
238
239    return OK;
240}
241
242status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
243    ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
244
245    Mutex::Autolock l(mLock);
246    if (!mFlashlightMapInitialized) {
247        ALOGE("%s: findFlashUnits() must be called before this method.");
248        return NO_INIT;
249    }
250
251    ssize_t index = mOpenedCameraIds.indexOf(cameraId);
252    if (index == NAME_NOT_FOUND) {
253        ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
254                cameraId.string());
255    } else {
256        mOpenedCameraIds.removeAt(index);
257    }
258
259    // Cannot do anything until all cameras are closed.
260    if (mOpenedCameraIds.size() != 0)
261        return OK;
262
263    if (mCameraModule->getRawModule()->module_api_version <
264            CAMERA_MODULE_API_VERSION_2_4) {
265        // notify torch available for all cameras with a flash
266        int numCameras = mCameraModule->getNumberOfCameras();
267        for (int i = 0; i < numCameras; i++) {
268            if (hasFlashUnitLocked(String8::format("%d", i))) {
269                mCallbacks->torch_mode_status_change(mCallbacks,
270                        String8::format("%d", i).string(),
271                        TORCH_MODE_STATUS_AVAILABLE_OFF);
272            }
273        }
274    }
275
276    return OK;
277}
278// CameraFlashlight implementation ends
279
280
281FlashControlBase::~FlashControlBase() {
282}
283
284/////////////////////////////////////////////////////////////////////
285// ModuleFlashControl implementation begins
286// Flash control for camera module v2.4 and above.
287/////////////////////////////////////////////////////////////////////
288ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
289        const camera_module_callbacks_t& callbacks) :
290    mCameraModule(&cameraModule) {
291}
292
293ModuleFlashControl::~ModuleFlashControl() {
294}
295
296status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
297    if (!hasFlash) {
298        return BAD_VALUE;
299    }
300
301    *hasFlash = false;
302    Mutex::Autolock l(mLock);
303
304    camera_info info;
305    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
306            &info);
307    if (res != 0) {
308        return res;
309    }
310
311    CameraMetadata metadata;
312    metadata = info.static_camera_characteristics;
313    camera_metadata_entry flashAvailable =
314            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
315    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
316        *hasFlash = true;
317    }
318
319    return OK;
320}
321
322status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
323    ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
324            cameraId.string(), enabled);
325
326    Mutex::Autolock l(mLock);
327    return mCameraModule->setTorchMode(cameraId.string(), enabled);
328}
329// ModuleFlashControl implementation ends
330
331/////////////////////////////////////////////////////////////////////
332// CameraDeviceClientFlashControl implementation begins
333// Flash control for camera module <= v2.3 and camera HAL v2-v3
334/////////////////////////////////////////////////////////////////////
335CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
336        CameraModule& cameraModule,
337        const camera_module_callbacks_t& callbacks) :
338        mCameraModule(&cameraModule),
339        mCallbacks(&callbacks),
340        mTorchEnabled(false),
341        mMetadata(NULL),
342        mStreaming(false) {
343}
344
345CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
346    disconnectCameraDevice();
347    if (mMetadata) {
348        delete mMetadata;
349    }
350
351    mAnw.clear();
352    mSurfaceTexture.clear();
353    mProducer.clear();
354    mConsumer.clear();
355
356    if (mTorchEnabled) {
357        if (mCallbacks) {
358            ALOGV("%s: notify the framework that torch was turned off",
359                    __FUNCTION__);
360            mCallbacks->torch_mode_status_change(mCallbacks,
361                    mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
362        }
363    }
364}
365
366status_t CameraDeviceClientFlashControl::initializeSurface(
367        sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
368    status_t res;
369    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
370
371    mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
372            true, true);
373    if (mSurfaceTexture == NULL) {
374        return NO_MEMORY;
375    }
376
377    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
378    res = mSurfaceTexture->setDefaultBufferSize(width, height);
379    if (res) {
380        return res;
381    }
382    res = mSurfaceTexture->setDefaultBufferFormat(format);
383    if (res) {
384        return res;
385    }
386
387    mAnw = new Surface(mProducer, /*useAsync*/ true);
388    if (mAnw == NULL) {
389        return NO_MEMORY;
390    }
391    res = device->createStream(mAnw, width, height, format,
392            HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
393    if (res) {
394        return res;
395    }
396
397    res = device->configureStreams();
398    if (res) {
399        return res;
400    }
401
402    return res;
403}
404
405status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
406        const camera_info& info, int32_t *width, int32_t *height) {
407    if (!width || !height) {
408        return BAD_VALUE;
409    }
410
411    int32_t w = INT32_MAX;
412    int32_t h = 1;
413
414    CameraMetadata metadata;
415    metadata = info.static_camera_characteristics;
416    camera_metadata_entry streamConfigs =
417            metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
418    for (size_t i = 0; i < streamConfigs.count; i += 4) {
419        int32_t fmt = streamConfigs.data.i32[i];
420        if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
421            int32_t ww = streamConfigs.data.i32[i + 1];
422            int32_t hh = streamConfigs.data.i32[i + 2];
423
424            if (w * h > ww * hh) {
425                w = ww;
426                h = hh;
427            }
428        }
429    }
430
431    // if stream configuration is not found, try available processed sizes.
432    if (streamConfigs.count == 0) {
433        camera_metadata_entry availableProcessedSizes =
434            metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
435        for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
436            int32_t ww = availableProcessedSizes.data.i32[i];
437            int32_t hh = availableProcessedSizes.data.i32[i + 1];
438            if (w * h > ww * hh) {
439                w = ww;
440                h = hh;
441            }
442        }
443    }
444
445    if (w == INT32_MAX) {
446        return NAME_NOT_FOUND;
447    }
448
449    *width = w;
450    *height = h;
451
452    return OK;
453}
454
455status_t CameraDeviceClientFlashControl::connectCameraDevice(
456        const String8& cameraId) {
457    camera_info info;
458    status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
459    if (res != 0) {
460        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
461                cameraId.string());
462        return res;
463    }
464
465    sp<CameraDeviceBase> device =
466            CameraDeviceFactory::createDevice(atoi(cameraId.string()));
467    if (device == NULL) {
468        return NO_MEMORY;
469    }
470
471    res = device->initialize(mCameraModule);
472    if (res) {
473        return res;
474    }
475
476    int32_t width, height;
477    res = getSmallestSurfaceSize(info, &width, &height);
478    if (res) {
479        return res;
480    }
481    res = initializeSurface(device, width, height);
482    if (res) {
483        return res;
484    }
485
486    mCameraId = cameraId;
487    mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
488    mDevice = device;
489
490    return OK;
491}
492
493status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
494    if (mDevice != NULL) {
495        mDevice->disconnect();
496        mDevice.clear();
497    }
498
499    return OK;
500}
501
502
503
504status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
505        bool *hasFlash) {
506    ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
507            cameraId.string());
508
509    Mutex::Autolock l(mLock);
510    return hasFlashUnitLocked(cameraId, hasFlash);
511
512}
513
514status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
515        const String8& cameraId, bool *hasFlash) {
516    if (!hasFlash) {
517        return BAD_VALUE;
518    }
519
520    camera_info info;
521    status_t res = mCameraModule->getCameraInfo(
522            atoi(cameraId.string()), &info);
523    if (res != 0) {
524        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
525                cameraId.string());
526        return res;
527    }
528
529    CameraMetadata metadata;
530    metadata = info.static_camera_characteristics;
531    camera_metadata_entry flashAvailable =
532            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
533    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
534        *hasFlash = true;
535    }
536
537    return OK;
538}
539
540status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
541    status_t res;
542
543    if (mMetadata == NULL) {
544        mMetadata = new CameraMetadata();
545        if (mMetadata == NULL) {
546            return NO_MEMORY;
547        }
548        res = mDevice->createDefaultRequest(
549                CAMERA3_TEMPLATE_PREVIEW, mMetadata);
550        if (res) {
551            return res;
552        }
553    }
554
555    uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
556    mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
557    mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
558
559    uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
560    mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
561
562    int32_t requestId = 0;
563    mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
564
565    if (mStreaming) {
566        res = mDevice->setStreamingRequest(*mMetadata);
567    } else {
568        res = mDevice->capture(*mMetadata);
569    }
570    return res;
571}
572
573
574
575
576status_t CameraDeviceClientFlashControl::setTorchMode(
577        const String8& cameraId, bool enabled) {
578    bool hasFlash = false;
579
580    Mutex::Autolock l(mLock);
581    status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
582
583    // pre-check
584    if (enabled) {
585        // invalid camera?
586        if (res) {
587            return -EINVAL;
588        }
589        // no flash unit?
590        if (!hasFlash) {
591            return -ENOSYS;
592        }
593        // already opened for a different device?
594        if (mDevice != NULL && cameraId != mCameraId) {
595            return BAD_INDEX;
596        }
597    } else if (mDevice == NULL || cameraId != mCameraId) {
598        // disabling the torch mode of an un-opened or different device.
599        return OK;
600    } else {
601        // disabling the torch mode of currently opened device
602        disconnectCameraDevice();
603        mTorchEnabled = false;
604        mCallbacks->torch_mode_status_change(mCallbacks,
605            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
606        return OK;
607    }
608
609    if (mDevice == NULL) {
610        res = connectCameraDevice(cameraId);
611        if (res) {
612            return res;
613        }
614    }
615
616    res = submitTorchEnabledRequest();
617    if (res) {
618        return res;
619    }
620
621    mTorchEnabled = true;
622    mCallbacks->torch_mode_status_change(mCallbacks,
623            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
624    return OK;
625}
626// CameraDeviceClientFlashControl implementation ends
627
628
629/////////////////////////////////////////////////////////////////////
630// CameraHardwareInterfaceFlashControl implementation begins
631// Flash control for camera module <= v2.3 and camera HAL v1
632/////////////////////////////////////////////////////////////////////
633CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
634        CameraModule& cameraModule,
635        const camera_module_callbacks_t& callbacks) :
636        mCameraModule(&cameraModule),
637        mCallbacks(&callbacks),
638        mTorchEnabled(false) {
639
640}
641
642CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
643    disconnectCameraDevice();
644
645    mAnw.clear();
646    mSurfaceTexture.clear();
647    mProducer.clear();
648    mConsumer.clear();
649
650    if (mTorchEnabled) {
651        if (mCallbacks) {
652            ALOGV("%s: notify the framework that torch was turned off",
653                    __FUNCTION__);
654            mCallbacks->torch_mode_status_change(mCallbacks,
655                    mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
656        }
657    }
658}
659
660status_t CameraHardwareInterfaceFlashControl::setTorchMode(
661        const String8& cameraId, bool enabled) {
662    Mutex::Autolock l(mLock);
663
664    // pre-check
665    status_t res;
666    if (enabled) {
667        bool hasFlash = false;
668        res = hasFlashUnitLocked(cameraId, &hasFlash);
669        // invalid camera?
670        if (res) {
671            // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
672            // another camera device.
673            return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
674        }
675        // no flash unit?
676        if (!hasFlash) {
677            return -ENOSYS;
678        }
679    } else if (mDevice == NULL || cameraId != mCameraId) {
680        // disabling the torch mode of an un-opened or different device.
681        return OK;
682    } else {
683        // disabling the torch mode of currently opened device
684        disconnectCameraDevice();
685        mTorchEnabled = false;
686        mCallbacks->torch_mode_status_change(mCallbacks,
687            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
688        return OK;
689    }
690
691    res = startPreviewAndTorch();
692    if (res) {
693        return res;
694    }
695
696    mTorchEnabled = true;
697    mCallbacks->torch_mode_status_change(mCallbacks,
698            cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
699    return OK;
700}
701
702status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
703        const String8& cameraId, bool *hasFlash) {
704    Mutex::Autolock l(mLock);
705    return hasFlashUnitLocked(cameraId, hasFlash);
706}
707
708status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
709        const String8& cameraId, bool *hasFlash) {
710    if (!hasFlash) {
711        return BAD_VALUE;
712    }
713
714    status_t res;
715    if (mDevice == NULL) {
716        res = connectCameraDevice(cameraId);
717        if (res) {
718            return res;
719        }
720    }
721
722    if (cameraId != mCameraId) {
723        return BAD_INDEX;
724    }
725
726    const char *flashMode =
727            mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
728    if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
729        *hasFlash = true;
730    } else {
731        *hasFlash = false;
732    }
733
734    return OK;
735}
736
737status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
738    status_t res = OK;
739    res = mDevice->startPreview();
740    if (res) {
741        ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
742                strerror(-res), res);
743        return res;
744    }
745
746    mParameters.set(CameraParameters::KEY_FLASH_MODE,
747            CameraParameters::FLASH_MODE_TORCH);
748
749    return mDevice->setParameters(mParameters);
750}
751
752status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
753        int32_t *width, int32_t *height) {
754    if (!width || !height) {
755        return BAD_VALUE;
756    }
757
758    int32_t w = INT32_MAX;
759    int32_t h = 1;
760    Vector<Size> sizes;
761
762    mParameters.getSupportedPreviewSizes(sizes);
763    for (size_t i = 0; i < sizes.size(); i++) {
764        Size s = sizes[i];
765        if (w * h > s.width * s.height) {
766            w = s.width;
767            h = s.height;
768        }
769    }
770
771    if (w == INT32_MAX) {
772        return NAME_NOT_FOUND;
773    }
774
775    *width = w;
776    *height = h;
777
778    return OK;
779}
780
781status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
782        sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
783    status_t res;
784    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
785
786    mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
787            true, true);
788    if (mSurfaceTexture == NULL) {
789        return NO_MEMORY;
790    }
791
792    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
793    res = mSurfaceTexture->setDefaultBufferSize(width, height);
794    if (res) {
795        return res;
796    }
797    res = mSurfaceTexture->setDefaultBufferFormat(format);
798    if (res) {
799        return res;
800    }
801
802    mAnw = new Surface(mProducer, /*useAsync*/ true);
803    if (mAnw == NULL) {
804        return NO_MEMORY;
805    }
806
807    res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA);
808    if (res) {
809        ALOGE("%s: Unable to connect to native window", __FUNCTION__);
810        return res;
811    }
812
813    return device->setPreviewWindow(mAnw);
814}
815
816status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
817        const String8& cameraId) {
818    sp<CameraHardwareInterface> device =
819            new CameraHardwareInterface(cameraId.string());
820
821    status_t res = device->initialize(mCameraModule);
822    if (res) {
823        ALOGE("%s: initializing camera %s failed", __FUNCTION__,
824                cameraId.string());
825        return res;
826    }
827
828    // need to set __get_memory in set_callbacks().
829    device->setCallbacks(NULL, NULL, NULL, NULL);
830
831    mParameters = device->getParameters();
832
833    int32_t width, height;
834    res = getSmallestSurfaceSize(&width, &height);
835    if (res) {
836        ALOGE("%s: failed to get smallest surface size for camera %s",
837                __FUNCTION__, cameraId.string());
838        return res;
839    }
840
841    res = initializePreviewWindow(device, width, height);
842    if (res) {
843        ALOGE("%s: failed to initialize preview window for camera %s",
844                __FUNCTION__, cameraId.string());
845        return res;
846    }
847
848    mCameraId = cameraId;
849    mDevice = device;
850    return OK;
851}
852
853status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
854    if (mDevice == NULL) {
855        return OK;
856    }
857
858    mParameters.set(CameraParameters::KEY_FLASH_MODE,
859            CameraParameters::FLASH_MODE_OFF);
860    mDevice->setParameters(mParameters);
861    mDevice->stopPreview();
862    status_t res = native_window_api_disconnect(mAnw.get(),
863            NATIVE_WINDOW_API_CAMERA);
864    if (res) {
865        ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
866                __FUNCTION__, strerror(-res), res);
867    }
868    mDevice->setPreviewWindow(NULL);
869    mDevice->release();
870
871    return OK;
872}
873// CameraHardwareInterfaceFlashControl implementation ends
874
875}
876