blob: a00a49f19febfa4bebb67bf2e9b14a753f281cc0 [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
Chien-Yu Chen88da5262015-02-17 13:56:46 -080019// #define LOG_NDEBUG 0
Chien-Yu Chen3068d732015-02-09 13:29:57 -080020
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
Chien-Yu Chen88da5262015-02-17 13:56:46 -080035/////////////////////////////////////////////////////////////////////
36// CameraFlashlight implementation begins
37// used by camera service to control flashflight.
38/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -080039CameraFlashlight::CameraFlashlight(CameraModule& cameraModule,
40 const camera_module_callbacks_t& callbacks) :
41 mCameraModule(&cameraModule),
Chien-Yu Chen88da5262015-02-17 13:56:46 -080042 mCallbacks(&callbacks),
43 mFlashlightMapInitialized(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080044}
45
46CameraFlashlight::~CameraFlashlight() {
47}
48
Chien-Yu Chen88da5262015-02-17 13:56:46 -080049status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080050 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) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -080060 mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080061 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) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -080075 ALOGE("%s: failed to get camera info for camera %s",
Chien-Yu Chen3068d732015-02-09 13:29:57 -080076 __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;
Chien-Yu Chen88da5262015-02-17 13:56:46 -080091 } else {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080092 // todo: implement for device api 1
93 return INVALID_OPERATION;
94 }
95 }
96
97 return OK;
98}
99
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800100status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
101 if (!mFlashlightMapInitialized) {
102 ALOGE("%s: findFlashUnits() must be called before this method.");
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800103 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 (mFlashControl == NULL) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800113 if (enabled == false) {
114 return OK;
115 }
116
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800117 res = createFlashlightControl(cameraId);
118 if (res) {
119 return res;
120 }
121 res = mFlashControl->setTorchMode(cameraId, enabled);
122 return res;
123 }
124
125 // if flash control already exists, turning on torch mode may fail if it's
126 // tied to another camera device for module v2.3 and below.
127 res = mFlashControl->setTorchMode(cameraId, enabled);
128 if (res == BAD_INDEX) {
129 // flash control is tied to another camera device, need to close it and
130 // try again.
131 mFlashControl.clear();
132 res = createFlashlightControl(cameraId);
133 if (res) {
134 return res;
135 }
136 res = mFlashControl->setTorchMode(cameraId, enabled);
137 }
138
139 return res;
140}
141
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800142status_t CameraFlashlight::findFlashUnits() {
143 Mutex::Autolock l(mLock);
144 status_t res;
145 int32_t numCameras = mCameraModule->getNumberOfCameras();
146
147 mHasFlashlightMap.clear();
148 mFlashlightMapInitialized = false;
149
150 for (int32_t i = 0; i < numCameras; i++) {
151 bool hasFlash = false;
152 String8 id = String8::format("%d", i);
153
154 res = createFlashlightControl(id);
155 if (res) {
156 ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
157 id.string());
158 } else {
159 res = mFlashControl->hasFlashUnit(id, &hasFlash);
160 if (res == -EUSERS || res == -EBUSY) {
161 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
162 "camera devices may be opened", __FUNCTION__,
163 id.string());
164 return res;
165 } else if (res) {
166 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
167 " (%d)", __FUNCTION__, id.string(), strerror(-res),
168 res);
169 }
170
171 mFlashControl.clear();
172 }
173 mHasFlashlightMap.add(id, hasFlash);
174 }
175
176 mFlashlightMapInitialized = true;
177 return OK;
178}
179
180bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800181 status_t res;
182
183 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800184 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800185}
186
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800187bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
188 if (!mFlashlightMapInitialized) {
189 ALOGE("%s: findFlashUnits() must be called before this method.");
190 return false;
191 }
192
193 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
194 if (index == NAME_NOT_FOUND) {
195 ALOGE("%s: camera %s not present when findFlashUnits() was called",
196 __FUNCTION__, cameraId.string());
197 return false;
198 }
199
200 return mHasFlashlightMap.valueAt(index);
201}
202
203status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800204 ALOGV("%s: prepare for device open", __FUNCTION__);
205
206 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800207 if (!mFlashlightMapInitialized) {
208 ALOGE("%s: findFlashUnits() must be called before this method.");
209 return NO_INIT;
210 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800211
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800212 if (mCameraModule->getRawModule()->module_api_version <
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800213 CAMERA_MODULE_API_VERSION_2_4) {
214 // framework is going to open a camera device, all flash light control
215 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800216 mFlashControl.clear();
217
218 if (mOpenedCameraIds.size() == 0) {
219 // notify torch unavailable for all cameras with a flash
220 int numCameras = mCameraModule->getNumberOfCameras();
221 for (int i = 0; i < numCameras; i++) {
222 if (hasFlashUnitLocked(String8::format("%d", i))) {
223 mCallbacks->torch_mode_status_change(mCallbacks,
224 String8::format("%d", i).string(),
225 TORCH_MODE_STATUS_NOT_AVAILABLE);
226 }
227 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800228 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800229
230 // close flash control that may be opened by calling hasFlashUnitLocked.
231 mFlashControl.clear();
232 }
233
234 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
235 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800236 }
237
238 return OK;
239}
240
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800241status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
242 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
243
244 Mutex::Autolock l(mLock);
245 if (!mFlashlightMapInitialized) {
246 ALOGE("%s: findFlashUnits() must be called before this method.");
247 return NO_INIT;
248 }
249
250 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
251 if (index == NAME_NOT_FOUND) {
252 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
253 cameraId.string());
254 } else {
255 mOpenedCameraIds.removeAt(index);
256 }
257
258 // Cannot do anything until all cameras are closed.
259 if (mOpenedCameraIds.size() != 0)
260 return OK;
261
262 if (mCameraModule->getRawModule()->module_api_version <
263 CAMERA_MODULE_API_VERSION_2_4) {
264 // notify torch available for all cameras with a flash
265 int numCameras = mCameraModule->getNumberOfCameras();
266 for (int i = 0; i < numCameras; i++) {
267 if (hasFlashUnitLocked(String8::format("%d", i))) {
268 mCallbacks->torch_mode_status_change(mCallbacks,
269 String8::format("%d", i).string(),
270 TORCH_MODE_STATUS_AVAILABLE_OFF);
271 }
272 }
273 }
274
275 return OK;
276}
277// CameraFlashlight implementation ends
278
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800279
280FlashControlBase::~FlashControlBase() {
281}
282
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800283/////////////////////////////////////////////////////////////////////
284// ModuleFlashControl implementation begins
285// Flash control for camera module v2.4 and above.
286/////////////////////////////////////////////////////////////////////
287ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800288 const camera_module_callbacks_t& callbacks) :
289 mCameraModule(&cameraModule) {
290}
291
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800292ModuleFlashControl::~ModuleFlashControl() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800293}
294
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800295status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800296 if (!hasFlash) {
297 return BAD_VALUE;
298 }
299
300 *hasFlash = false;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800301 Mutex::Autolock l(mLock);
302
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800303 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800304 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800305 &info);
306 if (res != 0) {
307 return res;
308 }
309
310 CameraMetadata metadata;
311 metadata = info.static_camera_characteristics;
312 camera_metadata_entry flashAvailable =
313 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
314 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
315 *hasFlash = true;
316 }
317
318 return OK;
319}
320
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800321status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800322 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
323 cameraId.string(), enabled);
324
325 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800326 return mCameraModule->setTorchMode(cameraId.string(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800327}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800328// ModuleFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800329
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800330/////////////////////////////////////////////////////////////////////
331// CameraDeviceClientFlashControl implementation begins
332// Flash control for camera module <= v2.3 and camera HAL v2-v3
333/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800334CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
335 CameraModule& cameraModule,
336 const camera_module_callbacks_t& callbacks) :
337 mCameraModule(&cameraModule),
338 mCallbacks(&callbacks),
339 mTorchEnabled(false),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800340 mMetadata(NULL),
341 mStreaming(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800342}
343
344CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800345 disconnectCameraDevice();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800346 if (mMetadata) {
347 delete mMetadata;
348 }
349
350 mAnw.clear();
351 mSurfaceTexture.clear();
352 mProducer.clear();
353 mConsumer.clear();
354
355 if (mTorchEnabled) {
356 if (mCallbacks) {
357 ALOGV("%s: notify the framework that torch was turned off",
358 __FUNCTION__);
359 mCallbacks->torch_mode_status_change(mCallbacks,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800360 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800361 }
362 }
363}
364
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800365status_t CameraDeviceClientFlashControl::initializeSurface(
366 sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800367 status_t res;
368 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
369
370 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
371 true, true);
372 if (mSurfaceTexture == NULL) {
373 return NO_MEMORY;
374 }
375
376 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
377 res = mSurfaceTexture->setDefaultBufferSize(width, height);
378 if (res) {
379 return res;
380 }
381 res = mSurfaceTexture->setDefaultBufferFormat(format);
382 if (res) {
383 return res;
384 }
385
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800386 mAnw = new Surface(mProducer, /*useAsync*/ true);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800387 if (mAnw == NULL) {
388 return NO_MEMORY;
389 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800390 res = device->createStream(mAnw, width, height, format, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800391 if (res) {
392 return res;
393 }
394
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800395 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800396 if (res) {
397 return res;
398 }
399
400 return res;
401}
402
403status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
404 const camera_info& info, int32_t *width, int32_t *height) {
405 if (!width || !height) {
406 return BAD_VALUE;
407 }
408
409 int32_t w = INT32_MAX;
410 int32_t h = 1;
411
412 CameraMetadata metadata;
413 metadata = info.static_camera_characteristics;
414 camera_metadata_entry streamConfigs =
415 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
416 for (size_t i = 0; i < streamConfigs.count; i += 4) {
417 int32_t fmt = streamConfigs.data.i32[i];
418 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
419 int32_t ww = streamConfigs.data.i32[i + 1];
420 int32_t hh = streamConfigs.data.i32[i + 2];
421
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800422 if (w * h > ww * hh) {
423 w = ww;
424 h = hh;
425 }
426 }
427 }
428
429 // if stream configuration is not found, try available processed sizes.
430 if (streamConfigs.count == 0) {
431 camera_metadata_entry availableProcessedSizes =
432 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
433 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
434 int32_t ww = availableProcessedSizes.data.i32[i];
435 int32_t hh = availableProcessedSizes.data.i32[i + 1];
436 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800437 w = ww;
438 h = hh;
439 }
440 }
441 }
442
443 if (w == INT32_MAX) {
444 return NAME_NOT_FOUND;
445 }
446
447 *width = w;
448 *height = h;
449
450 return OK;
451}
452
453status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800454 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800455 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800456 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800457 if (res != 0) {
458 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800459 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800460 return res;
461 }
462
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800463 sp<CameraDeviceBase> device =
464 CameraDeviceFactory::createDevice(atoi(cameraId.string()));
465 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800466 return NO_MEMORY;
467 }
468
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800469 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800470 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800471 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800472 }
473
474 int32_t width, height;
475 res = getSmallestSurfaceSize(info, &width, &height);
476 if (res) {
477 return res;
478 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800479 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800480 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800481 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800482 }
483
484 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800485 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
486 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800487
488 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800489}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800490
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800491status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
492 if (mDevice != NULL) {
493 mDevice->disconnect();
494 mDevice.clear();
495 }
496
497 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800498}
499
500
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800501
502status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800503 bool *hasFlash) {
504 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
505 cameraId.string());
506
507 Mutex::Autolock l(mLock);
508 return hasFlashUnitLocked(cameraId, hasFlash);
509
510}
511
512status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800513 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800514 if (!hasFlash) {
515 return BAD_VALUE;
516 }
517
518 camera_info info;
519 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800520 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800521 if (res != 0) {
522 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
523 cameraId.string());
524 return res;
525 }
526
527 CameraMetadata metadata;
528 metadata = info.static_camera_characteristics;
529 camera_metadata_entry flashAvailable =
530 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
531 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
532 *hasFlash = true;
533 }
534
535 return OK;
536}
537
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800538status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800539 status_t res;
540
541 if (mMetadata == NULL) {
542 mMetadata = new CameraMetadata();
543 if (mMetadata == NULL) {
544 return NO_MEMORY;
545 }
546 res = mDevice->createDefaultRequest(
547 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
548 if (res) {
549 return res;
550 }
551 }
552
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800553 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800554 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
555 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
556
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800557 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
558 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
559
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800560 int32_t requestId = 0;
561 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
562
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800563 if (mStreaming) {
564 res = mDevice->setStreamingRequest(*mMetadata);
565 } else {
566 res = mDevice->capture(*mMetadata);
567 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800568 return res;
569}
570
571
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800572
573
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800574status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800575 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800576 bool hasFlash = false;
577
578 Mutex::Autolock l(mLock);
579 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
580
581 // pre-check
582 if (enabled) {
583 // invalid camera?
584 if (res) {
585 return -EINVAL;
586 }
587 // no flash unit?
588 if (!hasFlash) {
589 return -ENOSYS;
590 }
591 // already opened for a different device?
592 if (mDevice != NULL && cameraId != mCameraId) {
593 return BAD_INDEX;
594 }
595 } else if (mDevice == NULL || cameraId != mCameraId) {
596 // disabling the torch mode of an un-opened or different device.
597 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800598 } else {
599 // disabling the torch mode of currently opened device
600 disconnectCameraDevice();
601 mTorchEnabled = false;
602 mCallbacks->torch_mode_status_change(mCallbacks,
603 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
604 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800605 }
606
607 if (mDevice == NULL) {
608 res = connectCameraDevice(cameraId);
609 if (res) {
610 return res;
611 }
612 }
613
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800614 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800615 if (res) {
616 return res;
617 }
618
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800619 mTorchEnabled = true;
620 mCallbacks->torch_mode_status_change(mCallbacks,
621 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800622 return OK;
623}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800624// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800625
626}