CameraFlashlight.cpp revision 3068d73c6c7e1f44523b1466b903a9c82408b258
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
35CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
36        const camera_module_callbacks_t& callbacks) :
37        mCameraModule(&cameraModule),
38        mCallbacks(&callbacks) {
39}
40
41CameraFlashlight::~CameraFlashlight() {
42}
43
44status_t CameraFlashlight::createFlashlightControl(const String16& cameraId) {
45    ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
46            cameraId.string());
47    if (mFlashControl != NULL) {
48        return INVALID_OPERATION;
49    }
50
51    status_t res = OK;
52
53    if (mCameraModule->getRawModule()->module_api_version >=
54            CAMERA_MODULE_API_VERSION_2_4) {
55        mFlashControl = new FlashControl(*mCameraModule, *mCallbacks);
56        if (mFlashControl == NULL) {
57            ALOGV("%s: cannot create flash control for module api v2.4+",
58                     __FUNCTION__);
59            return NO_MEMORY;
60        }
61    } else {
62        uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
63
64        if (mCameraModule->getRawModule()->module_api_version >=
65                CAMERA_MODULE_API_VERSION_2_0) {
66            camera_info info;
67            res = mCameraModule->getCameraInfo(
68                    atoi(String8(cameraId).string()), &info);
69            if (res) {
70                ALOGV("%s: failed to get camera info for camera %s",
71                        __FUNCTION__, cameraId.string());
72                return res;
73            }
74            deviceVersion = info.device_version;
75        }
76
77        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
78            CameraDeviceClientFlashControl *flashControl =
79                    new CameraDeviceClientFlashControl(*mCameraModule,
80                                                       *mCallbacks);
81            if (!flashControl) {
82                return NO_MEMORY;
83            }
84
85            mFlashControl = flashControl;
86        }
87        else {
88            // todo: implement for device api 1
89            return INVALID_OPERATION;
90        }
91    }
92
93    return OK;
94}
95
96status_t CameraFlashlight::setTorchMode(const String16& cameraId, bool enabled) {
97    if (!mCameraModule) {
98        return NO_INIT;
99    }
100
101    ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
102            cameraId.string(), enabled);
103
104    status_t res = OK;
105    Mutex::Autolock l(mLock);
106
107    if (mFlashControl == NULL) {
108        res = createFlashlightControl(cameraId);
109        if (res) {
110            return res;
111        }
112        res =  mFlashControl->setTorchMode(cameraId, enabled);
113        return res;
114    }
115
116    // if flash control already exists, turning on torch mode may fail if it's
117    // tied to another camera device for module v2.3 and below.
118    res = mFlashControl->setTorchMode(cameraId, enabled);
119    if (res == BAD_INDEX) {
120        // flash control is tied to another camera device, need to close it and
121        // try again.
122        mFlashControl.clear();
123        res = createFlashlightControl(cameraId);
124        if (res) {
125            return res;
126        }
127        res = mFlashControl->setTorchMode(cameraId, enabled);
128    }
129
130    return res;
131}
132
133bool CameraFlashlight::hasFlashUnit(const String16& cameraId) {
134    status_t res;
135
136    Mutex::Autolock l(mLock);
137
138    if (mFlashControl == NULL) {
139        res = createFlashlightControl(cameraId);
140        if (res) {
141            ALOGE("%s: failed to create flash control for %s ",
142                    __FUNCTION__, cameraId.string());
143            return false;
144        }
145    }
146
147    bool flashUnit = false;
148
149    // if flash control already exists, querying if a camera device has a flash
150    // unit may fail if it's module v1
151    res = mFlashControl->hasFlashUnit(cameraId, &flashUnit);
152    if (res == BAD_INDEX) {
153        // need to close the flash control before query.
154        mFlashControl.clear();
155        res = createFlashlightControl(cameraId);
156        if (res) {
157            ALOGE("%s: failed to create flash control for %s ", __FUNCTION__,
158                    cameraId.string());
159            return false;
160        }
161        res = mFlashControl->hasFlashUnit(cameraId, &flashUnit);
162        if (res) {
163            flashUnit = false;
164        }
165    }
166
167    return flashUnit;
168}
169
170status_t CameraFlashlight::prepareDeviceOpen() {
171    ALOGV("%s: prepare for device open", __FUNCTION__);
172
173    Mutex::Autolock l(mLock);
174
175    if (mCameraModule && mCameraModule->getRawModule()->module_api_version <
176            CAMERA_MODULE_API_VERSION_2_4) {
177        // framework is going to open a camera device, all flash light control
178        // should be closed for backward compatible support.
179        if (mFlashControl != NULL) {
180            mFlashControl.clear();
181        }
182    }
183
184    return OK;
185}
186
187
188FlashControlBase::~FlashControlBase() {
189}
190
191
192FlashControl::FlashControl(CameraModule& cameraModule,
193        const camera_module_callbacks_t& callbacks) :
194    mCameraModule(&cameraModule) {
195}
196
197FlashControl::~FlashControl() {
198}
199
200status_t FlashControl::hasFlashUnit(const String16& cameraId, bool *hasFlash) {
201    if (!hasFlash) {
202        return BAD_VALUE;
203    }
204
205    *hasFlash = false;
206
207    Mutex::Autolock l(mLock);
208
209    if (!mCameraModule) {
210        return NO_INIT;
211    }
212
213    camera_info info;
214    status_t res = mCameraModule->getCameraInfo(atoi(String8(cameraId).string()),
215            &info);
216    if (res != 0) {
217        return res;
218    }
219
220    CameraMetadata metadata;
221    metadata = info.static_camera_characteristics;
222    camera_metadata_entry flashAvailable =
223            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
224    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
225        *hasFlash = true;
226    }
227
228    return OK;
229}
230
231status_t FlashControl::setTorchMode(const String16& cameraId, bool enabled) {
232    ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
233            cameraId.string(), enabled);
234
235    Mutex::Autolock l(mLock);
236    if (!mCameraModule) {
237        return NO_INIT;
238    }
239
240    return mCameraModule->setTorchMode(String8(cameraId).string(), enabled);
241}
242
243CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
244        CameraModule& cameraModule,
245        const camera_module_callbacks_t& callbacks) :
246        mCameraModule(&cameraModule),
247        mCallbacks(&callbacks),
248        mTorchEnabled(false),
249        mMetadata(NULL) {
250}
251
252CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
253    if (mDevice != NULL) {
254        mDevice->flush();
255        mDevice->deleteStream(mStreamId);
256        mDevice.clear();
257    }
258    if (mMetadata) {
259        delete mMetadata;
260    }
261
262    mAnw.clear();
263    mSurfaceTexture.clear();
264    mProducer.clear();
265    mConsumer.clear();
266
267    if (mTorchEnabled) {
268        if (mCallbacks) {
269            ALOGV("%s: notify the framework that torch was turned off",
270                    __FUNCTION__);
271            mCallbacks->torch_mode_status_change(mCallbacks,
272                    String8(mCameraId).string(), TORCH_MODE_STATUS_OFF);
273        }
274    }
275}
276
277status_t CameraDeviceClientFlashControl::initializeSurface(int32_t width,
278        int32_t height) {
279    status_t res;
280    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
281
282    mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
283            true, true);
284    if (mSurfaceTexture == NULL) {
285        return NO_MEMORY;
286    }
287
288    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
289    res = mSurfaceTexture->setDefaultBufferSize(width, height);
290    if (res) {
291        return res;
292    }
293    res = mSurfaceTexture->setDefaultBufferFormat(format);
294    if (res) {
295        return res;
296    }
297
298    bool useAsync = false;
299    int32_t consumerUsage;
300    res = mProducer->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &consumerUsage);
301    if (res) {
302        return res;
303    }
304
305    if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
306        useAsync = true;
307    }
308
309    mAnw = new Surface(mProducer, useAsync);
310    if (mAnw == NULL) {
311        return NO_MEMORY;
312    }
313    res = mDevice->createStream(mAnw, width, height, format, &mStreamId);
314    if (res) {
315        return res;
316    }
317
318    res = mDevice->configureStreams();
319    if (res) {
320        return res;
321    }
322
323    return res;
324}
325
326status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
327        const camera_info& info, int32_t *width, int32_t *height) {
328    if (!width || !height) {
329        return BAD_VALUE;
330    }
331
332    int32_t w = INT32_MAX;
333    int32_t h = 1;
334
335    CameraMetadata metadata;
336    metadata = info.static_camera_characteristics;
337    camera_metadata_entry streamConfigs =
338            metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
339    for (size_t i = 0; i < streamConfigs.count; i += 4) {
340        int32_t fmt = streamConfigs.data.i32[i];
341        if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
342            int32_t ww = streamConfigs.data.i32[i + 1];
343            int32_t hh = streamConfigs.data.i32[i + 2];
344
345            if (w* h > ww * hh) {
346                w = ww;
347                h = hh;
348            }
349        }
350    }
351
352    if (w == INT32_MAX) {
353        return NAME_NOT_FOUND;
354    }
355
356    *width = w;
357    *height = h;
358
359    return OK;
360}
361
362status_t CameraDeviceClientFlashControl::connectCameraDevice(
363        const String16& cameraId) {
364    String8 id = String8(cameraId);
365    camera_info info;
366    status_t res = mCameraModule->getCameraInfo(atoi(id.string()), &info);
367    if (res != 0) {
368        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
369                mCameraId.string());
370        return res;
371    }
372
373    mDevice = CameraDeviceFactory::createDevice(atoi(id.string()));
374    if (mDevice == NULL) {
375        return NO_MEMORY;
376    }
377
378    res = mDevice->initialize(mCameraModule);
379    if (res) {
380        goto fail;
381    }
382
383    int32_t width, height;
384    res = getSmallestSurfaceSize(info, &width, &height);
385    if (res) {
386        return res;
387    }
388    res = initializeSurface(width, height);
389    if (res) {
390        goto fail;
391    }
392
393    mCameraId = cameraId;
394
395    return OK;
396
397fail:
398    mDevice.clear();
399    return res;
400}
401
402
403status_t CameraDeviceClientFlashControl::hasFlashUnit(const String16& cameraId,
404        bool *hasFlash) {
405    ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
406            cameraId.string());
407
408    Mutex::Autolock l(mLock);
409    return hasFlashUnitLocked(cameraId, hasFlash);
410
411}
412
413status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
414        const String16& cameraId, bool *hasFlash) {
415    if (!mCameraModule) {
416        ALOGE("%s: camera module is NULL", __FUNCTION__);
417        return NO_INIT;
418    }
419
420    if (!hasFlash) {
421        return BAD_VALUE;
422    }
423
424    camera_info info;
425    status_t res = mCameraModule->getCameraInfo(
426            atoi(String8(cameraId).string()), &info);
427    if (res != 0) {
428        ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
429                cameraId.string());
430        return res;
431    }
432
433    CameraMetadata metadata;
434    metadata = info.static_camera_characteristics;
435    camera_metadata_entry flashAvailable =
436            metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
437    if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
438        *hasFlash = true;
439    }
440
441    return OK;
442}
443
444status_t CameraDeviceClientFlashControl::submitTorchRequest(bool enabled) {
445    status_t res;
446
447    if (mMetadata == NULL) {
448        mMetadata = new CameraMetadata();
449        if (mMetadata == NULL) {
450            return NO_MEMORY;
451        }
452        res = mDevice->createDefaultRequest(
453                CAMERA3_TEMPLATE_PREVIEW, mMetadata);
454        if (res) {
455            return res;
456        }
457    }
458
459    uint8_t torchOn = enabled ? ANDROID_FLASH_MODE_TORCH :
460                                ANDROID_FLASH_MODE_OFF;
461
462    mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
463    mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
464
465    int32_t requestId = 0;
466    mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
467
468    List<const CameraMetadata> metadataRequestList;
469    metadataRequestList.push_back(*mMetadata);
470
471    int64_t lastFrameNumber = 0;
472    res = mDevice->captureList(metadataRequestList, &lastFrameNumber);
473
474    return res;
475}
476
477
478status_t CameraDeviceClientFlashControl::setTorchMode(
479        const String16& cameraId, bool enabled) {
480    bool hasFlash = false;
481
482    Mutex::Autolock l(mLock);
483    status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
484
485    // pre-check
486    if (enabled) {
487        // invalid camera?
488        if (res) {
489            return -EINVAL;
490        }
491        // no flash unit?
492        if (!hasFlash) {
493            return -ENOSYS;
494        }
495        // already opened for a different device?
496        if (mDevice != NULL && cameraId != mCameraId) {
497            return BAD_INDEX;
498        }
499    } else if (mDevice == NULL || cameraId != mCameraId) {
500        // disabling the torch mode of an un-opened or different device.
501        return OK;
502    }
503
504    if (mDevice == NULL) {
505        res = connectCameraDevice(cameraId);
506        if (res) {
507            return res;
508        }
509    }
510
511    res = submitTorchRequest(enabled);
512    if (res) {
513        return res;
514    }
515
516    mTorchEnabled = enabled;
517    return OK;
518}
519
520}
521