blob: 8e894cd37cb40cc93cc71f20f62e8ce22bbb9800 [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 Chend231fd62015-02-25 16:04:22 -080092 mFlashControl =
93 new CameraHardwareInterfaceFlashControl(*mCameraModule,
94 *mCallbacks);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080095 }
96 }
97
98 return OK;
99}
100
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800101status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
102 if (!mFlashlightMapInitialized) {
103 ALOGE("%s: findFlashUnits() must be called before this method.");
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800104 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) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800114 if (enabled == false) {
115 return OK;
116 }
117
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800118 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
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800143status_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) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800182 status_t res;
183
184 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800185 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800186}
187
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800188bool 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) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800205 ALOGV("%s: prepare for device open", __FUNCTION__);
206
207 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800208 if (!mFlashlightMapInitialized) {
209 ALOGE("%s: findFlashUnits() must be called before this method.");
210 return NO_INIT;
211 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800212
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800213 if (mCameraModule->getRawModule()->module_api_version <
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800214 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.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800217 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 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800229 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800230
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);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800237 }
238
239 return OK;
240}
241
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800242status_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
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800280
281FlashControlBase::~FlashControlBase() {
282}
283
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800284/////////////////////////////////////////////////////////////////////
285// ModuleFlashControl implementation begins
286// Flash control for camera module v2.4 and above.
287/////////////////////////////////////////////////////////////////////
288ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800289 const camera_module_callbacks_t& callbacks) :
290 mCameraModule(&cameraModule) {
291}
292
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800293ModuleFlashControl::~ModuleFlashControl() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800294}
295
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800296status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800297 if (!hasFlash) {
298 return BAD_VALUE;
299 }
300
301 *hasFlash = false;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800302 Mutex::Autolock l(mLock);
303
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800304 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800305 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800306 &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
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800322status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800323 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
324 cameraId.string(), enabled);
325
326 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800327 return mCameraModule->setTorchMode(cameraId.string(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800328}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800329// ModuleFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800330
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800331/////////////////////////////////////////////////////////////////////
332// CameraDeviceClientFlashControl implementation begins
333// Flash control for camera module <= v2.3 and camera HAL v2-v3
334/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800335CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
336 CameraModule& cameraModule,
337 const camera_module_callbacks_t& callbacks) :
338 mCameraModule(&cameraModule),
339 mCallbacks(&callbacks),
340 mTorchEnabled(false),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800341 mMetadata(NULL),
342 mStreaming(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800343}
344
345CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800346 disconnectCameraDevice();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800347 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,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800361 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800362 }
363 }
364}
365
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800366status_t CameraDeviceClientFlashControl::initializeSurface(
367 sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800368 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
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800387 mAnw = new Surface(mProducer, /*useAsync*/ true);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800388 if (mAnw == NULL) {
389 return NO_MEMORY;
390 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800391 res = device->createStream(mAnw, width, height, format, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800392 if (res) {
393 return res;
394 }
395
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800396 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800397 if (res) {
398 return res;
399 }
400
401 return res;
402}
403
404status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
405 const camera_info& info, int32_t *width, int32_t *height) {
406 if (!width || !height) {
407 return BAD_VALUE;
408 }
409
410 int32_t w = INT32_MAX;
411 int32_t h = 1;
412
413 CameraMetadata metadata;
414 metadata = info.static_camera_characteristics;
415 camera_metadata_entry streamConfigs =
416 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
417 for (size_t i = 0; i < streamConfigs.count; i += 4) {
418 int32_t fmt = streamConfigs.data.i32[i];
419 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
420 int32_t ww = streamConfigs.data.i32[i + 1];
421 int32_t hh = streamConfigs.data.i32[i + 2];
422
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800423 if (w * h > ww * hh) {
424 w = ww;
425 h = hh;
426 }
427 }
428 }
429
430 // if stream configuration is not found, try available processed sizes.
431 if (streamConfigs.count == 0) {
432 camera_metadata_entry availableProcessedSizes =
433 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
434 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
435 int32_t ww = availableProcessedSizes.data.i32[i];
436 int32_t hh = availableProcessedSizes.data.i32[i + 1];
437 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800438 w = ww;
439 h = hh;
440 }
441 }
442 }
443
444 if (w == INT32_MAX) {
445 return NAME_NOT_FOUND;
446 }
447
448 *width = w;
449 *height = h;
450
451 return OK;
452}
453
454status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800455 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800456 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800457 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800458 if (res != 0) {
459 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800460 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800461 return res;
462 }
463
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800464 sp<CameraDeviceBase> device =
465 CameraDeviceFactory::createDevice(atoi(cameraId.string()));
466 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800467 return NO_MEMORY;
468 }
469
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800470 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800471 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800472 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800473 }
474
475 int32_t width, height;
476 res = getSmallestSurfaceSize(info, &width, &height);
477 if (res) {
478 return res;
479 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800480 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800481 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800482 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800483 }
484
485 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800486 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
487 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800488
489 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800490}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800491
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800492status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
493 if (mDevice != NULL) {
494 mDevice->disconnect();
495 mDevice.clear();
496 }
497
498 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800499}
500
501
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800502
503status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800504 bool *hasFlash) {
505 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
506 cameraId.string());
507
508 Mutex::Autolock l(mLock);
509 return hasFlashUnitLocked(cameraId, hasFlash);
510
511}
512
513status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800514 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800515 if (!hasFlash) {
516 return BAD_VALUE;
517 }
518
519 camera_info info;
520 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800521 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800522 if (res != 0) {
523 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
524 cameraId.string());
525 return res;
526 }
527
528 CameraMetadata metadata;
529 metadata = info.static_camera_characteristics;
530 camera_metadata_entry flashAvailable =
531 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
532 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
533 *hasFlash = true;
534 }
535
536 return OK;
537}
538
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800539status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800540 status_t res;
541
542 if (mMetadata == NULL) {
543 mMetadata = new CameraMetadata();
544 if (mMetadata == NULL) {
545 return NO_MEMORY;
546 }
547 res = mDevice->createDefaultRequest(
548 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
549 if (res) {
550 return res;
551 }
552 }
553
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800554 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800555 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
556 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
557
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800558 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
559 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
560
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800561 int32_t requestId = 0;
562 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
563
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800564 if (mStreaming) {
565 res = mDevice->setStreamingRequest(*mMetadata);
566 } else {
567 res = mDevice->capture(*mMetadata);
568 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800569 return res;
570}
571
572
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800573
574
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800575status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800576 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800577 bool hasFlash = false;
578
579 Mutex::Autolock l(mLock);
580 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
581
582 // pre-check
583 if (enabled) {
584 // invalid camera?
585 if (res) {
586 return -EINVAL;
587 }
588 // no flash unit?
589 if (!hasFlash) {
590 return -ENOSYS;
591 }
592 // already opened for a different device?
593 if (mDevice != NULL && cameraId != mCameraId) {
594 return BAD_INDEX;
595 }
596 } else if (mDevice == NULL || cameraId != mCameraId) {
597 // disabling the torch mode of an un-opened or different device.
598 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800599 } else {
600 // disabling the torch mode of currently opened device
601 disconnectCameraDevice();
602 mTorchEnabled = false;
603 mCallbacks->torch_mode_status_change(mCallbacks,
604 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
605 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800606 }
607
608 if (mDevice == NULL) {
609 res = connectCameraDevice(cameraId);
610 if (res) {
611 return res;
612 }
613 }
614
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800615 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800616 if (res) {
617 return res;
618 }
619
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800620 mTorchEnabled = true;
621 mCallbacks->torch_mode_status_change(mCallbacks,
622 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800623 return OK;
624}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800625// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800626
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800627
628/////////////////////////////////////////////////////////////////////
629// CameraHardwareInterfaceFlashControl implementation begins
630// Flash control for camera module <= v2.3 and camera HAL v1
631/////////////////////////////////////////////////////////////////////
632CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
633 CameraModule& cameraModule,
634 const camera_module_callbacks_t& callbacks) :
635 mCameraModule(&cameraModule),
636 mCallbacks(&callbacks),
637 mTorchEnabled(false) {
638
639}
640
641CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
642 disconnectCameraDevice();
643
644 mAnw.clear();
645 mSurfaceTexture.clear();
646 mProducer.clear();
647 mConsumer.clear();
648
649 if (mTorchEnabled) {
650 if (mCallbacks) {
651 ALOGV("%s: notify the framework that torch was turned off",
652 __FUNCTION__);
653 mCallbacks->torch_mode_status_change(mCallbacks,
654 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
655 }
656 }
657}
658
659status_t CameraHardwareInterfaceFlashControl::setTorchMode(
660 const String8& cameraId, bool enabled) {
661 Mutex::Autolock l(mLock);
662
663 // pre-check
664 status_t res;
665 if (enabled) {
666 bool hasFlash = false;
667 res = hasFlashUnitLocked(cameraId, &hasFlash);
668 // invalid camera?
669 if (res) {
670 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
671 // another camera device.
672 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
673 }
674 // no flash unit?
675 if (!hasFlash) {
676 return -ENOSYS;
677 }
678 } else if (mDevice == NULL || cameraId != mCameraId) {
679 // disabling the torch mode of an un-opened or different device.
680 return OK;
681 } else {
682 // disabling the torch mode of currently opened device
683 disconnectCameraDevice();
684 mTorchEnabled = false;
685 mCallbacks->torch_mode_status_change(mCallbacks,
686 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
687 return OK;
688 }
689
690 res = startPreviewAndTorch();
691 if (res) {
692 return res;
693 }
694
695 mTorchEnabled = true;
696 mCallbacks->torch_mode_status_change(mCallbacks,
697 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
698 return OK;
699}
700
701status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
702 const String8& cameraId, bool *hasFlash) {
703 Mutex::Autolock l(mLock);
704 return hasFlashUnitLocked(cameraId, hasFlash);
705}
706
707status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
708 const String8& cameraId, bool *hasFlash) {
709 if (!hasFlash) {
710 return BAD_VALUE;
711 }
712
713 status_t res;
714 if (mDevice == NULL) {
715 res = connectCameraDevice(cameraId);
716 if (res) {
717 return res;
718 }
719 }
720
721 if (cameraId != mCameraId) {
722 return BAD_INDEX;
723 }
724
725 const char *flashMode =
726 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
727 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
728 *hasFlash = true;
729 } else {
730 *hasFlash = false;
731 }
732
733 return OK;
734}
735
736status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
737 status_t res = OK;
738 res = mDevice->startPreview();
739 if (res) {
740 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
741 strerror(-res), res);
742 return res;
743 }
744
745 mParameters.set(CameraParameters::KEY_FLASH_MODE,
746 CameraParameters::FLASH_MODE_TORCH);
747
748 return mDevice->setParameters(mParameters);
749}
750
751status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
752 int32_t *width, int32_t *height) {
753 if (!width || !height) {
754 return BAD_VALUE;
755 }
756
757 int32_t w = INT32_MAX;
758 int32_t h = 1;
759 Vector<Size> sizes;
760
761 mParameters.getSupportedPreviewSizes(sizes);
762 for (size_t i = 0; i < sizes.size(); i++) {
763 Size s = sizes[i];
764 if (w * h > s.width * s.height) {
765 w = s.width;
766 h = s.height;
767 }
768 }
769
770 if (w == INT32_MAX) {
771 return NAME_NOT_FOUND;
772 }
773
774 *width = w;
775 *height = h;
776
777 return OK;
778}
779
780status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
781 sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
782 status_t res;
783 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
784
785 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
786 true, true);
787 if (mSurfaceTexture == NULL) {
788 return NO_MEMORY;
789 }
790
791 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
792 res = mSurfaceTexture->setDefaultBufferSize(width, height);
793 if (res) {
794 return res;
795 }
796 res = mSurfaceTexture->setDefaultBufferFormat(format);
797 if (res) {
798 return res;
799 }
800
801 mAnw = new Surface(mProducer, /*useAsync*/ true);
802 if (mAnw == NULL) {
803 return NO_MEMORY;
804 }
805
806 res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA);
807 if (res) {
808 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
809 return res;
810 }
811
812 return device->setPreviewWindow(mAnw);
813}
814
815status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
816 const String8& cameraId) {
817 sp<CameraHardwareInterface> device =
818 new CameraHardwareInterface(cameraId.string());
819
820 status_t res = device->initialize(mCameraModule);
821 if (res) {
822 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
823 cameraId.string());
824 return res;
825 }
826
827 // need to set __get_memory in set_callbacks().
828 device->setCallbacks(NULL, NULL, NULL, NULL);
829
830 mParameters = device->getParameters();
831
832 int32_t width, height;
833 res = getSmallestSurfaceSize(&width, &height);
834 if (res) {
835 ALOGE("%s: failed to get smallest surface size for camera %s",
836 __FUNCTION__, cameraId.string());
837 return res;
838 }
839
840 res = initializePreviewWindow(device, width, height);
841 if (res) {
842 ALOGE("%s: failed to initialize preview window for camera %s",
843 __FUNCTION__, cameraId.string());
844 return res;
845 }
846
847 mCameraId = cameraId;
848 mDevice = device;
849 return OK;
850}
851
852status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
853 if (mDevice == NULL) {
854 return OK;
855 }
856
857 mParameters.set(CameraParameters::KEY_FLASH_MODE,
858 CameraParameters::FLASH_MODE_OFF);
859 mDevice->setParameters(mParameters);
860 mDevice->stopPreview();
861 status_t res = native_window_api_disconnect(mAnw.get(),
862 NATIVE_WINDOW_API_CAMERA);
863 if (res) {
864 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
865 __FUNCTION__, strerror(-res), res);
866 }
867 mDevice->setPreviewWindow(NULL);
868 mDevice->release();
869
870 return OK;
871}
872// CameraHardwareInterfaceFlashControl implementation ends
873
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800874}