blob: 4537ae6b8df960976f450d52d155255a8c4e21f5 [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) {
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -070067 if (mProviderManager->supportSetTorchMode(cameraId.string())) {
68 mFlashControl = new ProviderFlashControl(mProviderManager);
69 } else {
70 // Only HAL1 devices do not support setTorchMode
71 mFlashControl =
72 new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
73 }
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080074 } else if (mCameraModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
75 mFlashControl = new ModuleFlashControl(*mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080076 if (mFlashControl == NULL) {
77 ALOGV("%s: cannot create flash control for module api v2.4+",
78 __FUNCTION__);
79 return NO_MEMORY;
80 }
81 } else {
82 uint32_t deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
83
Chien-Yu Chen676b21b2015-02-24 10:28:19 -080084 if (mCameraModule->getModuleApiVersion() >=
85 CAMERA_MODULE_API_VERSION_2_0) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080086 camera_info info;
87 res = mCameraModule->getCameraInfo(
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080088 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080089 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -080090 ALOGE("%s: failed to get camera info for camera %s",
Chien-Yu Chen3068d732015-02-09 13:29:57 -080091 __FUNCTION__, cameraId.string());
92 return res;
93 }
94 deviceVersion = info.device_version;
95 }
96
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -080097 if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_0) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080098 CameraDeviceClientFlashControl *flashControl =
99 new CameraDeviceClientFlashControl(*mCameraModule,
100 *mCallbacks);
101 if (!flashControl) {
102 return NO_MEMORY;
103 }
104
105 mFlashControl = flashControl;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800106 } else {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800107 mFlashControl =
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700108 new CameraHardwareInterfaceFlashControl(mCameraModule, *mCallbacks);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800109 }
110 }
111
112 return OK;
113}
114
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800115status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
116 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700117 ALOGE("%s: findFlashUnits() must be called before this method.",
118 __FUNCTION__);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800119 return NO_INIT;
120 }
121
122 ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
123 cameraId.string(), enabled);
124
125 status_t res = OK;
126 Mutex::Autolock l(mLock);
127
Ruben Brunkcc776712015-02-17 20:18:47 -0800128 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
129 // This case is needed to avoid state corruption during the following call sequence:
130 // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
131 // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
132 // CameraService::setTorchMode for camera ID 0 continues, calls
133 // CameraFlashlight::setTorchMode
134
135 // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
136 // to avoid other similar race conditions.
137 ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
138 __FUNCTION__, cameraId.string());
139 return -EBUSY;
140 }
141
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800142 if (mFlashControl == NULL) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800143 if (enabled == false) {
144 return OK;
145 }
146
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800147 res = createFlashlightControl(cameraId);
148 if (res) {
149 return res;
150 }
151 res = mFlashControl->setTorchMode(cameraId, enabled);
152 return res;
153 }
154
155 // if flash control already exists, turning on torch mode may fail if it's
156 // tied to another camera device for module v2.3 and below.
157 res = mFlashControl->setTorchMode(cameraId, enabled);
158 if (res == BAD_INDEX) {
159 // flash control is tied to another camera device, need to close it and
160 // try again.
161 mFlashControl.clear();
162 res = createFlashlightControl(cameraId);
163 if (res) {
164 return res;
165 }
166 res = mFlashControl->setTorchMode(cameraId, enabled);
167 }
168
169 return res;
170}
171
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700172int CameraFlashlight::getNumberOfCameras() {
173 if (mCameraModule) {
174 return mCameraModule->getNumberOfCameras();
175 } else {
176 return mProviderManager->getStandardCameraCount();
177 }
178}
179
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800180status_t CameraFlashlight::findFlashUnits() {
181 Mutex::Autolock l(mLock);
182 status_t res;
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800183
184 std::vector<String8> cameraIds;
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700185 int numberOfCameras = getNumberOfCameras();
186 cameraIds.resize(numberOfCameras);
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800187 if (mCameraModule) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800188 for (size_t i = 0; i < cameraIds.size(); i++) {
189 cameraIds[i] = String8::format("%zu", i);
190 }
191 } else {
192 // No module, must be provider
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700193 std::vector<std::string> ids = mProviderManager->getStandardCameraDeviceIds();
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800194 for (size_t i = 0; i < cameraIds.size(); i++) {
195 cameraIds[i] = String8(ids[i].c_str());
196 }
197 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800198
199 mHasFlashlightMap.clear();
200 mFlashlightMapInitialized = false;
201
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800202 for (auto &id : cameraIds) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800203 bool hasFlash = false;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800204 res = createFlashlightControl(id);
205 if (res) {
206 ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
207 id.string());
208 } else {
209 res = mFlashControl->hasFlashUnit(id, &hasFlash);
210 if (res == -EUSERS || res == -EBUSY) {
211 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
212 "camera devices may be opened", __FUNCTION__,
213 id.string());
214 return res;
215 } else if (res) {
216 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
217 " (%d)", __FUNCTION__, id.string(), strerror(-res),
218 res);
219 }
220
221 mFlashControl.clear();
222 }
223 mHasFlashlightMap.add(id, hasFlash);
224 }
225
226 mFlashlightMapInitialized = true;
227 return OK;
228}
229
230bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800231 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800232 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800233}
234
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800235bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
236 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700237 ALOGE("%s: findFlashUnits() must be called before this method.",
238 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800239 return false;
240 }
241
242 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
243 if (index == NAME_NOT_FOUND) {
244 ALOGE("%s: camera %s not present when findFlashUnits() was called",
245 __FUNCTION__, cameraId.string());
246 return false;
247 }
248
249 return mHasFlashlightMap.valueAt(index);
250}
251
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700252bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
253 bool backwardCompatibleMode = false;
254 if (mCameraModule && mCameraModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_4) {
255 backwardCompatibleMode = true;
256 } else if (mProviderManager != nullptr &&
257 !mProviderManager->supportSetTorchMode(cameraId.string())) {
258 backwardCompatibleMode = true;
259 }
260 return backwardCompatibleMode;
261}
262
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800263status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800264 ALOGV("%s: prepare for device open", __FUNCTION__);
265
266 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800267 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700268 ALOGE("%s: findFlashUnits() must be called before this method.",
269 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800270 return NO_INIT;
271 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800272
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700273 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800274 // framework is going to open a camera device, all flash light control
275 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800276 mFlashControl.clear();
277
278 if (mOpenedCameraIds.size() == 0) {
279 // notify torch unavailable for all cameras with a flash
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700280 int numCameras = getNumberOfCameras();
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800281 for (int i = 0; i < numCameras; i++) {
282 if (hasFlashUnitLocked(String8::format("%d", i))) {
283 mCallbacks->torch_mode_status_change(mCallbacks,
284 String8::format("%d", i).string(),
285 TORCH_MODE_STATUS_NOT_AVAILABLE);
286 }
287 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800288 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800289
290 // close flash control that may be opened by calling hasFlashUnitLocked.
291 mFlashControl.clear();
292 }
293
294 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
295 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800296 }
297
298 return OK;
299}
300
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800301status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
302 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
303
304 Mutex::Autolock l(mLock);
305 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700306 ALOGE("%s: findFlashUnits() must be called before this method.",
307 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800308 return NO_INIT;
309 }
310
311 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
312 if (index == NAME_NOT_FOUND) {
313 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
314 cameraId.string());
315 } else {
316 mOpenedCameraIds.removeAt(index);
317 }
318
319 // Cannot do anything until all cameras are closed.
320 if (mOpenedCameraIds.size() != 0)
321 return OK;
322
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700323 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800324 // notify torch available for all cameras with a flash
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700325 int numCameras = getNumberOfCameras();
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800326 for (int i = 0; i < numCameras; i++) {
327 if (hasFlashUnitLocked(String8::format("%d", i))) {
328 mCallbacks->torch_mode_status_change(mCallbacks,
329 String8::format("%d", i).string(),
330 TORCH_MODE_STATUS_AVAILABLE_OFF);
331 }
332 }
333 }
334
335 return OK;
336}
337// CameraFlashlight implementation ends
338
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800339
340FlashControlBase::~FlashControlBase() {
341}
342
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800343/////////////////////////////////////////////////////////////////////
344// ModuleFlashControl implementation begins
345// Flash control for camera module v2.4 and above.
346/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800347ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
348 mProviderManager(providerManager) {
349}
350
351ProviderFlashControl::~ProviderFlashControl() {
352}
353
354status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
355 if (!hasFlash) {
356 return BAD_VALUE;
357 }
358 *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
359 return OK;
360}
361
362status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
363 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
364 cameraId.string(), enabled);
365
366 return mProviderManager->setTorchMode(cameraId.string(), enabled);
367}
368// ProviderFlashControl implementation ends
369
370/////////////////////////////////////////////////////////////////////
371// ModuleFlashControl implementation begins
372// Flash control for camera module v2.4 and above.
373/////////////////////////////////////////////////////////////////////
374ModuleFlashControl::ModuleFlashControl(CameraModule& cameraModule) :
Eino-Ville Talvalad309fb92015-11-25 12:12:45 -0800375 mCameraModule(&cameraModule) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800376}
377
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800378ModuleFlashControl::~ModuleFlashControl() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800379}
380
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800381status_t ModuleFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800382 if (!hasFlash) {
383 return BAD_VALUE;
384 }
385
386 *hasFlash = false;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800387 Mutex::Autolock l(mLock);
388
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800389 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800390 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()),
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800391 &info);
392 if (res != 0) {
393 return res;
394 }
395
396 CameraMetadata metadata;
397 metadata = info.static_camera_characteristics;
398 camera_metadata_entry flashAvailable =
399 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
400 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
401 *hasFlash = true;
402 }
403
404 return OK;
405}
406
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800407status_t ModuleFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800408 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
409 cameraId.string(), enabled);
410
411 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800412 return mCameraModule->setTorchMode(cameraId.string(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800413}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800414// ModuleFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800415
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800416/////////////////////////////////////////////////////////////////////
417// CameraDeviceClientFlashControl implementation begins
418// Flash control for camera module <= v2.3 and camera HAL v2-v3
419/////////////////////////////////////////////////////////////////////
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800420CameraDeviceClientFlashControl::CameraDeviceClientFlashControl(
421 CameraModule& cameraModule,
422 const camera_module_callbacks_t& callbacks) :
423 mCameraModule(&cameraModule),
424 mCallbacks(&callbacks),
425 mTorchEnabled(false),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800426 mMetadata(NULL),
427 mStreaming(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800428}
429
430CameraDeviceClientFlashControl::~CameraDeviceClientFlashControl() {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800431 disconnectCameraDevice();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800432 if (mMetadata) {
433 delete mMetadata;
434 }
435
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700436 mSurface.clear();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800437 mSurfaceTexture.clear();
438 mProducer.clear();
439 mConsumer.clear();
440
441 if (mTorchEnabled) {
442 if (mCallbacks) {
443 ALOGV("%s: notify the framework that torch was turned off",
444 __FUNCTION__);
445 mCallbacks->torch_mode_status_change(mCallbacks,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800446 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800447 }
448 }
449}
450
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800451status_t CameraDeviceClientFlashControl::initializeSurface(
452 sp<CameraDeviceBase> &device, int32_t width, int32_t height) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800453 status_t res;
454 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
455
456 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
457 true, true);
458 if (mSurfaceTexture == NULL) {
459 return NO_MEMORY;
460 }
461
462 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
463 res = mSurfaceTexture->setDefaultBufferSize(width, height);
464 if (res) {
465 return res;
466 }
467 res = mSurfaceTexture->setDefaultBufferFormat(format);
468 if (res) {
469 return res;
470 }
471
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700472 mSurface = new Surface(mProducer, /*useAsync*/ true);
473 if (mSurface == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800474 return NO_MEMORY;
475 }
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700476 res = device->createStream(mSurface, width, height, format,
Yin-Chia Yehb97babb2015-03-12 13:42:44 -0700477 HAL_DATASPACE_UNKNOWN, CAMERA3_STREAM_ROTATION_0, &mStreamId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800478 if (res) {
479 return res;
480 }
481
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800482 res = device->configureStreams();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800483 if (res) {
484 return res;
485 }
486
487 return res;
488}
489
490status_t CameraDeviceClientFlashControl::getSmallestSurfaceSize(
491 const camera_info& info, int32_t *width, int32_t *height) {
492 if (!width || !height) {
493 return BAD_VALUE;
494 }
495
496 int32_t w = INT32_MAX;
497 int32_t h = 1;
498
499 CameraMetadata metadata;
500 metadata = info.static_camera_characteristics;
501 camera_metadata_entry streamConfigs =
502 metadata.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
503 for (size_t i = 0; i < streamConfigs.count; i += 4) {
504 int32_t fmt = streamConfigs.data.i32[i];
505 if (fmt == ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED) {
506 int32_t ww = streamConfigs.data.i32[i + 1];
507 int32_t hh = streamConfigs.data.i32[i + 2];
508
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800509 if (w * h > ww * hh) {
510 w = ww;
511 h = hh;
512 }
513 }
514 }
515
516 // if stream configuration is not found, try available processed sizes.
517 if (streamConfigs.count == 0) {
518 camera_metadata_entry availableProcessedSizes =
519 metadata.find(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
520 for (size_t i = 0; i < availableProcessedSizes.count; i += 2) {
521 int32_t ww = availableProcessedSizes.data.i32[i];
522 int32_t hh = availableProcessedSizes.data.i32[i + 1];
523 if (w * h > ww * hh) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800524 w = ww;
525 h = hh;
526 }
527 }
528 }
529
530 if (w == INT32_MAX) {
531 return NAME_NOT_FOUND;
532 }
533
534 *width = w;
535 *height = h;
536
537 return OK;
538}
539
540status_t CameraDeviceClientFlashControl::connectCameraDevice(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800541 const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800542 camera_info info;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800543 status_t res = mCameraModule->getCameraInfo(atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800544 if (res != 0) {
545 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800546 cameraId.string());
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800547 return res;
548 }
549
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800550 sp<CameraDeviceBase> device =
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800551 new Camera3Device(cameraId);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800552 if (device == NULL) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800553 return NO_MEMORY;
554 }
555
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800556 res = device->initialize(mCameraModule);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800557 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800558 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800559 }
560
561 int32_t width, height;
562 res = getSmallestSurfaceSize(info, &width, &height);
563 if (res) {
564 return res;
565 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800566 res = initializeSurface(device, width, height);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800567 if (res) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800568 return res;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800569 }
570
571 mCameraId = cameraId;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800572 mStreaming = (info.device_version <= CAMERA_DEVICE_API_VERSION_3_1);
573 mDevice = device;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800574
575 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800576}
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800577
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800578status_t CameraDeviceClientFlashControl::disconnectCameraDevice() {
579 if (mDevice != NULL) {
580 mDevice->disconnect();
581 mDevice.clear();
582 }
583
584 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800585}
586
587
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800588
589status_t CameraDeviceClientFlashControl::hasFlashUnit(const String8& cameraId,
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800590 bool *hasFlash) {
591 ALOGV("%s: checking if camera %s has a flash unit", __FUNCTION__,
592 cameraId.string());
593
594 Mutex::Autolock l(mLock);
595 return hasFlashUnitLocked(cameraId, hasFlash);
596
597}
598
599status_t CameraDeviceClientFlashControl::hasFlashUnitLocked(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800600 const String8& cameraId, bool *hasFlash) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800601 if (!hasFlash) {
602 return BAD_VALUE;
603 }
604
605 camera_info info;
606 status_t res = mCameraModule->getCameraInfo(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800607 atoi(cameraId.string()), &info);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800608 if (res != 0) {
609 ALOGE("%s: failed to get camera info for camera %s", __FUNCTION__,
610 cameraId.string());
611 return res;
612 }
613
614 CameraMetadata metadata;
615 metadata = info.static_camera_characteristics;
616 camera_metadata_entry flashAvailable =
617 metadata.find(ANDROID_FLASH_INFO_AVAILABLE);
618 if (flashAvailable.count == 1 && flashAvailable.data.u8[0] == 1) {
619 *hasFlash = true;
620 }
621
622 return OK;
623}
624
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800625status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800626 status_t res;
627
628 if (mMetadata == NULL) {
629 mMetadata = new CameraMetadata();
630 if (mMetadata == NULL) {
631 return NO_MEMORY;
632 }
633 res = mDevice->createDefaultRequest(
634 CAMERA3_TEMPLATE_PREVIEW, mMetadata);
635 if (res) {
636 return res;
637 }
638 }
639
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800640 uint8_t torchOn = ANDROID_FLASH_MODE_TORCH;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800641 mMetadata->update(ANDROID_FLASH_MODE, &torchOn, 1);
642 mMetadata->update(ANDROID_REQUEST_OUTPUT_STREAMS, &mStreamId, 1);
643
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800644 uint8_t aeMode = ANDROID_CONTROL_AE_MODE_ON;
645 mMetadata->update(ANDROID_CONTROL_AE_MODE, &aeMode, 1);
646
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800647 int32_t requestId = 0;
648 mMetadata->update(ANDROID_REQUEST_ID, &requestId, 1);
649
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800650 if (mStreaming) {
651 res = mDevice->setStreamingRequest(*mMetadata);
652 } else {
653 res = mDevice->capture(*mMetadata);
654 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800655 return res;
656}
657
658
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800659
660
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800661status_t CameraDeviceClientFlashControl::setTorchMode(
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800662 const String8& cameraId, bool enabled) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800663 bool hasFlash = false;
664
665 Mutex::Autolock l(mLock);
666 status_t res = hasFlashUnitLocked(cameraId, &hasFlash);
667
668 // pre-check
669 if (enabled) {
670 // invalid camera?
671 if (res) {
672 return -EINVAL;
673 }
674 // no flash unit?
675 if (!hasFlash) {
676 return -ENOSYS;
677 }
678 // already opened for a different device?
679 if (mDevice != NULL && cameraId != mCameraId) {
680 return BAD_INDEX;
681 }
682 } else if (mDevice == NULL || cameraId != mCameraId) {
683 // disabling the torch mode of an un-opened or different device.
684 return OK;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800685 } else {
686 // disabling the torch mode of currently opened device
687 disconnectCameraDevice();
688 mTorchEnabled = false;
689 mCallbacks->torch_mode_status_change(mCallbacks,
690 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
691 return OK;
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800692 }
693
694 if (mDevice == NULL) {
695 res = connectCameraDevice(cameraId);
696 if (res) {
697 return res;
698 }
699 }
700
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800701 res = submitTorchEnabledRequest();
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800702 if (res) {
703 return res;
704 }
705
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800706 mTorchEnabled = true;
707 mCallbacks->torch_mode_status_change(mCallbacks,
708 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800709 return OK;
710}
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800711// CameraDeviceClientFlashControl implementation ends
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800712
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800713
714/////////////////////////////////////////////////////////////////////
715// CameraHardwareInterfaceFlashControl implementation begins
716// Flash control for camera module <= v2.3 and camera HAL v1
717/////////////////////////////////////////////////////////////////////
718CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700719 CameraModule* cameraModule,
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800720 const camera_module_callbacks_t& callbacks) :
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700721 mCameraModule(cameraModule),
722 mProviderManager(nullptr),
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800723 mCallbacks(&callbacks),
724 mTorchEnabled(false) {
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700725}
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800726
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700727CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
728 sp<CameraProviderManager> manager,
729 const camera_module_callbacks_t& callbacks) :
730 mCameraModule(nullptr),
731 mProviderManager(manager),
732 mCallbacks(&callbacks),
733 mTorchEnabled(false) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800734}
735
736CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
737 disconnectCameraDevice();
738
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700739 mSurface.clear();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800740 mSurfaceTexture.clear();
741 mProducer.clear();
742 mConsumer.clear();
743
744 if (mTorchEnabled) {
745 if (mCallbacks) {
746 ALOGV("%s: notify the framework that torch was turned off",
747 __FUNCTION__);
748 mCallbacks->torch_mode_status_change(mCallbacks,
749 mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
750 }
751 }
752}
753
754status_t CameraHardwareInterfaceFlashControl::setTorchMode(
755 const String8& cameraId, bool enabled) {
756 Mutex::Autolock l(mLock);
757
758 // pre-check
759 status_t res;
760 if (enabled) {
761 bool hasFlash = false;
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700762 // Check if it has a flash unit and leave camera device open.
763 res = hasFlashUnitLocked(cameraId, &hasFlash, /*keepDeviceOpen*/true);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800764 // invalid camera?
765 if (res) {
766 // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
767 // another camera device.
768 return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
769 }
770 // no flash unit?
771 if (!hasFlash) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700772 // Disconnect camera device if it has no flash.
773 disconnectCameraDevice();
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800774 return -ENOSYS;
775 }
776 } else if (mDevice == NULL || cameraId != mCameraId) {
777 // disabling the torch mode of an un-opened or different device.
778 return OK;
779 } else {
780 // disabling the torch mode of currently opened device
781 disconnectCameraDevice();
782 mTorchEnabled = false;
783 mCallbacks->torch_mode_status_change(mCallbacks,
784 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
785 return OK;
786 }
787
788 res = startPreviewAndTorch();
789 if (res) {
790 return res;
791 }
792
793 mTorchEnabled = true;
794 mCallbacks->torch_mode_status_change(mCallbacks,
795 cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
796 return OK;
797}
798
799status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
800 const String8& cameraId, bool *hasFlash) {
801 Mutex::Autolock l(mLock);
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700802 // Close device after checking if it has a flash unit.
803 return hasFlashUnitLocked(cameraId, hasFlash, /*keepDeviceOpen*/false);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800804}
805
806status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700807 const String8& cameraId, bool *hasFlash, bool keepDeviceOpen) {
808 bool closeCameraDevice = false;
809
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800810 if (!hasFlash) {
811 return BAD_VALUE;
812 }
813
814 status_t res;
815 if (mDevice == NULL) {
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700816 // Connect to camera device to query if it has a flash unit.
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800817 res = connectCameraDevice(cameraId);
818 if (res) {
819 return res;
820 }
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700821 // Close camera device only when it is just opened and the caller doesn't want to keep
822 // the camera device open.
823 closeCameraDevice = !keepDeviceOpen;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800824 }
825
826 if (cameraId != mCameraId) {
827 return BAD_INDEX;
828 }
829
830 const char *flashMode =
831 mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
832 if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
833 *hasFlash = true;
834 } else {
835 *hasFlash = false;
836 }
837
Chien-Yu Chen6dcc7062016-04-18 11:14:48 -0700838 if (closeCameraDevice) {
839 res = disconnectCameraDevice();
840 if (res != OK) {
841 ALOGE("%s: Failed to disconnect camera device. %s (%d)", __FUNCTION__,
842 strerror(-res), res);
843 return res;
844 }
845 }
846
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800847 return OK;
848}
849
850status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
851 status_t res = OK;
852 res = mDevice->startPreview();
853 if (res) {
854 ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
855 strerror(-res), res);
856 return res;
857 }
858
859 mParameters.set(CameraParameters::KEY_FLASH_MODE,
860 CameraParameters::FLASH_MODE_TORCH);
861
862 return mDevice->setParameters(mParameters);
863}
864
865status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
866 int32_t *width, int32_t *height) {
867 if (!width || !height) {
868 return BAD_VALUE;
869 }
870
871 int32_t w = INT32_MAX;
872 int32_t h = 1;
873 Vector<Size> sizes;
874
875 mParameters.getSupportedPreviewSizes(sizes);
876 for (size_t i = 0; i < sizes.size(); i++) {
877 Size s = sizes[i];
878 if (w * h > s.width * s.height) {
879 w = s.width;
880 h = s.height;
881 }
882 }
883
884 if (w == INT32_MAX) {
885 return NAME_NOT_FOUND;
886 }
887
888 *width = w;
889 *height = h;
890
891 return OK;
892}
893
894status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
Chih-Hung Hsieh8b0b9712016-08-09 14:25:53 -0700895 const sp<CameraHardwareInterface>& device, int32_t width, int32_t height) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800896 status_t res;
897 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
898
899 mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
900 true, true);
901 if (mSurfaceTexture == NULL) {
902 return NO_MEMORY;
903 }
904
905 int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
906 res = mSurfaceTexture->setDefaultBufferSize(width, height);
907 if (res) {
908 return res;
909 }
910 res = mSurfaceTexture->setDefaultBufferFormat(format);
911 if (res) {
912 return res;
913 }
914
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700915 mSurface = new Surface(mProducer, /*useAsync*/ true);
916 if (mSurface == NULL) {
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800917 return NO_MEMORY;
918 }
919
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700920 res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800921 if (res) {
922 ALOGE("%s: Unable to connect to native window", __FUNCTION__);
923 return res;
924 }
925
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700926 return device->setPreviewWindow(mSurface);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800927}
928
929status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
930 const String8& cameraId) {
931 sp<CameraHardwareInterface> device =
932 new CameraHardwareInterface(cameraId.string());
933
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700934 status_t res;
935 if (mCameraModule != nullptr) {
936 res = device->initialize(mCameraModule);
937 } else {
938 res = device->initialize(mProviderManager);
939 }
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800940 if (res) {
941 ALOGE("%s: initializing camera %s failed", __FUNCTION__,
942 cameraId.string());
943 return res;
944 }
945
946 // need to set __get_memory in set_callbacks().
Yin-Chia Yehb5df5472017-03-20 19:32:19 -0700947 device->setCallbacks(NULL, NULL, NULL, NULL, NULL);
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800948
949 mParameters = device->getParameters();
950
951 int32_t width, height;
952 res = getSmallestSurfaceSize(&width, &height);
953 if (res) {
954 ALOGE("%s: failed to get smallest surface size for camera %s",
955 __FUNCTION__, cameraId.string());
956 return res;
957 }
958
959 res = initializePreviewWindow(device, width, height);
960 if (res) {
961 ALOGE("%s: failed to initialize preview window for camera %s",
962 __FUNCTION__, cameraId.string());
963 return res;
964 }
965
966 mCameraId = cameraId;
967 mDevice = device;
968 return OK;
969}
970
971status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
972 if (mDevice == NULL) {
973 return OK;
974 }
975
Jim Kaye3d1c4782016-04-12 17:24:46 -0700976 if (mParameters.get(CameraParameters::KEY_FLASH_MODE)) {
977 // There is a flash, turn if off.
978 // (If there isn't one, leave the parameter null)
979 mParameters.set(CameraParameters::KEY_FLASH_MODE,
980 CameraParameters::FLASH_MODE_OFF);
981 mDevice->setParameters(mParameters);
982 }
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800983 mDevice->stopPreview();
Eino-Ville Talvala727d1722015-06-09 13:44:19 -0700984 status_t res = native_window_api_disconnect(mSurface.get(),
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800985 NATIVE_WINDOW_API_CAMERA);
986 if (res) {
987 ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
988 __FUNCTION__, strerror(-res), res);
989 }
990 mDevice->setPreviewWindow(NULL);
991 mDevice->release();
Oleksiy Avramchenko8a4a0ac2015-09-14 11:00:33 +0200992 mDevice = NULL;
Chien-Yu Chend231fd62015-02-25 16:04:22 -0800993
994 return OK;
995}
996// CameraHardwareInterfaceFlashControl implementation ends
997
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800998}