blob: 00a70eb19a19daca11bda5d907efd2c2870df507 [file] [log] [blame]
Chien-Yu Chen3068d732015-02-09 13:29:57 -08001/*
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}