blob: b3449e2e9623e8a04ca62d7fa4508de54ff89fcc [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 }
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800391 res = device->createStream(mAnw, width, height, format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700392 HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800393 if (res) {
394 return res;
395 }
396
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800397 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800398 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
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800424 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) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800439 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(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800456 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800457 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800458 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800459 if (res != 0) {
460 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800461 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800462 return res;
463 }
464
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800465 sp<CameraDeviceBase> device =
466 CameraDeviceFactory::createDevice(atoi(cameraId.string()));
467 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800468 return NO_MEMORY;
469 }
470
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800471 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800472 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800473 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800474 }
475
476 int32_t width, height;
477 res = getSmallestSurfaceSize(info, &width, &height);
478 if (res) {
479 return res;
480 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800481 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800482 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800483 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800484 }
485
486 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800487 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
488 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800489
490 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800491}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800492
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800493status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
494 if (mDevice != NULL) {
495 mDevice->disconnect();
496 mDevice.clear();
497 }
498
499 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800500}
501
502
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800503
504status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800505 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(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800515 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800516 if (!hasFlash) {
517 return BAD_VALUE;
518 }
519
520 camera_info info;
521 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800522 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800523 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
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800540status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800541 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
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800555 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800556 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
557 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
558
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800559 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
560 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
561
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800562 int32_t requestId = 0;
563 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
564
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800565 if (mStreaming) {
566 res = mDevice->setStreamingRequest(*mMetadata);
567 } else {
568 res = mDevice->capture(*mMetadata);
569 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800570 return res;
571}
572
573
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800574
575
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800576status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800577 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800578 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;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800600 } 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;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800607 }
608
609 if (mDevice == NULL) {
610 res = connectCameraDevice(cameraId);
611 if (res) {
612 return res;
613 }
614 }
615
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800616 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800617 if (res) {
618 return res;
619 }
620
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800621 mTorchEnabled = true;
622 mCallbacks->torch_mode_status_change(mCallbacks,
623 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800624 return OK;
625}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800626// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800627
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800628
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
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800875}