blob: ad08a682b0b285096d09d5e40148d32c27542dc5 [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"
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -080030#include "device3/Camera3Device.h"
Chien-Yu Chen3068d732015-02-09 13:29:57 -080031
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
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -080081 if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_0) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080082 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) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700102 ALOGE("%s: findFlashUnits() must be called before this method.",
103 __FUNCTION__);
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 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800197 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800198}
199
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800200bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
201 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700202 ALOGE("%s: findFlashUnits() must be called before this method.",
203 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800204 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) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700222 ALOGE("%s: findFlashUnits() must be called before this method.",
223 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800224 return NO_INIT;
225 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800226
Chien-Yu Chen676b21b2015-02-24 10:28:19 -0800227 if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800228 // framework is going to open a camera device, all flash light control
229 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800230 mFlashControl.clear();
231
232 if (mOpenedCameraIds.size() == 0) {
233 // notify torch unavailable for all cameras with a flash
234 int numCameras = mCameraModule->getNumberOfCameras();
235 for (int i = 0; i < numCameras; i++) {
236 if (hasFlashUnitLocked(String8::format("%d", i))) {
237 mCallbacks->torch_mode_status_change(mCallbacks,
238 String8::format("%d", i).string(),
239 TORCH_MODE_STATUS_NOT_AVAILABLE);
240 }
241 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800242 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800243
244 // close flash control that may be opened by calling hasFlashUnitLocked.
245 mFlashControl.clear();
246 }
247
248 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
249 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800250 }
251
252 return OK;
253}
254
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800255status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
256 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
257
258 Mutex::Autolock l(mLock);
259 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700260 ALOGE("%s: findFlashUnits() must be called before this method.",
261 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800262 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
Chien-Yu Chen676b21b2015-02-24 10:28:19 -0800277 if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800278 // notify torch available for all cameras with a flash
279 int numCameras = mCameraModule->getNumberOfCameras();
280 for (int i = 0; i < numCameras; i++) {
281 if (hasFlashUnitLocked(String8::format("%d", i))) {
282 mCallbacks->torch_mode_status_change(mCallbacks,
283 String8::format("%d", i).string(),
284 TORCH_MODE_STATUS_AVAILABLE_OFF);
285 }
286 }
287 }
288
289 return OK;
290}
291// CameraFlashlight implementation ends
292
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800293
294FlashControlBase::~FlashControlBase() {
295}
296
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800297/////////////////////////////////////////////////////////////////////
298// ModuleFlashControl implementation begins
299// Flash control for camera module v2.4 and above.
300/////////////////////////////////////////////////////////////////////
301ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800302 const camera_module_callbacks_t& callbacks) :
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -0800303 mCameraModule(&cameraModule) {
304 (void) callbacks;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800305}
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
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700365 mSurface.clear();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800366 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
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700401 mSurface = new Surface(mProducer, /*useAsync*/ true);
402 if (mSurface == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800403 return NO_MEMORY;
404 }
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700405 res = device->createStream(mSurface, width, height, format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700406 HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800407 if (res) {
408 return res;
409 }
410
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800411 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800412 if (res) {
413 return res;
414 }
415
416 return res;
417}
418
419status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
420 const camera_info& info, int32_t *width, int32_t *height) {
421 if (!width || !height) {
422 return BAD_VALUE;
423 }
424
425 int32_t w = INT32_MAX;
426 int32_t h = 1;
427
428 CameraMetadata metadata;
429 metadata = info.static_camera_characteristics;
430 camera_metadata_entry streamConfigs =
431 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
432 for (size_t i = 0; i < streamConfigs.count; i += 4) {
433 int32_t fmt = streamConfigs.data.i32[i];
434 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
435 int32_t ww = streamConfigs.data.i32[i + 1];
436 int32_t hh = streamConfigs.data.i32[i + 2];
437
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800438 if (w * h > ww * hh) {
439 w = ww;
440 h = hh;
441 }
442 }
443 }
444
445 // if stream configuration is not found, try available processed sizes.
446 if (streamConfigs.count == 0) {
447 camera_metadata_entry availableProcessedSizes =
448 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
449 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
450 int32_t ww = availableProcessedSizes.data.i32[i];
451 int32_t hh = availableProcessedSizes.data.i32[i + 1];
452 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800453 w = ww;
454 h = hh;
455 }
456 }
457 }
458
459 if (w == INT32_MAX) {
460 return NAME_NOT_FOUND;
461 }
462
463 *width = w;
464 *height = h;
465
466 return OK;
467}
468
469status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800470 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800471 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800472 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800473 if (res != 0) {
474 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800475 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800476 return res;
477 }
478
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800479 sp<CameraDeviceBase> device =
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -0800480 new Camera3Device(atoi(cameraId.string()));
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800481 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800482 return NO_MEMORY;
483 }
484
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800485 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800486 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800487 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800488 }
489
490 int32_t width, height;
491 res = getSmallestSurfaceSize(info, &width, &height);
492 if (res) {
493 return res;
494 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800495 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800496 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800497 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800498 }
499
500 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800501 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
502 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800503
504 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800505}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800506
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800507status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
508 if (mDevice != NULL) {
509 mDevice->disconnect();
510 mDevice.clear();
511 }
512
513 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800514}
515
516
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800517
518status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800519 bool *hasFlash) {
520 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
521 cameraId.string());
522
523 Mutex::Autolock l(mLock);
524 return hasFlashUnitLocked(cameraId, hasFlash);
525
526}
527
528status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800529 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800530 if (!hasFlash) {
531 return BAD_VALUE;
532 }
533
534 camera_info info;
535 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800536 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800537 if (res != 0) {
538 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
539 cameraId.string());
540 return res;
541 }
542
543 CameraMetadata metadata;
544 metadata = info.static_camera_characteristics;
545 camera_metadata_entry flashAvailable =
546 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
547 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
548 *hasFlash = true;
549 }
550
551 return OK;
552}
553
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800554status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800555 status_t res;
556
557 if (mMetadata == NULL) {
558 mMetadata = new CameraMetadata();
559 if (mMetadata == NULL) {
560 return NO_MEMORY;
561 }
562 res = mDevice->createDefaultRequest(
563 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
564 if (res) {
565 return res;
566 }
567 }
568
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800569 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800570 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
571 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
572
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800573 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
574 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
575
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800576 int32_t requestId = 0;
577 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
578
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800579 if (mStreaming) {
580 res = mDevice->setStreamingRequest(*mMetadata);
581 } else {
582 res = mDevice->capture(*mMetadata);
583 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800584 return res;
585}
586
587
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800588
589
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800590status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800591 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800592 bool hasFlash = false;
593
594 Mutex::Autolock l(mLock);
595 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
596
597 // pre-check
598 if (enabled) {
599 // invalid camera?
600 if (res) {
601 return -EINVAL;
602 }
603 // no flash unit?
604 if (!hasFlash) {
605 return -ENOSYS;
606 }
607 // already opened for a different device?
608 if (mDevice != NULL && cameraId != mCameraId) {
609 return BAD_INDEX;
610 }
611 } else if (mDevice == NULL || cameraId != mCameraId) {
612 // disabling the torch mode of an un-opened or different device.
613 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800614 } else {
615 // disabling the torch mode of currently opened device
616 disconnectCameraDevice();
617 mTorchEnabled = false;
618 mCallbacks->torch_mode_status_change(mCallbacks,
619 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
620 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800621 }
622
623 if (mDevice == NULL) {
624 res = connectCameraDevice(cameraId);
625 if (res) {
626 return res;
627 }
628 }
629
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800630 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800631 if (res) {
632 return res;
633 }
634
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800635 mTorchEnabled = true;
636 mCallbacks->torch_mode_status_change(mCallbacks,
637 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800638 return OK;
639}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800640// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800641
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800642
643/////////////////////////////////////////////////////////////////////
644// CameraHardwareInterfaceFlashControl implementation begins
645// Flash control for camera module <= v2.3 and camera HAL v1
646/////////////////////////////////////////////////////////////////////
647CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
648 CameraModule& cameraModule,
649 const camera_module_callbacks_t& callbacks) :
650 mCameraModule(&cameraModule),
651 mCallbacks(&callbacks),
652 mTorchEnabled(false) {
653
654}
655
656CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
657 disconnectCameraDevice();
658
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700659 mSurface.clear();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800660 mSurfaceTexture.clear();
661 mProducer.clear();
662 mConsumer.clear();
663
664 if (mTorchEnabled) {
665 if (mCallbacks) {
666 ALOGV("%s: notify the framework that torch was turned off",
667 __FUNCTION__);
668 mCallbacks->torch_mode_status_change(mCallbacks,
669 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
670 }
671 }
672}
673
674status_t CameraHardwareInterfaceFlashControl::setTorchMode(
675 const String8& cameraId, bool enabled) {
676 Mutex::Autolock l(mLock);
677
678 // pre-check
679 status_t res;
680 if (enabled) {
681 bool hasFlash = false;
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700682 // Check if it has a flash unit and leave camera device open.
683 res = hasFlashUnitLocked(cameraId, &hasFlash, /*keepDeviceOpen*/true);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800684 // invalid camera?
685 if (res) {
686 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
687 // another camera device.
688 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
689 }
690 // no flash unit?
691 if (!hasFlash) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700692 // Disconnect camera device if it has no flash.
693 disconnectCameraDevice();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800694 return -ENOSYS;
695 }
696 } else if (mDevice == NULL || cameraId != mCameraId) {
697 // disabling the torch mode of an un-opened or different device.
698 return OK;
699 } else {
700 // disabling the torch mode of currently opened device
701 disconnectCameraDevice();
702 mTorchEnabled = false;
703 mCallbacks->torch_mode_status_change(mCallbacks,
704 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
705 return OK;
706 }
707
708 res = startPreviewAndTorch();
709 if (res) {
710 return res;
711 }
712
713 mTorchEnabled = true;
714 mCallbacks->torch_mode_status_change(mCallbacks,
715 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
716 return OK;
717}
718
719status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
720 const String8& cameraId, bool *hasFlash) {
721 Mutex::Autolock l(mLock);
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700722 // Close device after checking if it has a flash unit.
723 return hasFlashUnitLocked(cameraId, hasFlash, /*keepDeviceOpen*/false);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800724}
725
726status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700727 const String8& cameraId, bool *hasFlash, bool keepDeviceOpen) {
728 bool closeCameraDevice = false;
729
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800730 if (!hasFlash) {
731 return BAD_VALUE;
732 }
733
734 status_t res;
735 if (mDevice == NULL) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700736 // Connect to camera device to query if it has a flash unit.
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800737 res = connectCameraDevice(cameraId);
738 if (res) {
739 return res;
740 }
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700741 // Close camera device only when it is just opened and the caller doesn't want to keep
742 // the camera device open.
743 closeCameraDevice = !keepDeviceOpen;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800744 }
745
746 if (cameraId != mCameraId) {
747 return BAD_INDEX;
748 }
749
750 const char *flashMode =
751 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
752 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
753 *hasFlash = true;
754 } else {
755 *hasFlash = false;
756 }
757
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700758 if (closeCameraDevice) {
759 res = disconnectCameraDevice();
760 if (res != OK) {
761 ALOGE("%s: Failed to disconnect camera device. %s (%d)", __FUNCTION__,
762 strerror(-res), res);
763 return res;
764 }
765 }
766
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800767 return OK;
768}
769
770status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
771 status_t res = OK;
772 res = mDevice->startPreview();
773 if (res) {
774 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
775 strerror(-res), res);
776 return res;
777 }
778
779 mParameters.set(CameraParameters::KEY_FLASH_MODE,
780 CameraParameters::FLASH_MODE_TORCH);
781
782 return mDevice->setParameters(mParameters);
783}
784
785status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
786 int32_t *width, int32_t *height) {
787 if (!width || !height) {
788 return BAD_VALUE;
789 }
790
791 int32_t w = INT32_MAX;
792 int32_t h = 1;
793 Vector<Size> sizes;
794
795 mParameters.getSupportedPreviewSizes(sizes);
796 for (size_t i = 0; i < sizes.size(); i++) {
797 Size s = sizes[i];
798 if (w * h > s.width * s.height) {
799 w = s.width;
800 h = s.height;
801 }
802 }
803
804 if (w == INT32_MAX) {
805 return NAME_NOT_FOUND;
806 }
807
808 *width = w;
809 *height = h;
810
811 return OK;
812}
813
814status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
815 sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
816 status_t res;
817 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
818
819 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
820 true, true);
821 if (mSurfaceTexture == NULL) {
822 return NO_MEMORY;
823 }
824
825 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
826 res = mSurfaceTexture->setDefaultBufferSize(width, height);
827 if (res) {
828 return res;
829 }
830 res = mSurfaceTexture->setDefaultBufferFormat(format);
831 if (res) {
832 return res;
833 }
834
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700835 mSurface = new Surface(mProducer, /*useAsync*/ true);
836 if (mSurface == NULL) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800837 return NO_MEMORY;
838 }
839
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700840 res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800841 if (res) {
842 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
843 return res;
844 }
845
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700846 return device->setPreviewWindow(mSurface);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800847}
848
849status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
850 const String8& cameraId) {
851 sp<CameraHardwareInterface> device =
852 new CameraHardwareInterface(cameraId.string());
853
854 status_t res = device->initialize(mCameraModule);
855 if (res) {
856 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
857 cameraId.string());
858 return res;
859 }
860
861 // need to set __get_memory in set_callbacks().
862 device->setCallbacks(NULL, NULL, NULL, NULL);
863
864 mParameters = device->getParameters();
865
866 int32_t width, height;
867 res = getSmallestSurfaceSize(&width, &height);
868 if (res) {
869 ALOGE("%s: failed to get smallest surface size for camera %s",
870 __FUNCTION__, cameraId.string());
871 return res;
872 }
873
874 res = initializePreviewWindow(device, width, height);
875 if (res) {
876 ALOGE("%s: failed to initialize preview window for camera %s",
877 __FUNCTION__, cameraId.string());
878 return res;
879 }
880
881 mCameraId = cameraId;
882 mDevice = device;
883 return OK;
884}
885
886status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
887 if (mDevice == NULL) {
888 return OK;
889 }
890
Jim Kaye3d1c4782016-04-12 17:24:46 -0700891 if (mParameters.get(CameraParameters::KEY_FLASH_MODE)) {
892 // There is a flash, turn if off.
893 // (If there isn't one, leave the parameter null)
894 mParameters.set(CameraParameters::KEY_FLASH_MODE,
895 CameraParameters::FLASH_MODE_OFF);
896 mDevice->setParameters(mParameters);
897 }
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800898 mDevice->stopPreview();
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700899 status_t res = native_window_api_disconnect(mSurface.get(),
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800900 NATIVE_WINDOW_API_CAMERA);
901 if (res) {
902 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
903 __FUNCTION__, strerror(-res), res);
904 }
905 mDevice->setPreviewWindow(NULL);
906 mDevice->release();
Oleksiy Avramchenko8a4a0ac2015-09-14 11:00:33 +0200907 mDevice = NULL;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800908
909 return OK;
910}
911// CameraHardwareInterfaceFlashControl implementation ends
912
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800913}