blob: 07d88f605b1ef66b0a86814e4ff42d62ebda04d0 [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/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080039CameraFlashlight::CameraFlashlight(CameraModule* cameraModule,
40 camera_module_callbacks_t* callbacks) :
41 mCameraModule(cameraModule),
42 mCallbacks(callbacks),
43 mFlashlightMapInitialized(false) {
44}
45
46CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
47 camera_module_callbacks_t* callbacks) :
48 mCameraModule(nullptr),
49 mProviderManager(providerManager),
50 mCallbacks(callbacks),
Chien-Yu Chen88da5262015-02-17 13:56:46 -080051 mFlashlightMapInitialized(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080052}
53
54CameraFlashlight::~CameraFlashlight() {
55}
56
Chien-Yu Chen88da5262015-02-17 13:56:46 -080057status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080058 ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
59 cameraId.string());
60 if (mFlashControl != NULL) {
61 return INVALID_OPERATION;
62 }
63
64 status_t res = OK;
65
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080066 if (mCameraModule == nullptr) {
67 mFlashControl = new ProviderFlashControl(mProviderManager);
68 } else if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
69 mFlashControl = new ModuleFlashControl(*mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080070 if (mFlashControl == NULL) {
71 ALOGV("%s: cannot create flash control for module api v2.4+",
72 __FUNCTION__);
73 return NO_MEMORY;
74 }
75 } else {
76 uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
77
Chien-Yu Chen676b21b2015-02-24 10:28:19 -080078 if (mCameraModule->getModuleApiVersion() >=
79 CAMERA_MODULE_API_VERSION_2_0) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080080 camera_info info;
81 res = mCameraModule->getCameraInfo(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080082 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080083 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -080084 ALOGE("%s: failed to get camera info for camera %s",
Chien-Yu Chen3068d732015-02-09 13:29:57 -080085 __FUNCTION__, cameraId.string());
86 return res;
87 }
88 deviceVersion = info.device_version;
89 }
90
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -080091 if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_0) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080092 CameraDeviceClientFlashControl *flashControl =
93 new CameraDeviceClientFlashControl(*mCameraModule,
94 *mCallbacks);
95 if (!flashControl) {
96 return NO_MEMORY;
97 }
98
99 mFlashControl = flashControl;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800100 } else {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800101 mFlashControl =
102 new CameraHardwareInterfaceFlashControl(*mCameraModule,
103 *mCallbacks);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800104 }
105 }
106
107 return OK;
108}
109
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800110status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
111 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700112 ALOGE("%s: findFlashUnits() must be called before this method.",
113 __FUNCTION__);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800114 return NO_INIT;
115 }
116
117 ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
118 cameraId.string(), enabled);
119
120 status_t res = OK;
121 Mutex::Autolock l(mLock);
122
Ruben Brunkcc776712015-02-17 20:18:47 -0800123 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
124 // This case is needed to avoid state corruption during the following call sequence:
125 // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
126 // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
127 // CameraService::setTorchMode for camera ID 0 continues, calls
128 // CameraFlashlight::setTorchMode
129
130 // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
131 // to avoid other similar race conditions.
132 ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
133 __FUNCTION__, cameraId.string());
134 return -EBUSY;
135 }
136
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800137 if (mFlashControl == NULL) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800138 if (enabled == false) {
139 return OK;
140 }
141
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800142 res = createFlashlightControl(cameraId);
143 if (res) {
144 return res;
145 }
146 res = mFlashControl->setTorchMode(cameraId, enabled);
147 return res;
148 }
149
150 // if flash control already exists, turning on torch mode may fail if it's
151 // tied to another camera device for module v2.3 and below.
152 res = mFlashControl->setTorchMode(cameraId, enabled);
153 if (res == BAD_INDEX) {
154 // flash control is tied to another camera device, need to close it and
155 // try again.
156 mFlashControl.clear();
157 res = createFlashlightControl(cameraId);
158 if (res) {
159 return res;
160 }
161 res = mFlashControl->setTorchMode(cameraId, enabled);
162 }
163
164 return res;
165}
166
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800167status_t CameraFlashlight::findFlashUnits() {
168 Mutex::Autolock l(mLock);
169 status_t res;
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800170
171 std::vector<String8> cameraIds;
172 if (mCameraModule) {
173 cameraIds.resize(mCameraModule->getNumberOfCameras());
174 for (size_t i = 0; i < cameraIds.size(); i++) {
175 cameraIds[i] = String8::format("%zu", i);
176 }
177 } else {
178 // No module, must be provider
179 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
180 cameraIds.resize(ids.size());
181 for (size_t i = 0; i < cameraIds.size(); i++) {
182 cameraIds[i] = String8(ids[i].c_str());
183 }
184 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800185
186 mHasFlashlightMap.clear();
187 mFlashlightMapInitialized = false;
188
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800189 for (auto &id : cameraIds) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800190 bool hasFlash = false;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800191 res = createFlashlightControl(id);
192 if (res) {
193 ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
194 id.string());
195 } else {
196 res = mFlashControl->hasFlashUnit(id, &hasFlash);
197 if (res == -EUSERS || res == -EBUSY) {
198 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
199 "camera devices may be opened", __FUNCTION__,
200 id.string());
201 return res;
202 } else if (res) {
203 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
204 " (%d)", __FUNCTION__, id.string(), strerror(-res),
205 res);
206 }
207
208 mFlashControl.clear();
209 }
210 mHasFlashlightMap.add(id, hasFlash);
211 }
212
213 mFlashlightMapInitialized = true;
214 return OK;
215}
216
217bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800218 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800219 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800220}
221
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800222bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
223 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 false;
227 }
228
229 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
230 if (index == NAME_NOT_FOUND) {
231 ALOGE("%s: camera %s not present when findFlashUnits() was called",
232 __FUNCTION__, cameraId.string());
233 return false;
234 }
235
236 return mHasFlashlightMap.valueAt(index);
237}
238
239status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800240 ALOGV("%s: prepare for device open", __FUNCTION__);
241
242 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800243 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700244 ALOGE("%s: findFlashUnits() must be called before this method.",
245 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800246 return NO_INIT;
247 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800248
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800249 if (mCameraModule && mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800250 // framework is going to open a camera device, all flash light control
251 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800252 mFlashControl.clear();
253
254 if (mOpenedCameraIds.size() == 0) {
255 // notify torch unavailable for all cameras with a flash
256 int numCameras = mCameraModule->getNumberOfCameras();
257 for (int i = 0; i < numCameras; i++) {
258 if (hasFlashUnitLocked(String8::format("%d", i))) {
259 mCallbacks->torch_mode_status_change(mCallbacks,
260 String8::format("%d", i).string(),
261 TORCH_MODE_STATUS_NOT_AVAILABLE);
262 }
263 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800264 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800265
266 // close flash control that may be opened by calling hasFlashUnitLocked.
267 mFlashControl.clear();
268 }
269
270 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
271 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800272 }
273
274 return OK;
275}
276
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800277status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
278 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
279
280 Mutex::Autolock l(mLock);
281 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700282 ALOGE("%s: findFlashUnits() must be called before this method.",
283 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800284 return NO_INIT;
285 }
286
287 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
288 if (index == NAME_NOT_FOUND) {
289 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
290 cameraId.string());
291 } else {
292 mOpenedCameraIds.removeAt(index);
293 }
294
295 // Cannot do anything until all cameras are closed.
296 if (mOpenedCameraIds.size() != 0)
297 return OK;
298
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800299 if (mCameraModule && mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800300 // notify torch available for all cameras with a flash
301 int numCameras = mCameraModule->getNumberOfCameras();
302 for (int i = 0; i < numCameras; i++) {
303 if (hasFlashUnitLocked(String8::format("%d", i))) {
304 mCallbacks->torch_mode_status_change(mCallbacks,
305 String8::format("%d", i).string(),
306 TORCH_MODE_STATUS_AVAILABLE_OFF);
307 }
308 }
309 }
310
311 return OK;
312}
313// CameraFlashlight implementation ends
314
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800315
316FlashControlBase::~FlashControlBase() {
317}
318
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800319/////////////////////////////////////////////////////////////////////
320// ModuleFlashControl implementation begins
321// Flash control for camera module v2.4 and above.
322/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800323ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
324 mProviderManager(providerManager) {
325}
326
327ProviderFlashControl::~ProviderFlashControl() {
328}
329
330status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
331 if (!hasFlash) {
332 return BAD_VALUE;
333 }
334 *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
335 return OK;
336}
337
338status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
339 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
340 cameraId.string(), enabled);
341
342 return mProviderManager->setTorchMode(cameraId.string(), enabled);
343}
344// ProviderFlashControl implementation ends
345
346/////////////////////////////////////////////////////////////////////
347// ModuleFlashControl implementation begins
348// Flash control for camera module v2.4 and above.
349/////////////////////////////////////////////////////////////////////
350ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule) :
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -0800351 mCameraModule(&cameraModule) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800352}
353
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800354ModuleFlashControl::~ModuleFlashControl() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800355}
356
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800357status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800358 if (!hasFlash) {
359 return BAD_VALUE;
360 }
361
362 *hasFlash = false;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800363 Mutex::Autolock l(mLock);
364
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800365 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800366 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800367 &info);
368 if (res != 0) {
369 return res;
370 }
371
372 CameraMetadata metadata;
373 metadata = info.static_camera_characteristics;
374 camera_metadata_entry flashAvailable =
375 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
376 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
377 *hasFlash = true;
378 }
379
380 return OK;
381}
382
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800383status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800384 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
385 cameraId.string(), enabled);
386
387 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800388 return mCameraModule->setTorchMode(cameraId.string(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800389}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800390// ModuleFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800391
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800392/////////////////////////////////////////////////////////////////////
393// CameraDeviceClientFlashControl implementation begins
394// Flash control for camera module <= v2.3 and camera HAL v2-v3
395/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800396CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
397 CameraModule& cameraModule,
398 const camera_module_callbacks_t& callbacks) :
399 mCameraModule(&cameraModule),
400 mCallbacks(&callbacks),
401 mTorchEnabled(false),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800402 mMetadata(NULL),
403 mStreaming(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800404}
405
406CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800407 disconnectCameraDevice();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800408 if (mMetadata) {
409 delete mMetadata;
410 }
411
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700412 mSurface.clear();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800413 mSurfaceTexture.clear();
414 mProducer.clear();
415 mConsumer.clear();
416
417 if (mTorchEnabled) {
418 if (mCallbacks) {
419 ALOGV("%s: notify the framework that torch was turned off",
420 __FUNCTION__);
421 mCallbacks->torch_mode_status_change(mCallbacks,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800422 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800423 }
424 }
425}
426
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800427status_t CameraDeviceClientFlashControl::initializeSurface(
428 sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800429 status_t res;
430 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
431
432 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
433 true, true);
434 if (mSurfaceTexture == NULL) {
435 return NO_MEMORY;
436 }
437
438 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
439 res = mSurfaceTexture->setDefaultBufferSize(width, height);
440 if (res) {
441 return res;
442 }
443 res = mSurfaceTexture->setDefaultBufferFormat(format);
444 if (res) {
445 return res;
446 }
447
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700448 mSurface = new Surface(mProducer, /*useAsync*/ true);
449 if (mSurface == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800450 return NO_MEMORY;
451 }
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700452 res = device->createStream(mSurface, width, height, format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700453 HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800454 if (res) {
455 return res;
456 }
457
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800458 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800459 if (res) {
460 return res;
461 }
462
463 return res;
464}
465
466status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
467 const camera_info& info, int32_t *width, int32_t *height) {
468 if (!width || !height) {
469 return BAD_VALUE;
470 }
471
472 int32_t w = INT32_MAX;
473 int32_t h = 1;
474
475 CameraMetadata metadata;
476 metadata = info.static_camera_characteristics;
477 camera_metadata_entry streamConfigs =
478 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
479 for (size_t i = 0; i < streamConfigs.count; i += 4) {
480 int32_t fmt = streamConfigs.data.i32[i];
481 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
482 int32_t ww = streamConfigs.data.i32[i + 1];
483 int32_t hh = streamConfigs.data.i32[i + 2];
484
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800485 if (w * h > ww * hh) {
486 w = ww;
487 h = hh;
488 }
489 }
490 }
491
492 // if stream configuration is not found, try available processed sizes.
493 if (streamConfigs.count == 0) {
494 camera_metadata_entry availableProcessedSizes =
495 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
496 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
497 int32_t ww = availableProcessedSizes.data.i32[i];
498 int32_t hh = availableProcessedSizes.data.i32[i + 1];
499 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800500 w = ww;
501 h = hh;
502 }
503 }
504 }
505
506 if (w == INT32_MAX) {
507 return NAME_NOT_FOUND;
508 }
509
510 *width = w;
511 *height = h;
512
513 return OK;
514}
515
516status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800517 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800518 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800519 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800520 if (res != 0) {
521 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800522 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800523 return res;
524 }
525
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800526 sp<CameraDeviceBase> device =
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800527 new Camera3Device(cameraId);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800528 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800529 return NO_MEMORY;
530 }
531
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800532 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800533 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800534 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800535 }
536
537 int32_t width, height;
538 res = getSmallestSurfaceSize(info, &width, &height);
539 if (res) {
540 return res;
541 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800542 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800543 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800544 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800545 }
546
547 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800548 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
549 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800550
551 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800552}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800553
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800554status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
555 if (mDevice != NULL) {
556 mDevice->disconnect();
557 mDevice.clear();
558 }
559
560 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800561}
562
563
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800564
565status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800566 bool *hasFlash) {
567 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
568 cameraId.string());
569
570 Mutex::Autolock l(mLock);
571 return hasFlashUnitLocked(cameraId, hasFlash);
572
573}
574
575status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800576 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800577 if (!hasFlash) {
578 return BAD_VALUE;
579 }
580
581 camera_info info;
582 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800583 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800584 if (res != 0) {
585 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
586 cameraId.string());
587 return res;
588 }
589
590 CameraMetadata metadata;
591 metadata = info.static_camera_characteristics;
592 camera_metadata_entry flashAvailable =
593 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
594 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
595 *hasFlash = true;
596 }
597
598 return OK;
599}
600
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800601status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800602 status_t res;
603
604 if (mMetadata == NULL) {
605 mMetadata = new CameraMetadata();
606 if (mMetadata == NULL) {
607 return NO_MEMORY;
608 }
609 res = mDevice->createDefaultRequest(
610 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
611 if (res) {
612 return res;
613 }
614 }
615
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800616 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800617 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
618 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
619
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800620 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
621 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
622
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800623 int32_t requestId = 0;
624 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
625
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800626 if (mStreaming) {
627 res = mDevice->setStreamingRequest(*mMetadata);
628 } else {
629 res = mDevice->capture(*mMetadata);
630 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800631 return res;
632}
633
634
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800635
636
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800637status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800638 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800639 bool hasFlash = false;
640
641 Mutex::Autolock l(mLock);
642 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
643
644 // pre-check
645 if (enabled) {
646 // invalid camera?
647 if (res) {
648 return -EINVAL;
649 }
650 // no flash unit?
651 if (!hasFlash) {
652 return -ENOSYS;
653 }
654 // already opened for a different device?
655 if (mDevice != NULL && cameraId != mCameraId) {
656 return BAD_INDEX;
657 }
658 } else if (mDevice == NULL || cameraId != mCameraId) {
659 // disabling the torch mode of an un-opened or different device.
660 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800661 } else {
662 // disabling the torch mode of currently opened device
663 disconnectCameraDevice();
664 mTorchEnabled = false;
665 mCallbacks->torch_mode_status_change(mCallbacks,
666 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
667 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800668 }
669
670 if (mDevice == NULL) {
671 res = connectCameraDevice(cameraId);
672 if (res) {
673 return res;
674 }
675 }
676
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800677 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800678 if (res) {
679 return res;
680 }
681
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800682 mTorchEnabled = true;
683 mCallbacks->torch_mode_status_change(mCallbacks,
684 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800685 return OK;
686}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800687// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800688
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800689
690/////////////////////////////////////////////////////////////////////
691// CameraHardwareInterfaceFlashControl implementation begins
692// Flash control for camera module <= v2.3 and camera HAL v1
693/////////////////////////////////////////////////////////////////////
694CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
695 CameraModule& cameraModule,
696 const camera_module_callbacks_t& callbacks) :
697 mCameraModule(&cameraModule),
698 mCallbacks(&callbacks),
699 mTorchEnabled(false) {
700
701}
702
703CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
704 disconnectCameraDevice();
705
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700706 mSurface.clear();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800707 mSurfaceTexture.clear();
708 mProducer.clear();
709 mConsumer.clear();
710
711 if (mTorchEnabled) {
712 if (mCallbacks) {
713 ALOGV("%s: notify the framework that torch was turned off",
714 __FUNCTION__);
715 mCallbacks->torch_mode_status_change(mCallbacks,
716 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
717 }
718 }
719}
720
721status_t CameraHardwareInterfaceFlashControl::setTorchMode(
722 const String8& cameraId, bool enabled) {
723 Mutex::Autolock l(mLock);
724
725 // pre-check
726 status_t res;
727 if (enabled) {
728 bool hasFlash = false;
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700729 // Check if it has a flash unit and leave camera device open.
730 res = hasFlashUnitLocked(cameraId, &hasFlash, /*keepDeviceOpen*/true);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800731 // invalid camera?
732 if (res) {
733 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
734 // another camera device.
735 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
736 }
737 // no flash unit?
738 if (!hasFlash) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700739 // Disconnect camera device if it has no flash.
740 disconnectCameraDevice();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800741 return -ENOSYS;
742 }
743 } else if (mDevice == NULL || cameraId != mCameraId) {
744 // disabling the torch mode of an un-opened or different device.
745 return OK;
746 } else {
747 // disabling the torch mode of currently opened device
748 disconnectCameraDevice();
749 mTorchEnabled = false;
750 mCallbacks->torch_mode_status_change(mCallbacks,
751 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
752 return OK;
753 }
754
755 res = startPreviewAndTorch();
756 if (res) {
757 return res;
758 }
759
760 mTorchEnabled = true;
761 mCallbacks->torch_mode_status_change(mCallbacks,
762 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
763 return OK;
764}
765
766status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
767 const String8& cameraId, bool *hasFlash) {
768 Mutex::Autolock l(mLock);
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700769 // Close device after checking if it has a flash unit.
770 return hasFlashUnitLocked(cameraId, hasFlash, /*keepDeviceOpen*/false);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800771}
772
773status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700774 const String8& cameraId, bool *hasFlash, bool keepDeviceOpen) {
775 bool closeCameraDevice = false;
776
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800777 if (!hasFlash) {
778 return BAD_VALUE;
779 }
780
781 status_t res;
782 if (mDevice == NULL) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700783 // Connect to camera device to query if it has a flash unit.
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800784 res = connectCameraDevice(cameraId);
785 if (res) {
786 return res;
787 }
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700788 // Close camera device only when it is just opened and the caller doesn't want to keep
789 // the camera device open.
790 closeCameraDevice = !keepDeviceOpen;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800791 }
792
793 if (cameraId != mCameraId) {
794 return BAD_INDEX;
795 }
796
797 const char *flashMode =
798 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
799 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
800 *hasFlash = true;
801 } else {
802 *hasFlash = false;
803 }
804
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700805 if (closeCameraDevice) {
806 res = disconnectCameraDevice();
807 if (res != OK) {
808 ALOGE("%s: Failed to disconnect camera device. %s (%d)", __FUNCTION__,
809 strerror(-res), res);
810 return res;
811 }
812 }
813
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800814 return OK;
815}
816
817status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
818 status_t res = OK;
819 res = mDevice->startPreview();
820 if (res) {
821 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
822 strerror(-res), res);
823 return res;
824 }
825
826 mParameters.set(CameraParameters::KEY_FLASH_MODE,
827 CameraParameters::FLASH_MODE_TORCH);
828
829 return mDevice->setParameters(mParameters);
830}
831
832status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
833 int32_t *width, int32_t *height) {
834 if (!width || !height) {
835 return BAD_VALUE;
836 }
837
838 int32_t w = INT32_MAX;
839 int32_t h = 1;
840 Vector<Size> sizes;
841
842 mParameters.getSupportedPreviewSizes(sizes);
843 for (size_t i = 0; i < sizes.size(); i++) {
844 Size s = sizes[i];
845 if (w * h > s.width * s.height) {
846 w = s.width;
847 h = s.height;
848 }
849 }
850
851 if (w == INT32_MAX) {
852 return NAME_NOT_FOUND;
853 }
854
855 *width = w;
856 *height = h;
857
858 return OK;
859}
860
861status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -0700862 const sp<CameraHardwareInterface>& device, int32_t width, int32_t height) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800863 status_t res;
864 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
865
866 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
867 true, true);
868 if (mSurfaceTexture == NULL) {
869 return NO_MEMORY;
870 }
871
872 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
873 res = mSurfaceTexture->setDefaultBufferSize(width, height);
874 if (res) {
875 return res;
876 }
877 res = mSurfaceTexture->setDefaultBufferFormat(format);
878 if (res) {
879 return res;
880 }
881
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700882 mSurface = new Surface(mProducer, /*useAsync*/ true);
883 if (mSurface == NULL) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800884 return NO_MEMORY;
885 }
886
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700887 res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800888 if (res) {
889 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
890 return res;
891 }
892
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700893 return device->setPreviewWindow(mSurface);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800894}
895
896status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
897 const String8& cameraId) {
898 sp<CameraHardwareInterface> device =
899 new CameraHardwareInterface(cameraId.string());
900
901 status_t res = device->initialize(mCameraModule);
902 if (res) {
903 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
904 cameraId.string());
905 return res;
906 }
907
908 // need to set __get_memory in set_callbacks().
909 device->setCallbacks(NULL, NULL, NULL, NULL);
910
911 mParameters = device->getParameters();
912
913 int32_t width, height;
914 res = getSmallestSurfaceSize(&width, &height);
915 if (res) {
916 ALOGE("%s: failed to get smallest surface size for camera %s",
917 __FUNCTION__, cameraId.string());
918 return res;
919 }
920
921 res = initializePreviewWindow(device, width, height);
922 if (res) {
923 ALOGE("%s: failed to initialize preview window for camera %s",
924 __FUNCTION__, cameraId.string());
925 return res;
926 }
927
928 mCameraId = cameraId;
929 mDevice = device;
930 return OK;
931}
932
933status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
934 if (mDevice == NULL) {
935 return OK;
936 }
937
Jim Kaye3d1c4782016-04-12 17:24:46 -0700938 if (mParameters.get(CameraParameters::KEY_FLASH_MODE)) {
939 // There is a flash, turn if off.
940 // (If there isn't one, leave the parameter null)
941 mParameters.set(CameraParameters::KEY_FLASH_MODE,
942 CameraParameters::FLASH_MODE_OFF);
943 mDevice->setParameters(mParameters);
944 }
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800945 mDevice->stopPreview();
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700946 status_t res = native_window_api_disconnect(mSurface.get(),
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800947 NATIVE_WINDOW_API_CAMERA);
948 if (res) {
949 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
950 __FUNCTION__, strerror(-res), res);
951 }
952 mDevice->setPreviewWindow(NULL);
953 mDevice->release();
Oleksiy Avramchenko8a4a0ac2015-09-14 11:00:33 +0200954 mDevice = NULL;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800955
956 return OK;
957}
958// CameraHardwareInterfaceFlashControl implementation ends
959
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800960}