blob: 0afd945e9d06e18af29687bb335932e0990852a6 [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;
682 res = hasFlashUnitLocked(cameraId, &hasFlash);
683 // invalid camera?
684 if (res) {
685 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
686 // another camera device.
687 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
688 }
689 // no flash unit?
690 if (!hasFlash) {
691 return -ENOSYS;
692 }
693 } else if (mDevice == NULL || cameraId != mCameraId) {
694 // disabling the torch mode of an un-opened or different device.
695 return OK;
696 } else {
697 // disabling the torch mode of currently opened device
698 disconnectCameraDevice();
699 mTorchEnabled = false;
700 mCallbacks->torch_mode_status_change(mCallbacks,
701 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
702 return OK;
703 }
704
705 res = startPreviewAndTorch();
706 if (res) {
707 return res;
708 }
709
710 mTorchEnabled = true;
711 mCallbacks->torch_mode_status_change(mCallbacks,
712 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
713 return OK;
714}
715
716status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
717 const String8& cameraId, bool *hasFlash) {
718 Mutex::Autolock l(mLock);
719 return hasFlashUnitLocked(cameraId, hasFlash);
720}
721
722status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
723 const String8& cameraId, bool *hasFlash) {
724 if (!hasFlash) {
725 return BAD_VALUE;
726 }
727
728 status_t res;
729 if (mDevice == NULL) {
730 res = connectCameraDevice(cameraId);
731 if (res) {
732 return res;
733 }
734 }
735
736 if (cameraId != mCameraId) {
737 return BAD_INDEX;
738 }
739
740 const char *flashMode =
741 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
742 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
743 *hasFlash = true;
744 } else {
745 *hasFlash = false;
746 }
747
748 return OK;
749}
750
751status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
752 status_t res = OK;
753 res = mDevice->startPreview();
754 if (res) {
755 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
756 strerror(-res), res);
757 return res;
758 }
759
760 mParameters.set(CameraParameters::KEY_FLASH_MODE,
761 CameraParameters::FLASH_MODE_TORCH);
762
763 return mDevice->setParameters(mParameters);
764}
765
766status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
767 int32_t *width, int32_t *height) {
768 if (!width || !height) {
769 return BAD_VALUE;
770 }
771
772 int32_t w = INT32_MAX;
773 int32_t h = 1;
774 Vector<Size> sizes;
775
776 mParameters.getSupportedPreviewSizes(sizes);
777 for (size_t i = 0; i < sizes.size(); i++) {
778 Size s = sizes[i];
779 if (w * h > s.width * s.height) {
780 w = s.width;
781 h = s.height;
782 }
783 }
784
785 if (w == INT32_MAX) {
786 return NAME_NOT_FOUND;
787 }
788
789 *width = w;
790 *height = h;
791
792 return OK;
793}
794
795status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
796 sp<CameraHardwareInterface> device, int32_t width, int32_t height) {
797 status_t res;
798 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
799
800 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
801 true, true);
802 if (mSurfaceTexture == NULL) {
803 return NO_MEMORY;
804 }
805
806 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
807 res = mSurfaceTexture->setDefaultBufferSize(width, height);
808 if (res) {
809 return res;
810 }
811 res = mSurfaceTexture->setDefaultBufferFormat(format);
812 if (res) {
813 return res;
814 }
815
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700816 mSurface = new Surface(mProducer, /*useAsync*/ true);
817 if (mSurface == NULL) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800818 return NO_MEMORY;
819 }
820
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700821 res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800822 if (res) {
823 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
824 return res;
825 }
826
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700827 return device->setPreviewWindow(mSurface);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800828}
829
830status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
831 const String8& cameraId) {
832 sp<CameraHardwareInterface> device =
833 new CameraHardwareInterface(cameraId.string());
834
835 status_t res = device->initialize(mCameraModule);
836 if (res) {
837 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
838 cameraId.string());
839 return res;
840 }
841
842 // need to set __get_memory in set_callbacks().
843 device->setCallbacks(NULL, NULL, NULL, NULL);
844
845 mParameters = device->getParameters();
846
847 int32_t width, height;
848 res = getSmallestSurfaceSize(&width, &height);
849 if (res) {
850 ALOGE("%s: failed to get smallest surface size for camera %s",
851 __FUNCTION__, cameraId.string());
852 return res;
853 }
854
855 res = initializePreviewWindow(device, width, height);
856 if (res) {
857 ALOGE("%s: failed to initialize preview window for camera %s",
858 __FUNCTION__, cameraId.string());
859 return res;
860 }
861
862 mCameraId = cameraId;
863 mDevice = device;
864 return OK;
865}
866
867status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
868 if (mDevice == NULL) {
869 return OK;
870 }
871
872 mParameters.set(CameraParameters::KEY_FLASH_MODE,
873 CameraParameters::FLASH_MODE_OFF);
874 mDevice->setParameters(mParameters);
875 mDevice->stopPreview();
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700876 status_t res = native_window_api_disconnect(mSurface.get(),
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800877 NATIVE_WINDOW_API_CAMERA);
878 if (res) {
879 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
880 __FUNCTION__, strerror(-res), res);
881 }
882 mDevice->setPreviewWindow(NULL);
883 mDevice->release();
Oleksiy Avramchenko8a4a0ac2015-09-14 11:00:33 +0200884 mDevice = NULL;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800885
886 return OK;
887}
888// CameraHardwareInterfaceFlashControl implementation ends
889
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800890}