blob: 8613ac61378ff7aa6d59792057a9329fce6d20b3 [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
Chien-Yu Chen676b21b2015-02-24 10:28:19 -080058 if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -080059 mFlashControl = new ModuleFlashControl(*mCameraModule, *mCallbacks);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080060 if (mFlashControl == NULL) {
61 ALOGV("%s: cannot create flash control for module api v2.4+",
62 __FUNCTION__);
63 return NO_MEMORY;
64 }
65 } else {
66 uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
67
Chien-Yu Chen676b21b2015-02-24 10:28:19 -080068 if (mCameraModule->getModuleApiVersion() >=
69 CAMERA_MODULE_API_VERSION_2_0) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080070 camera_info info;
71 res = mCameraModule->getCameraInfo(
72 atoi(String8(cameraId).string()), &info);
73 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -080074 ALOGE("%s: failed to get camera info for camera %s",
Chien-Yu Chen3068d732015-02-09 13:29:57 -080075 __FUNCTION__, cameraId.string());
76 return res;
77 }
78 deviceVersion = info.device_version;
79 }
80
81 if (deviceVersion >= CAMERA_DEVICE_API_VERSION_2_0) {
82 CameraDeviceClientFlashControl *flashControl =
83 new CameraDeviceClientFlashControl(*mCameraModule,
84 *mCallbacks);
85 if (!flashControl) {
86 return NO_MEMORY;
87 }
88
89 mFlashControl = flashControl;
Chien-Yu Chen88da5262015-02-17 13:56:46 -080090 } else {
Chien-Yu Chend231fd62015-02-25 16:04:22 -080091 mFlashControl =
92 new CameraHardwareInterfaceFlashControl(*mCameraModule,
93 *mCallbacks);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080094 }
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
Ruben Brunkcc776712015-02-17 20:18:47 -0800112 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
113 // This case is needed to avoid state corruption during the following call sequence:
114 // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
115 // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
116 // CameraService::setTorchMode for camera ID 0 continues, calls
117 // CameraFlashlight::setTorchMode
118
119 // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
120 // to avoid other similar race conditions.
121 ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
122 __FUNCTION__, cameraId.string());
123 return -EBUSY;
124 }
125
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800126 if (mFlashControl == NULL) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800127 if (enabled == false) {
128 return OK;
129 }
130
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800131 res = createFlashlightControl(cameraId);
132 if (res) {
133 return res;
134 }
135 res = mFlashControl->setTorchMode(cameraId, enabled);
136 return res;
137 }
138
139 // if flash control already exists, turning on torch mode may fail if it's
140 // tied to another camera device for module v2.3 and below.
141 res = mFlashControl->setTorchMode(cameraId, enabled);
142 if (res == BAD_INDEX) {
143 // flash control is tied to another camera device, need to close it and
144 // try again.
145 mFlashControl.clear();
146 res = createFlashlightControl(cameraId);
147 if (res) {
148 return res;
149 }
150 res = mFlashControl->setTorchMode(cameraId, enabled);
151 }
152
153 return res;
154}
155
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800156status_t CameraFlashlight::findFlashUnits() {
157 Mutex::Autolock l(mLock);
158 status_t res;
159 int32_t numCameras = mCameraModule->getNumberOfCameras();
160
161 mHasFlashlightMap.clear();
162 mFlashlightMapInitialized = false;
163
164 for (int32_t i = 0; i < numCameras; i++) {
165 bool hasFlash = false;
166 String8 id = String8::format("%d", i);
167
168 res = createFlashlightControl(id);
169 if (res) {
170 ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
171 id.string());
172 } else {
173 res = mFlashControl->hasFlashUnit(id, &hasFlash);
174 if (res == -EUSERS || res == -EBUSY) {
175 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
176 "camera devices may be opened", __FUNCTION__,
177 id.string());
178 return res;
179 } else if (res) {
180 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
181 " (%d)", __FUNCTION__, id.string(), strerror(-res),
182 res);
183 }
184
185 mFlashControl.clear();
186 }
187 mHasFlashlightMap.add(id, hasFlash);
188 }
189
190 mFlashlightMapInitialized = true;
191 return OK;
192}
193
194bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800195 status_t res;
196
197 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800198 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800199}
200
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800201bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
202 if (!mFlashlightMapInitialized) {
203 ALOGE("%s: findFlashUnits() must be called before this method.");
204 return false;
205 }
206
207 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
208 if (index == NAME_NOT_FOUND) {
209 ALOGE("%s: camera %s not present when findFlashUnits() was called",
210 __FUNCTION__, cameraId.string());
211 return false;
212 }
213
214 return mHasFlashlightMap.valueAt(index);
215}
216
217status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800218 ALOGV("%s: prepare for device open", __FUNCTION__);
219
220 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800221 if (!mFlashlightMapInitialized) {
222 ALOGE("%s: findFlashUnits() must be called before this method.");
223 return NO_INIT;
224 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800225
Chien-Yu Chen676b21b2015-02-24 10:28:19 -0800226 if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800227 // framework is going to open a camera device, all flash light control
228 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800229 mFlashControl.clear();
230
231 if (mOpenedCameraIds.size() == 0) {
232 // notify torch unavailable for all cameras with a flash
233 int numCameras = mCameraModule->getNumberOfCameras();
234 for (int i = 0; i < numCameras; i++) {
235 if (hasFlashUnitLocked(String8::format("%d", i))) {
236 mCallbacks->torch_mode_status_change(mCallbacks,
237 String8::format("%d", i).string(),
238 TORCH_MODE_STATUS_NOT_AVAILABLE);
239 }
240 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800241 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800242
243 // close flash control that may be opened by calling hasFlashUnitLocked.
244 mFlashControl.clear();
245 }
246
247 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
248 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800249 }
250
251 return OK;
252}
253
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800254status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
255 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
256
257 Mutex::Autolock l(mLock);
258 if (!mFlashlightMapInitialized) {
259 ALOGE("%s: findFlashUnits() must be called before this method.");
260 return NO_INIT;
261 }
262
263 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
264 if (index == NAME_NOT_FOUND) {
265 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
266 cameraId.string());
267 } else {
268 mOpenedCameraIds.removeAt(index);
269 }
270
271 // Cannot do anything until all cameras are closed.
272 if (mOpenedCameraIds.size() != 0)
273 return OK;
274
Chien-Yu Chen676b21b2015-02-24 10:28:19 -0800275 if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800276 // notify torch available for all cameras with a flash
277 int numCameras = mCameraModule->getNumberOfCameras();
278 for (int i = 0; i < numCameras; i++) {
279 if (hasFlashUnitLocked(String8::format("%d", i))) {
280 mCallbacks->torch_mode_status_change(mCallbacks,
281 String8::format("%d", i).string(),
282 TORCH_MODE_STATUS_AVAILABLE_OFF);
283 }
284 }
285 }
286
287 return OK;
288}
289// CameraFlashlight implementation ends
290
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800291
292FlashControlBase::~FlashControlBase() {
293}
294
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800295/////////////////////////////////////////////////////////////////////
296// ModuleFlashControl implementation begins
297// Flash control for camera module v2.4 and above.
298/////////////////////////////////////////////////////////////////////
299ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800300 const camera_module_callbacks_t& callbacks) :
301 mCameraModule(&cameraModule) {
302}
303
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800304ModuleFlashControl::~ModuleFlashControl() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800305}
306
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800307status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800308 if (!hasFlash) {
309 return BAD_VALUE;
310 }
311
312 *hasFlash = false;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800313 Mutex::Autolock l(mLock);
314
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800315 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800316 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800317 &info);
318 if (res != 0) {
319 return res;
320 }
321
322 CameraMetadata metadata;
323 metadata = info.static_camera_characteristics;
324 camera_metadata_entry flashAvailable =
325 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
326 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
327 *hasFlash = true;
328 }
329
330 return OK;
331}
332
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800333status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800334 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
335 cameraId.string(), enabled);
336
337 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800338 return mCameraModule->setTorchMode(cameraId.string(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800339}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800340// ModuleFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800341
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800342/////////////////////////////////////////////////////////////////////
343// CameraDeviceClientFlashControl implementation begins
344// Flash control for camera module <= v2.3 and camera HAL v2-v3
345/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800346CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
347 CameraModule& cameraModule,
348 const camera_module_callbacks_t& callbacks) :
349 mCameraModule(&cameraModule),
350 mCallbacks(&callbacks),
351 mTorchEnabled(false),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800352 mMetadata(NULL),
353 mStreaming(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800354}
355
356CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800357 disconnectCameraDevice();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800358 if (mMetadata) {
359 delete mMetadata;
360 }
361
362 mAnw.clear();
363 mSurfaceTexture.clear();
364 mProducer.clear();
365 mConsumer.clear();
366
367 if (mTorchEnabled) {
368 if (mCallbacks) {
369 ALOGV("%s: notify the framework that torch was turned off",
370 __FUNCTION__);
371 mCallbacks->torch_mode_status_change(mCallbacks,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800372 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800373 }
374 }
375}
376
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800377status_t CameraDeviceClientFlashControl::initializeSurface(
378 sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800379 status_t res;
380 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
381
382 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
383 true, true);
384 if (mSurfaceTexture == NULL) {
385 return NO_MEMORY;
386 }
387
388 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
389 res = mSurfaceTexture->setDefaultBufferSize(width, height);
390 if (res) {
391 return res;
392 }
393 res = mSurfaceTexture->setDefaultBufferFormat(format);
394 if (res) {
395 return res;
396 }
397
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800398 mAnw = new Surface(mProducer, /*useAsync*/ true);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800399 if (mAnw == NULL) {
400 return NO_MEMORY;
401 }
Eino-Ville Talvala3d82c0d2015-02-23 15:19:19 -0800402 res = device->createStream(mAnw, width, height, format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700403 HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800404 if (res) {
405 return res;
406 }
407
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800408 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800409 if (res) {
410 return res;
411 }
412
413 return res;
414}
415
416status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
417 const camera_info& info, int32_t *width, int32_t *height) {
418 if (!width || !height) {
419 return BAD_VALUE;
420 }
421
422 int32_t w = INT32_MAX;
423 int32_t h = 1;
424
425 CameraMetadata metadata;
426 metadata = info.static_camera_characteristics;
427 camera_metadata_entry streamConfigs =
428 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
429 for (size_t i = 0; i < streamConfigs.count; i += 4) {
430 int32_t fmt = streamConfigs.data.i32[i];
431 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
432 int32_t ww = streamConfigs.data.i32[i + 1];
433 int32_t hh = streamConfigs.data.i32[i + 2];
434
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800435 if (w * h > ww * hh) {
436 w = ww;
437 h = hh;
438 }
439 }
440 }
441
442 // if stream configuration is not found, try available processed sizes.
443 if (streamConfigs.count == 0) {
444 camera_metadata_entry availableProcessedSizes =
445 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
446 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
447 int32_t ww = availableProcessedSizes.data.i32[i];
448 int32_t hh = availableProcessedSizes.data.i32[i + 1];
449 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800450 w = ww;
451 h = hh;
452 }
453 }
454 }
455
456 if (w == INT32_MAX) {
457 return NAME_NOT_FOUND;
458 }
459
460 *width = w;
461 *height = h;
462
463 return OK;
464}
465
466status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800467 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800468 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800469 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800470 if (res != 0) {
471 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800472 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800473 return res;
474 }
475
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800476 sp<CameraDeviceBase> device =
477 CameraDeviceFactory::createDevice(atoi(cameraId.string()));
478 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800479 return NO_MEMORY;
480 }
481
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800482 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800483 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800484 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800485 }
486
487 int32_t width, height;
488 res = getSmallestSurfaceSize(info, &width, &height);
489 if (res) {
490 return res;
491 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800492 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800493 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800494 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800495 }
496
497 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800498 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
499 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800500
501 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800502}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800503
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800504status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
505 if (mDevice != NULL) {
506 mDevice->disconnect();
507 mDevice.clear();
508 }
509
510 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800511}
512
513
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800514
515status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800516 bool *hasFlash) {
517 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
518 cameraId.string());
519
520 Mutex::Autolock l(mLock);
521 return hasFlashUnitLocked(cameraId, hasFlash);
522
523}
524
525status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800526 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800527 if (!hasFlash) {
528 return BAD_VALUE;
529 }
530
531 camera_info info;
532 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800533 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800534 if (res != 0) {
535 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
536 cameraId.string());
537 return res;
538 }
539
540 CameraMetadata metadata;
541 metadata = info.static_camera_characteristics;
542 camera_metadata_entry flashAvailable =
543 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
544 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
545 *hasFlash = true;
546 }
547
548 return OK;
549}
550
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800551status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800552 status_t res;
553
554 if (mMetadata == NULL) {
555 mMetadata = new CameraMetadata();
556 if (mMetadata == NULL) {
557 return NO_MEMORY;
558 }
559 res = mDevice->createDefaultRequest(
560 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
561 if (res) {
562 return res;
563 }
564 }
565
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800566 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800567 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
568 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
569
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800570 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
571 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
572
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800573 int32_t requestId = 0;
574 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
575
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800576 if (mStreaming) {
577 res = mDevice->setStreamingRequest(*mMetadata);
578 } else {
579 res = mDevice->capture(*mMetadata);
580 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800581 return res;
582}
583
584
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800585
586
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800587status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800588 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800589 bool hasFlash = false;
590
591 Mutex::Autolock l(mLock);
592 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
593
594 // pre-check
595 if (enabled) {
596 // invalid camera?
597 if (res) {
598 return -EINVAL;
599 }
600 // no flash unit?
601 if (!hasFlash) {
602 return -ENOSYS;
603 }
604 // already opened for a different device?
605 if (mDevice != NULL && cameraId != mCameraId) {
606 return BAD_INDEX;
607 }
608 } else if (mDevice == NULL || cameraId != mCameraId) {
609 // disabling the torch mode of an un-opened or different device.
610 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800611 } else {
612 // disabling the torch mode of currently opened device
613 disconnectCameraDevice();
614 mTorchEnabled = false;
615 mCallbacks->torch_mode_status_change(mCallbacks,
616 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
617 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800618 }
619
620 if (mDevice == NULL) {
621 res = connectCameraDevice(cameraId);
622 if (res) {
623 return res;
624 }
625 }
626
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800627 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800628 if (res) {
629 return res;
630 }
631
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800632 mTorchEnabled = true;
633 mCallbacks->torch_mode_status_change(mCallbacks,
634 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800635 return OK;
636}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800637// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800638
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800639
640/////////////////////////////////////////////////////////////////////
641// CameraHardwareInterfaceFlashControl implementation begins
642// Flash control for camera module <= v2.3 and camera HAL v1
643/////////////////////////////////////////////////////////////////////
644CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
645 CameraModule& cameraModule,
646 const camera_module_callbacks_t& callbacks) :
647 mCameraModule(&cameraModule),
648 mCallbacks(&callbacks),
649 mTorchEnabled(false) {
650
651}
652
653CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
654 disconnectCameraDevice();
655
656 mAnw.clear();
657 mSurfaceTexture.clear();
658 mProducer.clear();
659 mConsumer.clear();
660
661 if (mTorchEnabled) {
662 if (mCallbacks) {
663 ALOGV("%s: notify the framework that torch was turned off",
664 __FUNCTION__);
665 mCallbacks->torch_mode_status_change(mCallbacks,
666 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
667 }
668 }
669}
670
671status_t CameraHardwareInterfaceFlashControl::setTorchMode(
672 const String8& cameraId, bool enabled) {
673 Mutex::Autolock l(mLock);
674
675 // pre-check
676 status_t res;
677 if (enabled) {
678 bool hasFlash = false;
679 res = hasFlashUnitLocked(cameraId, &hasFlash);
680 // invalid camera?
681 if (res) {
682 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
683 // another camera device.
684 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
685 }
686 // no flash unit?
687 if (!hasFlash) {
688 return -ENOSYS;
689 }
690 } else if (mDevice == NULL || cameraId != mCameraId) {
691 // disabling the torch mode of an un-opened or different device.
692 return OK;
693 } else {
694 // disabling the torch mode of currently opened device
695 disconnectCameraDevice();
696 mTorchEnabled = false;
697 mCallbacks->torch_mode_status_change(mCallbacks,
698 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
699 return OK;
700 }
701
702 res = startPreviewAndTorch();
703 if (res) {
704 return res;
705 }
706
707 mTorchEnabled = true;
708 mCallbacks->torch_mode_status_change(mCallbacks,
709 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
710 return OK;
711}
712
713status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
714 const String8& cameraId, bool *hasFlash) {
715 Mutex::Autolock l(mLock);
716 return hasFlashUnitLocked(cameraId, hasFlash);
717}
718
719status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
720 const String8& cameraId, bool *hasFlash) {
721 if (!hasFlash) {
722 return BAD_VALUE;
723 }
724
725 status_t res;
726 if (mDevice == NULL) {
727 res = connectCameraDevice(cameraId);
728 if (res) {
729 return res;
730 }
731 }
732
733 if (cameraId != mCameraId) {
734 return BAD_INDEX;
735 }
736
737 const char *flashMode =
738 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
739 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
740 *hasFlash = true;
741 } else {
742 *hasFlash = false;
743 }
744
745 return OK;
746}
747
748status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
749 status_t res = OK;
750 res = mDevice->startPreview();
751 if (res) {
752 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
753 strerror(-res), res);
754 return res;
755 }
756
757 mParameters.set(CameraParameters::KEY_FLASH_MODE,
758 CameraParameters::FLASH_MODE_TORCH);
759
760 return mDevice->setParameters(mParameters);
761}
762
763status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
764 int32_t *width, int32_t *height) {
765 if (!width || !height) {
766 return BAD_VALUE;
767 }
768
769 int32_t w = INT32_MAX;
770 int32_t h = 1;
771 Vector<Size> sizes;
772
773 mParameters.getSupportedPreviewSizes(sizes);
774 for (size_t i = 0; i < sizes.size(); i++) {
775 Size s = sizes[i];
776 if (w * h > s.width * s.height) {
777 w = s.width;
778 h = s.height;
779 }
780 }
781
782 if (w == INT32_MAX) {
783 return NAME_NOT_FOUND;
784 }
785
786 *width = w;
787 *height = h;
788
789 return OK;
790}
791
792status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
793 sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
794 status_t res;
795 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
796
797 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
798 true, true);
799 if (mSurfaceTexture == NULL) {
800 return NO_MEMORY;
801 }
802
803 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
804 res = mSurfaceTexture->setDefaultBufferSize(width, height);
805 if (res) {
806 return res;
807 }
808 res = mSurfaceTexture->setDefaultBufferFormat(format);
809 if (res) {
810 return res;
811 }
812
813 mAnw = new Surface(mProducer, /*useAsync*/ true);
814 if (mAnw == NULL) {
815 return NO_MEMORY;
816 }
817
818 res = native_window_api_connect(mAnw.get(), NATIVE_WINDOW_API_CAMERA);
819 if (res) {
820 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
821 return res;
822 }
823
824 return device->setPreviewWindow(mAnw);
825}
826
827status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
828 const String8& cameraId) {
829 sp<CameraHardwareInterface> device =
830 new CameraHardwareInterface(cameraId.string());
831
832 status_t res = device->initialize(mCameraModule);
833 if (res) {
834 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
835 cameraId.string());
836 return res;
837 }
838
839 // need to set __get_memory in set_callbacks().
840 device->setCallbacks(NULL, NULL, NULL, NULL);
841
842 mParameters = device->getParameters();
843
844 int32_t width, height;
845 res = getSmallestSurfaceSize(&width, &height);
846 if (res) {
847 ALOGE("%s: failed to get smallest surface size for camera %s",
848 __FUNCTION__, cameraId.string());
849 return res;
850 }
851
852 res = initializePreviewWindow(device, width, height);
853 if (res) {
854 ALOGE("%s: failed to initialize preview window for camera %s",
855 __FUNCTION__, cameraId.string());
856 return res;
857 }
858
859 mCameraId = cameraId;
860 mDevice = device;
861 return OK;
862}
863
864status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
865 if (mDevice == NULL) {
866 return OK;
867 }
868
869 mParameters.set(CameraParameters::KEY_FLASH_MODE,
870 CameraParameters::FLASH_MODE_OFF);
871 mDevice->setParameters(mParameters);
872 mDevice->stopPreview();
873 status_t res = native_window_api_disconnect(mAnw.get(),
874 NATIVE_WINDOW_API_CAMERA);
875 if (res) {
876 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
877 __FUNCTION__, strerror(-res), res);
878 }
879 mDevice->setPreviewWindow(NULL);
880 mDevice->release();
881
882 return OK;
883}
884// CameraHardwareInterfaceFlashControl implementation ends
885
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800886}