blob: 6c237aaa3a77000de071472ee6f6d9f9f1607c58 [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
Ruben Brunkcc776712015-02-17 20:18:47 -0800113 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
114 // This case is needed to avoid state corruption during the following call sequence:
115 // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
116 // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
117 // CameraService::setTorchMode for camera ID 0 continues, calls
118 // CameraFlashlight::setTorchMode
119
120 // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
121 // to avoid other similar race conditions.
122 ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
123 __FUNCTION__, cameraId.string());
124 return -EBUSY;
125 }
126
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800127 if (mFlashControl == NULL) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800128 if (enabled == false) {
129 return OK;
130 }
131
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800132 res = createFlashlightControl(cameraId);
133 if (res) {
134 return res;
135 }
136 res = mFlashControl->setTorchMode(cameraId, enabled);
137 return res;
138 }
139
140 // if flash control already exists, turning on torch mode may fail if it's
141 // tied to another camera device for module v2.3 and below.
142 res = mFlashControl->setTorchMode(cameraId, enabled);
143 if (res == BAD_INDEX) {
144 // flash control is tied to another camera device, need to close it and
145 // try again.
146 mFlashControl.clear();
147 res = createFlashlightControl(cameraId);
148 if (res) {
149 return res;
150 }
151 res = mFlashControl->setTorchMode(cameraId, enabled);
152 }
153
154 return res;
155}
156
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800157status_t CameraFlashlight::findFlashUnits() {
158 Mutex::Autolock l(mLock);
159 status_t res;
160 int32_t numCameras = mCameraModule->getNumberOfCameras();
161
162 mHasFlashlightMap.clear();
163 mFlashlightMapInitialized = false;
164
165 for (int32_t i = 0; i < numCameras; i++) {
166 bool hasFlash = false;
167 String8 id = String8::format("%d", i);
168
169 res = createFlashlightControl(id);
170 if (res) {
171 ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
172 id.string());
173 } else {
174 res = mFlashControl->hasFlashUnit(id, &hasFlash);
175 if (res == -EUSERS || res == -EBUSY) {
176 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
177 "camera devices may be opened", __FUNCTION__,
178 id.string());
179 return res;
180 } else if (res) {
181 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
182 " (%d)", __FUNCTION__, id.string(), strerror(-res),
183 res);
184 }
185
186 mFlashControl.clear();
187 }
188 mHasFlashlightMap.add(id, hasFlash);
189 }
190
191 mFlashlightMapInitialized = true;
192 return OK;
193}
194
195bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800196 status_t res;
197
198 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800199 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800200}
201
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800202bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
203 if (!mFlashlightMapInitialized) {
204 ALOGE("%s: findFlashUnits() must be called before this method.");
205 return false;
206 }
207
208 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
209 if (index == NAME_NOT_FOUND) {
210 ALOGE("%s: camera %s not present when findFlashUnits() was called",
211 __FUNCTION__, cameraId.string());
212 return false;
213 }
214
215 return mHasFlashlightMap.valueAt(index);
216}
217
218status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800219 ALOGV("%s: prepare for device open", __FUNCTION__);
220
221 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800222 if (!mFlashlightMapInitialized) {
223 ALOGE("%s: findFlashUnits() must be called before this method.");
224 return NO_INIT;
225 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800226
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800227 if (mCameraModule->getRawModule()->module_api_version <
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800228 CAMERA_MODULE_API_VERSION_2_4) {
229 // framework is going to open a camera device, all flash light control
230 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800231 mFlashControl.clear();
232
233 if (mOpenedCameraIds.size() == 0) {
234 // notify torch unavailable for all cameras with a flash
235 int numCameras = mCameraModule->getNumberOfCameras();
236 for (int i = 0; i < numCameras; i++) {
237 if (hasFlashUnitLocked(String8::format("%d", i))) {
238 mCallbacks->torch_mode_status_change(mCallbacks,
239 String8::format("%d", i).string(),
240 TORCH_MODE_STATUS_NOT_AVAILABLE);
241 }
242 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800243 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800244
245 // close flash control that may be opened by calling hasFlashUnitLocked.
246 mFlashControl.clear();
247 }
248
249 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
250 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800251 }
252
253 return OK;
254}
255
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800256status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
257 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
258
259 Mutex::Autolock l(mLock);
260 if (!mFlashlightMapInitialized) {
261 ALOGE("%s: findFlashUnits() must be called before this method.");
262 return NO_INIT;
263 }
264
265 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
266 if (index == NAME_NOT_FOUND) {
267 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
268 cameraId.string());
269 } else {
270 mOpenedCameraIds.removeAt(index);
271 }
272
273 // Cannot do anything until all cameras are closed.
274 if (mOpenedCameraIds.size() != 0)
275 return OK;
276
277 if (mCameraModule->getRawModule()->module_api_version <
278 CAMERA_MODULE_API_VERSION_2_4) {
279 // notify torch available for all cameras with a flash
280 int numCameras = mCameraModule->getNumberOfCameras();
281 for (int i = 0; i < numCameras; i++) {
282 if (hasFlashUnitLocked(String8::format("%d", i))) {
283 mCallbacks->torch_mode_status_change(mCallbacks,
284 String8::format("%d", i).string(),
285 TORCH_MODE_STATUS_AVAILABLE_OFF);
286 }
287 }
288 }
289
290 return OK;
291}
292// CameraFlashlight implementation ends
293
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800294
295FlashControlBase::~FlashControlBase() {
296}
297
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800298/////////////////////////////////////////////////////////////////////
299// ModuleFlashControl implementation begins
300// Flash control for camera module v2.4 and above.
301/////////////////////////////////////////////////////////////////////
302ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800303 const camera_module_callbacks_t& callbacks) :
304 mCameraModule(&cameraModule) {
305}
306
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800307ModuleFlashControl::~ModuleFlashControl() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800308}
309
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800310status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800311 if (!hasFlash) {
312 return BAD_VALUE;
313 }
314
315 *hasFlash = false;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800316 Mutex::Autolock l(mLock);
317
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800318 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800319 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800320 &info);
321 if (res != 0) {
322 return res;
323 }
324
325 CameraMetadata metadata;
326 metadata = info.static_camera_characteristics;
327 camera_metadata_entry flashAvailable =
328 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
329 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
330 *hasFlash = true;
331 }
332
333 return OK;
334}
335
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800336status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800337 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
338 cameraId.string(), enabled);
339
340 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800341 return mCameraModule->setTorchMode(cameraId.string(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800342}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800343// ModuleFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800344
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800345/////////////////////////////////////////////////////////////////////
346// CameraDeviceClientFlashControl implementation begins
347// Flash control for camera module <= v2.3 and camera HAL v2-v3
348/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800349CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
350 CameraModule& cameraModule,
351 const camera_module_callbacks_t& callbacks) :
352 mCameraModule(&cameraModule),
353 mCallbacks(&callbacks),
354 mTorchEnabled(false),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800355 mMetadata(NULL),
356 mStreaming(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800357}
358
359CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800360 disconnectCameraDevice();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800361 if (mMetadata) {
362 delete mMetadata;
363 }
364
365 mAnw.clear();
366 mSurfaceTexture.clear();
367 mProducer.clear();
368 mConsumer.clear();
369
370 if (mTorchEnabled) {
371 if (mCallbacks) {
372 ALOGV("%s: notify the framework that torch was turned off",
373 __FUNCTION__);
374 mCallbacks->torch_mode_status_change(mCallbacks,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800375 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800376 }
377 }
378}
379
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800380status_t CameraDeviceClientFlashControl::initializeSurface(
381 sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800382 status_t res;
383 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
384
385 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
386 true, true);
387 if (mSurfaceTexture == NULL) {
388 return NO_MEMORY;
389 }
390
391 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
392 res = mSurfaceTexture->setDefaultBufferSize(width, height);
393 if (res) {
394 return res;
395 }
396 res = mSurfaceTexture->setDefaultBufferFormat(format);
397 if (res) {
398 return res;
399 }
400
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800401 mAnw = new Surface(mProducer, /*useAsync*/ true);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800402 if (mAnw == NULL) {
403 return NO_MEMORY;
404 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800405 res = device->createStream(mAnw, width, height, format, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800406 if (res) {
407 return res;
408 }
409
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800410 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800411 if (res) {
412 return res;
413 }
414
415 return res;
416}
417
418status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
419 const camera_info& info, int32_t *width, int32_t *height) {
420 if (!width || !height) {
421 return BAD_VALUE;
422 }
423
424 int32_t w = INT32_MAX;
425 int32_t h = 1;
426
427 CameraMetadata metadata;
428 metadata = info.static_camera_characteristics;
429 camera_metadata_entry streamConfigs =
430 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
431 for (size_t i = 0; i < streamConfigs.count; i += 4) {
432 int32_t fmt = streamConfigs.data.i32[i];
433 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
434 int32_t ww = streamConfigs.data.i32[i + 1];
435 int32_t hh = streamConfigs.data.i32[i + 2];
436
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800437 if (w * h > ww * hh) {
438 w = ww;
439 h = hh;
440 }
441 }
442 }
443
444 // if stream configuration is not found, try available processed sizes.
445 if (streamConfigs.count == 0) {
446 camera_metadata_entry availableProcessedSizes =
447 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
448 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
449 int32_t ww = availableProcessedSizes.data.i32[i];
450 int32_t hh = availableProcessedSizes.data.i32[i + 1];
451 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800452 w = ww;
453 h = hh;
454 }
455 }
456 }
457
458 if (w == INT32_MAX) {
459 return NAME_NOT_FOUND;
460 }
461
462 *width = w;
463 *height = h;
464
465 return OK;
466}
467
468status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800469 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800470 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800471 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800472 if (res != 0) {
473 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800474 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800475 return res;
476 }
477
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800478 sp<CameraDeviceBase> device =
479 CameraDeviceFactory::createDevice(atoi(cameraId.string()));
480 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800481 return NO_MEMORY;
482 }
483
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800484 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800485 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800486 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800487 }
488
489 int32_t width, height;
490 res = getSmallestSurfaceSize(info, &width, &height);
491 if (res) {
492 return res;
493 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800494 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800495 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800496 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800497 }
498
499 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800500 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
501 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800502
503 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800504}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800505
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800506status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
507 if (mDevice != NULL) {
508 mDevice->disconnect();
509 mDevice.clear();
510 }
511
512 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800513}
514
515
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800516
517status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800518 bool *hasFlash) {
519 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
520 cameraId.string());
521
522 Mutex::Autolock l(mLock);
523 return hasFlashUnitLocked(cameraId, hasFlash);
524
525}
526
527status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800528 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800529 if (!hasFlash) {
530 return BAD_VALUE;
531 }
532
533 camera_info info;
534 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800535 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800536 if (res != 0) {
537 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
538 cameraId.string());
539 return res;
540 }
541
542 CameraMetadata metadata;
543 metadata = info.static_camera_characteristics;
544 camera_metadata_entry flashAvailable =
545 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
546 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
547 *hasFlash = true;
548 }
549
550 return OK;
551}
552
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800553status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800554 status_t res;
555
556 if (mMetadata == NULL) {
557 mMetadata = new CameraMetadata();
558 if (mMetadata == NULL) {
559 return NO_MEMORY;
560 }
561 res = mDevice->createDefaultRequest(
562 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
563 if (res) {
564 return res;
565 }
566 }
567
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800568 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800569 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
570 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
571
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800572 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
573 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
574
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800575 int32_t requestId = 0;
576 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
577
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800578 if (mStreaming) {
579 res = mDevice->setStreamingRequest(*mMetadata);
580 } else {
581 res = mDevice->capture(*mMetadata);
582 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800583 return res;
584}
585
586
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800587
588
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800589status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800590 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800591 bool hasFlash = false;
592
593 Mutex::Autolock l(mLock);
594 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
595
596 // pre-check
597 if (enabled) {
598 // invalid camera?
599 if (res) {
600 return -EINVAL;
601 }
602 // no flash unit?
603 if (!hasFlash) {
604 return -ENOSYS;
605 }
606 // already opened for a different device?
607 if (mDevice != NULL && cameraId != mCameraId) {
608 return BAD_INDEX;
609 }
610 } else if (mDevice == NULL || cameraId != mCameraId) {
611 // disabling the torch mode of an un-opened or different device.
612 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800613 } else {
614 // disabling the torch mode of currently opened device
615 disconnectCameraDevice();
616 mTorchEnabled = false;
617 mCallbacks->torch_mode_status_change(mCallbacks,
618 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
619 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800620 }
621
622 if (mDevice == NULL) {
623 res = connectCameraDevice(cameraId);
624 if (res) {
625 return res;
626 }
627 }
628
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800629 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800630 if (res) {
631 return res;
632 }
633
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800634 mTorchEnabled = true;
635 mCallbacks->torch_mode_status_change(mCallbacks,
636 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800637 return OK;
638}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800639// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800640
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800641
642/////////////////////////////////////////////////////////////////////
643// CameraHardwareInterfaceFlashControl implementation begins
644// Flash control for camera module <= v2.3 and camera HAL v1
645/////////////////////////////////////////////////////////////////////
646CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
647 CameraModule& cameraModule,
648 const camera_module_callbacks_t& callbacks) :
649 mCameraModule(&cameraModule),
650 mCallbacks(&callbacks),
651 mTorchEnabled(false) {
652
653}
654
655CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
656 disconnectCameraDevice();
657
658 mAnw.clear();
659 mSurfaceTexture.clear();
660 mProducer.clear();
661 mConsumer.clear();
662
663 if (mTorchEnabled) {
664 if (mCallbacks) {
665 ALOGV("%s: notify the framework that torch was turned off",
666 __FUNCTION__);
667 mCallbacks->torch_mode_status_change(mCallbacks,
668 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
669 }
670 }
671}
672
673status_t CameraHardwareInterfaceFlashControl::setTorchMode(
674 const String8& cameraId, bool enabled) {
675 Mutex::Autolock l(mLock);
676
677 // pre-check
678 status_t res;
679 if (enabled) {
680 bool hasFlash = false;
681 res = hasFlashUnitLocked(cameraId, &hasFlash);
682 // invalid camera?
683 if (res) {
684 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
685 // another camera device.
686 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
687 }
688 // no flash unit?
689 if (!hasFlash) {
690 return -ENOSYS;
691 }
692 } else if (mDevice == NULL || cameraId != mCameraId) {
693 // disabling the torch mode of an un-opened or different device.
694 return OK;
695 } else {
696 // disabling the torch mode of currently opened device
697 disconnectCameraDevice();
698 mTorchEnabled = false;
699 mCallbacks->torch_mode_status_change(mCallbacks,
700 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
701 return OK;
702 }
703
704 res = startPreviewAndTorch();
705 if (res) {
706 return res;
707 }
708
709 mTorchEnabled = true;
710 mCallbacks->torch_mode_status_change(mCallbacks,
711 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
712 return OK;
713}
714
715status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
716 const String8& cameraId, bool *hasFlash) {
717 Mutex::Autolock l(mLock);
718 return hasFlashUnitLocked(cameraId, hasFlash);
719}
720
721status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
722 const String8& cameraId, bool *hasFlash) {
723 if (!hasFlash) {
724 return BAD_VALUE;
725 }
726
727 status_t res;
728 if (mDevice == NULL) {
729 res = connectCameraDevice(cameraId);
730 if (res) {
731 return res;
732 }
733 }
734
735 if (cameraId != mCameraId) {
736 return BAD_INDEX;
737 }
738
739 const char *flashMode =
740 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
741 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
742 *hasFlash = true;
743 } else {
744 *hasFlash = false;
745 }
746
747 return OK;
748}
749
750status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
751 status_t res = OK;
752 res = mDevice->startPreview();
753 if (res) {
754 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
755 strerror(-res), res);
756 return res;
757 }
758
759 mParameters.set(CameraParameters::KEY_FLASH_MODE,
760 CameraParameters::FLASH_MODE_TORCH);
761
762 return mDevice->setParameters(mParameters);
763}
764
765status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
766 int32_t *width, int32_t *height) {
767 if (!width || !height) {
768 return BAD_VALUE;
769 }
770
771 int32_t w = INT32_MAX;
772 int32_t h = 1;
773 Vector<Size> sizes;
774
775 mParameters.getSupportedPreviewSizes(sizes);
776 for (size_t i = 0; i < sizes.size(); i++) {
777 Size s = sizes[i];
778 if (w * h > s.width * s.height) {
779 w = s.width;
780 h = s.height;
781 }
782 }
783
784 if (w == INT32_MAX) {
785 return NAME_NOT_FOUND;
786 }
787
788 *width = w;
789 *height = h;
790
791 return OK;
792}
793
794status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
795 sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
796 status_t res;
797 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
798
799 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
800 true, true);
801 if (mSurfaceTexture == NULL) {
802 return NO_MEMORY;
803 }
804
805 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
806 res = mSurfaceTexture->setDefaultBufferSize(width, height);
807 if (res) {
808 return res;
809 }
810 res = mSurfaceTexture->setDefaultBufferFormat(format);
811 if (res) {
812 return res;
813 }
814
815 mAnw = new Surface(mProducer, /*useAsync*/ true);
816 if (mAnw == NULL) {
817 return NO_MEMORY;
818 }
819
820 res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA);
821 if (res) {
822 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
823 return res;
824 }
825
826 return device->setPreviewWindow(mAnw);
827}
828
829status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
830 const String8& cameraId) {
831 sp<CameraHardwareInterface> device =
832 new CameraHardwareInterface(cameraId.string());
833
834 status_t res = device->initialize(mCameraModule);
835 if (res) {
836 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
837 cameraId.string());
838 return res;
839 }
840
841 // need to set __get_memory in set_callbacks().
842 device->setCallbacks(NULL, NULL, NULL, NULL);
843
844 mParameters = device->getParameters();
845
846 int32_t width, height;
847 res = getSmallestSurfaceSize(&width, &height);
848 if (res) {
849 ALOGE("%s: failed to get smallest surface size for camera %s",
850 __FUNCTION__, cameraId.string());
851 return res;
852 }
853
854 res = initializePreviewWindow(device, width, height);
855 if (res) {
856 ALOGE("%s: failed to initialize preview window for camera %s",
857 __FUNCTION__, cameraId.string());
858 return res;
859 }
860
861 mCameraId = cameraId;
862 mDevice = device;
863 return OK;
864}
865
866status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
867 if (mDevice == NULL) {
868 return OK;
869 }
870
871 mParameters.set(CameraParameters::KEY_FLASH_MODE,
872 CameraParameters::FLASH_MODE_OFF);
873 mDevice->setParameters(mParameters);
874 mDevice->stopPreview();
875 status_t res = native_window_api_disconnect(mAnw.get(),
876 NATIVE_WINDOW_API_CAMERA);
877 if (res) {
878 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
879 __FUNCTION__, strerror(-res), res);
880 }
881 mDevice->setPreviewWindow(NULL);
882 mDevice->release();
883
884 return OK;
885}
886// CameraHardwareInterfaceFlashControl implementation ends
887
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800888}