blob: b04b9a83ac4225c7bba98ac8b89da3d2e7e26ac7 [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) {
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 status_t res;
197
198 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800199 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800200}
201
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800202bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
203 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700204 ALOGE("%s: findFlashUnits() must be called before this method.",
205 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800206 return false;
207 }
208
209 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
210 if (index == NAME_NOT_FOUND) {
211 ALOGE("%s: camera %s not present when findFlashUnits() was called",
212 __FUNCTION__, cameraId.string());
213 return false;
214 }
215
216 return mHasFlashlightMap.valueAt(index);
217}
218
219status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800220 ALOGV("%s: prepare for device open", __FUNCTION__);
221
222 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800223 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700224 ALOGE("%s: findFlashUnits() must be called before this method.",
225 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800226 return NO_INIT;
227 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800228
Chien-Yu Chen676b21b2015-02-24 10:28:19 -0800229 if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800230 // framework is going to open a camera device, all flash light control
231 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800232 mFlashControl.clear();
233
234 if (mOpenedCameraIds.size() == 0) {
235 // notify torch unavailable for all cameras with a flash
236 int numCameras = mCameraModule->getNumberOfCameras();
237 for (int i = 0; i < numCameras; i++) {
238 if (hasFlashUnitLocked(String8::format("%d", i))) {
239 mCallbacks->torch_mode_status_change(mCallbacks,
240 String8::format("%d", i).string(),
241 TORCH_MODE_STATUS_NOT_AVAILABLE);
242 }
243 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800244 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800245
246 // close flash control that may be opened by calling hasFlashUnitLocked.
247 mFlashControl.clear();
248 }
249
250 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
251 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800252 }
253
254 return OK;
255}
256
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800257status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
258 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
259
260 Mutex::Autolock l(mLock);
261 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700262 ALOGE("%s: findFlashUnits() must be called before this method.",
263 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800264 return NO_INIT;
265 }
266
267 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
268 if (index == NAME_NOT_FOUND) {
269 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
270 cameraId.string());
271 } else {
272 mOpenedCameraIds.removeAt(index);
273 }
274
275 // Cannot do anything until all cameras are closed.
276 if (mOpenedCameraIds.size() != 0)
277 return OK;
278
Chien-Yu Chen676b21b2015-02-24 10:28:19 -0800279 if (mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800280 // notify torch available for all cameras with a flash
281 int numCameras = mCameraModule->getNumberOfCameras();
282 for (int i = 0; i < numCameras; i++) {
283 if (hasFlashUnitLocked(String8::format("%d", i))) {
284 mCallbacks->torch_mode_status_change(mCallbacks,
285 String8::format("%d", i).string(),
286 TORCH_MODE_STATUS_AVAILABLE_OFF);
287 }
288 }
289 }
290
291 return OK;
292}
293// CameraFlashlight implementation ends
294
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800295
296FlashControlBase::~FlashControlBase() {
297}
298
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800299/////////////////////////////////////////////////////////////////////
300// ModuleFlashControl implementation begins
301// Flash control for camera module v2.4 and above.
302/////////////////////////////////////////////////////////////////////
303ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800304 const camera_module_callbacks_t& callbacks) :
305 mCameraModule(&cameraModule) {
306}
307
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800308ModuleFlashControl::~ModuleFlashControl() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800309}
310
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800311status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800312 if (!hasFlash) {
313 return BAD_VALUE;
314 }
315
316 *hasFlash = false;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800317 Mutex::Autolock l(mLock);
318
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800319 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800320 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800321 &info);
322 if (res != 0) {
323 return res;
324 }
325
326 CameraMetadata metadata;
327 metadata = info.static_camera_characteristics;
328 camera_metadata_entry flashAvailable =
329 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
330 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
331 *hasFlash = true;
332 }
333
334 return OK;
335}
336
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800337status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800338 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
339 cameraId.string(), enabled);
340
341 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800342 return mCameraModule->setTorchMode(cameraId.string(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800343}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800344// ModuleFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800345
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800346/////////////////////////////////////////////////////////////////////
347// CameraDeviceClientFlashControl implementation begins
348// Flash control for camera module <= v2.3 and camera HAL v2-v3
349/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800350CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
351 CameraModule& cameraModule,
352 const camera_module_callbacks_t& callbacks) :
353 mCameraModule(&cameraModule),
354 mCallbacks(&callbacks),
355 mTorchEnabled(false),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800356 mMetadata(NULL),
357 mStreaming(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800358}
359
360CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800361 disconnectCameraDevice();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800362 if (mMetadata) {
363 delete mMetadata;
364 }
365
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700366 mSurface.clear();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800367 mSurfaceTexture.clear();
368 mProducer.clear();
369 mConsumer.clear();
370
371 if (mTorchEnabled) {
372 if (mCallbacks) {
373 ALOGV("%s: notify the framework that torch was turned off",
374 __FUNCTION__);
375 mCallbacks->torch_mode_status_change(mCallbacks,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800376 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800377 }
378 }
379}
380
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800381status_t CameraDeviceClientFlashControl::initializeSurface(
382 sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800383 status_t res;
384 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
385
386 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
387 true, true);
388 if (mSurfaceTexture == NULL) {
389 return NO_MEMORY;
390 }
391
392 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
393 res = mSurfaceTexture->setDefaultBufferSize(width, height);
394 if (res) {
395 return res;
396 }
397 res = mSurfaceTexture->setDefaultBufferFormat(format);
398 if (res) {
399 return res;
400 }
401
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700402 mSurface = new Surface(mProducer, /*useAsync*/ true);
403 if (mSurface == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800404 return NO_MEMORY;
405 }
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700406 res = device->createStream(mSurface, width, height, format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700407 HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800408 if (res) {
409 return res;
410 }
411
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800412 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800413 if (res) {
414 return res;
415 }
416
417 return res;
418}
419
420status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
421 const camera_info& info, int32_t *width, int32_t *height) {
422 if (!width || !height) {
423 return BAD_VALUE;
424 }
425
426 int32_t w = INT32_MAX;
427 int32_t h = 1;
428
429 CameraMetadata metadata;
430 metadata = info.static_camera_characteristics;
431 camera_metadata_entry streamConfigs =
432 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
433 for (size_t i = 0; i < streamConfigs.count; i += 4) {
434 int32_t fmt = streamConfigs.data.i32[i];
435 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
436 int32_t ww = streamConfigs.data.i32[i + 1];
437 int32_t hh = streamConfigs.data.i32[i + 2];
438
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800439 if (w * h > ww * hh) {
440 w = ww;
441 h = hh;
442 }
443 }
444 }
445
446 // if stream configuration is not found, try available processed sizes.
447 if (streamConfigs.count == 0) {
448 camera_metadata_entry availableProcessedSizes =
449 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
450 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
451 int32_t ww = availableProcessedSizes.data.i32[i];
452 int32_t hh = availableProcessedSizes.data.i32[i + 1];
453 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800454 w = ww;
455 h = hh;
456 }
457 }
458 }
459
460 if (w == INT32_MAX) {
461 return NAME_NOT_FOUND;
462 }
463
464 *width = w;
465 *height = h;
466
467 return OK;
468}
469
470status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800471 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800472 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800473 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800474 if (res != 0) {
475 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800476 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800477 return res;
478 }
479
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800480 sp<CameraDeviceBase> device =
481 CameraDeviceFactory::createDevice(atoi(cameraId.string()));
482 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800483 return NO_MEMORY;
484 }
485
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800486 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800487 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800488 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800489 }
490
491 int32_t width, height;
492 res = getSmallestSurfaceSize(info, &width, &height);
493 if (res) {
494 return res;
495 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800496 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800497 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800498 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800499 }
500
501 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800502 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
503 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800504
505 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800506}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800507
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800508status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
509 if (mDevice != NULL) {
510 mDevice->disconnect();
511 mDevice.clear();
512 }
513
514 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800515}
516
517
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800518
519status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800520 bool *hasFlash) {
521 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
522 cameraId.string());
523
524 Mutex::Autolock l(mLock);
525 return hasFlashUnitLocked(cameraId, hasFlash);
526
527}
528
529status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800530 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800531 if (!hasFlash) {
532 return BAD_VALUE;
533 }
534
535 camera_info info;
536 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800537 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800538 if (res != 0) {
539 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
540 cameraId.string());
541 return res;
542 }
543
544 CameraMetadata metadata;
545 metadata = info.static_camera_characteristics;
546 camera_metadata_entry flashAvailable =
547 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
548 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
549 *hasFlash = true;
550 }
551
552 return OK;
553}
554
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800555status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800556 status_t res;
557
558 if (mMetadata == NULL) {
559 mMetadata = new CameraMetadata();
560 if (mMetadata == NULL) {
561 return NO_MEMORY;
562 }
563 res = mDevice->createDefaultRequest(
564 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
565 if (res) {
566 return res;
567 }
568 }
569
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800570 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800571 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
572 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
573
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800574 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
575 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
576
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800577 int32_t requestId = 0;
578 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
579
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800580 if (mStreaming) {
581 res = mDevice->setStreamingRequest(*mMetadata);
582 } else {
583 res = mDevice->capture(*mMetadata);
584 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800585 return res;
586}
587
588
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800589
590
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800591status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800592 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800593 bool hasFlash = false;
594
595 Mutex::Autolock l(mLock);
596 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
597
598 // pre-check
599 if (enabled) {
600 // invalid camera?
601 if (res) {
602 return -EINVAL;
603 }
604 // no flash unit?
605 if (!hasFlash) {
606 return -ENOSYS;
607 }
608 // already opened for a different device?
609 if (mDevice != NULL && cameraId != mCameraId) {
610 return BAD_INDEX;
611 }
612 } else if (mDevice == NULL || cameraId != mCameraId) {
613 // disabling the torch mode of an un-opened or different device.
614 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800615 } else {
616 // disabling the torch mode of currently opened device
617 disconnectCameraDevice();
618 mTorchEnabled = false;
619 mCallbacks->torch_mode_status_change(mCallbacks,
620 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
621 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800622 }
623
624 if (mDevice == NULL) {
625 res = connectCameraDevice(cameraId);
626 if (res) {
627 return res;
628 }
629 }
630
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800631 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800632 if (res) {
633 return res;
634 }
635
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800636 mTorchEnabled = true;
637 mCallbacks->torch_mode_status_change(mCallbacks,
638 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800639 return OK;
640}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800641// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800642
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800643
644/////////////////////////////////////////////////////////////////////
645// CameraHardwareInterfaceFlashControl implementation begins
646// Flash control for camera module <= v2.3 and camera HAL v1
647/////////////////////////////////////////////////////////////////////
648CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
649 CameraModule& cameraModule,
650 const camera_module_callbacks_t& callbacks) :
651 mCameraModule(&cameraModule),
652 mCallbacks(&callbacks),
653 mTorchEnabled(false) {
654
655}
656
657CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
658 disconnectCameraDevice();
659
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700660 mSurface.clear();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800661 mSurfaceTexture.clear();
662 mProducer.clear();
663 mConsumer.clear();
664
665 if (mTorchEnabled) {
666 if (mCallbacks) {
667 ALOGV("%s: notify the framework that torch was turned off",
668 __FUNCTION__);
669 mCallbacks->torch_mode_status_change(mCallbacks,
670 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
671 }
672 }
673}
674
675status_t CameraHardwareInterfaceFlashControl::setTorchMode(
676 const String8& cameraId, bool enabled) {
677 Mutex::Autolock l(mLock);
678
679 // pre-check
680 status_t res;
681 if (enabled) {
682 bool hasFlash = false;
683 res = hasFlashUnitLocked(cameraId, &hasFlash);
684 // 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) {
692 return -ENOSYS;
693 }
694 } else if (mDevice == NULL || cameraId != mCameraId) {
695 // disabling the torch mode of an un-opened or different device.
696 return OK;
697 } else {
698 // disabling the torch mode of currently opened device
699 disconnectCameraDevice();
700 mTorchEnabled = false;
701 mCallbacks->torch_mode_status_change(mCallbacks,
702 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
703 return OK;
704 }
705
706 res = startPreviewAndTorch();
707 if (res) {
708 return res;
709 }
710
711 mTorchEnabled = true;
712 mCallbacks->torch_mode_status_change(mCallbacks,
713 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
714 return OK;
715}
716
717status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
718 const String8& cameraId, bool *hasFlash) {
719 Mutex::Autolock l(mLock);
720 return hasFlashUnitLocked(cameraId, hasFlash);
721}
722
723status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
724 const String8& cameraId, bool *hasFlash) {
725 if (!hasFlash) {
726 return BAD_VALUE;
727 }
728
729 status_t res;
730 if (mDevice == NULL) {
731 res = connectCameraDevice(cameraId);
732 if (res) {
733 return res;
734 }
735 }
736
737 if (cameraId != mCameraId) {
738 return BAD_INDEX;
739 }
740
741 const char *flashMode =
742 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
743 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
744 *hasFlash = true;
745 } else {
746 *hasFlash = false;
747 }
748
749 return OK;
750}
751
752status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
753 status_t res = OK;
754 res = mDevice->startPreview();
755 if (res) {
756 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
757 strerror(-res), res);
758 return res;
759 }
760
761 mParameters.set(CameraParameters::KEY_FLASH_MODE,
762 CameraParameters::FLASH_MODE_TORCH);
763
764 return mDevice->setParameters(mParameters);
765}
766
767status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
768 int32_t *width, int32_t *height) {
769 if (!width || !height) {
770 return BAD_VALUE;
771 }
772
773 int32_t w = INT32_MAX;
774 int32_t h = 1;
775 Vector<Size> sizes;
776
777 mParameters.getSupportedPreviewSizes(sizes);
778 for (size_t i = 0; i < sizes.size(); i++) {
779 Size s = sizes[i];
780 if (w * h > s.width * s.height) {
781 w = s.width;
782 h = s.height;
783 }
784 }
785
786 if (w == INT32_MAX) {
787 return NAME_NOT_FOUND;
788 }
789
790 *width = w;
791 *height = h;
792
793 return OK;
794}
795
796status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
Chih-Hung Hsieh5404ee12016-08-09 14:25:53 -0700797 const sp<CameraHardwareInterface>& device, int32_t width, int32_t height) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800798 status_t res;
799 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
800
801 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
802 true, true);
803 if (mSurfaceTexture == NULL) {
804 return NO_MEMORY;
805 }
806
807 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
808 res = mSurfaceTexture->setDefaultBufferSize(width, height);
809 if (res) {
810 return res;
811 }
812 res = mSurfaceTexture->setDefaultBufferFormat(format);
813 if (res) {
814 return res;
815 }
816
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700817 mSurface = new Surface(mProducer, /*useAsync*/ true);
818 if (mSurface == NULL) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800819 return NO_MEMORY;
820 }
821
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700822 res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800823 if (res) {
824 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
825 return res;
826 }
827
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700828 return device->setPreviewWindow(mSurface);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800829}
830
831status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
832 const String8& cameraId) {
833 sp<CameraHardwareInterface> device =
834 new CameraHardwareInterface(cameraId.string());
835
836 status_t res = device->initialize(mCameraModule);
837 if (res) {
838 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
839 cameraId.string());
840 return res;
841 }
842
843 // need to set __get_memory in set_callbacks().
844 device->setCallbacks(NULL, NULL, NULL, NULL);
845
846 mParameters = device->getParameters();
847
848 int32_t width, height;
849 res = getSmallestSurfaceSize(&width, &height);
850 if (res) {
851 ALOGE("%s: failed to get smallest surface size for camera %s",
852 __FUNCTION__, cameraId.string());
853 return res;
854 }
855
856 res = initializePreviewWindow(device, width, height);
857 if (res) {
858 ALOGE("%s: failed to initialize preview window for camera %s",
859 __FUNCTION__, cameraId.string());
860 return res;
861 }
862
863 mCameraId = cameraId;
864 mDevice = device;
865 return OK;
866}
867
868status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
869 if (mDevice == NULL) {
870 return OK;
871 }
872
873 mParameters.set(CameraParameters::KEY_FLASH_MODE,
874 CameraParameters::FLASH_MODE_OFF);
875 mDevice->setParameters(mParameters);
876 mDevice->stopPreview();
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700877 status_t res = native_window_api_disconnect(mSurface.get(),
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800878 NATIVE_WINDOW_API_CAMERA);
879 if (res) {
880 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
881 __FUNCTION__, strerror(-res), res);
882 }
883 mDevice->setPreviewWindow(NULL);
884 mDevice->release();
Oleksiy Avramchenko8a4a0ac2015-09-14 11:00:33 +0200885 mDevice = NULL;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800886
887 return OK;
888}
889// CameraHardwareInterfaceFlashControl implementation ends
890
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800891}