blob: 015ae2f4536384bf3b75640434970f3bdf2f61f4 [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
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -080035using hardware::camera::common::V1_0::TorchModeStatus;
36
Chien-Yu Chen88da5262015-02-17 13:56:46 -080037/////////////////////////////////////////////////////////////////////
38// CameraFlashlight implementation begins
39// used by camera service to control flashflight.
40/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080041
42CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -080043 CameraProviderManager::StatusListener* callbacks) :
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080044 mProviderManager(providerManager),
45 mCallbacks(callbacks),
Chien-Yu Chen88da5262015-02-17 13:56:46 -080046 mFlashlightMapInitialized(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080047}
48
49CameraFlashlight::~CameraFlashlight() {
50}
51
Chien-Yu Chen88da5262015-02-17 13:56:46 -080052status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080053 ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
54 cameraId.string());
55 if (mFlashControl != NULL) {
56 return INVALID_OPERATION;
57 }
58
Emilian Peevf53f66e2017-04-11 14:29:43 +010059 if (mProviderManager->supportSetTorchMode(cameraId.string())) {
60 mFlashControl = new ProviderFlashControl(mProviderManager);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080061 } else {
Eino-Ville Talvalaa976df82019-06-13 18:01:58 -070062 ALOGE("Flashlight control not supported by this device!");
63 return NO_INIT;
Chien-Yu Chen3068d732015-02-09 13:29:57 -080064 }
65
66 return OK;
67}
68
Chien-Yu Chen88da5262015-02-17 13:56:46 -080069status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
70 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -070071 ALOGE("%s: findFlashUnits() must be called before this method.",
72 __FUNCTION__);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080073 return NO_INIT;
74 }
75
76 ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
77 cameraId.string(), enabled);
78
79 status_t res = OK;
80 Mutex::Autolock l(mLock);
81
Ruben Brunkcc776712015-02-17 20:18:47 -080082 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
83 // This case is needed to avoid state corruption during the following call sequence:
84 // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
85 // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
86 // CameraService::setTorchMode for camera ID 0 continues, calls
87 // CameraFlashlight::setTorchMode
88
89 // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
90 // to avoid other similar race conditions.
91 ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
92 __FUNCTION__, cameraId.string());
93 return -EBUSY;
94 }
95
Chien-Yu Chen3068d732015-02-09 13:29:57 -080096 if (mFlashControl == NULL) {
97 res = createFlashlightControl(cameraId);
98 if (res) {
99 return res;
100 }
101 res = mFlashControl->setTorchMode(cameraId, enabled);
102 return res;
103 }
104
105 // if flash control already exists, turning on torch mode may fail if it's
106 // tied to another camera device for module v2.3 and below.
107 res = mFlashControl->setTorchMode(cameraId, enabled);
108 if (res == BAD_INDEX) {
109 // flash control is tied to another camera device, need to close it and
110 // try again.
111 mFlashControl.clear();
112 res = createFlashlightControl(cameraId);
113 if (res) {
114 return res;
115 }
116 res = mFlashControl->setTorchMode(cameraId, enabled);
117 }
118
119 return res;
120}
121
Rucha Katakwar38284522021-11-10 11:25:21 -0800122status_t CameraFlashlight::turnOnTorchWithStrengthLevel(const String8& cameraId,
123 int32_t torchStrength) {
124 if (!mFlashlightMapInitialized) {
125 ALOGE("%s: findFlashUnits() must be called before this method.",
126 __FUNCTION__);
127 return NO_INIT;
128 }
129
130 ALOGV("%s: set torch strength of camera %s to %d", __FUNCTION__,
131 cameraId.string(), torchStrength);
132 status_t res = OK;
133 Mutex::Autolock l(mLock);
134
135 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
136 ALOGE("%s: Camera device %s is in use, cannot be turned ON.",
137 __FUNCTION__, cameraId.string());
138 return -EBUSY;
139 }
140
141 if (mFlashControl == NULL) {
142 res = createFlashlightControl(cameraId);
143 if (res) {
144 return res;
145 }
146 }
147
148 res = mFlashControl->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
149 return res;
150}
151
152
153status_t CameraFlashlight::getTorchStrengthLevel(const String8& cameraId,
154 int32_t* torchStrength) {
155 status_t res = OK;
156 if (!mFlashlightMapInitialized) {
157 ALOGE("%s: findFlashUnits() must be called before this method.",
158 __FUNCTION__);
159 return false;
160 }
161
162 Mutex::Autolock l(mLock);
163
164 if (mFlashControl == NULL) {
165 res = createFlashlightControl(cameraId);
166 if (res) {
167 return res;
168 }
169 }
170
171 res = mFlashControl->getTorchStrengthLevel(cameraId, torchStrength);
172 return res;
173}
174
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800175status_t CameraFlashlight::findFlashUnits() {
176 Mutex::Autolock l(mLock);
177 status_t res;
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800178
179 std::vector<String8> cameraIds;
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700180 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800181 int numberOfCameras = static_cast<int>(ids.size());
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700182 cameraIds.resize(numberOfCameras);
Emilian Peevf53f66e2017-04-11 14:29:43 +0100183 // No module, must be provider
Emilian Peevf53f66e2017-04-11 14:29:43 +0100184 for (size_t i = 0; i < cameraIds.size(); i++) {
185 cameraIds[i] = String8(ids[i].c_str());
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800186 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800187
Emilian Peevaee727d2017-05-04 16:35:48 +0100188 mFlashControl.clear();
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800189
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800190 for (auto &id : cameraIds) {
Emilian Peevaee727d2017-05-04 16:35:48 +0100191 ssize_t index = mHasFlashlightMap.indexOfKey(id);
192 if (0 <= index) {
193 continue;
194 }
195
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800196 bool hasFlash = false;
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800197 res = createFlashlightControl(id);
198 if (res) {
199 ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
200 id.string());
201 } else {
202 res = mFlashControl->hasFlashUnit(id, &hasFlash);
203 if (res == -EUSERS || res == -EBUSY) {
204 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
205 "camera devices may be opened", __FUNCTION__,
206 id.string());
207 return res;
208 } else if (res) {
209 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
210 " (%d)", __FUNCTION__, id.string(), strerror(-res),
211 res);
212 }
213
214 mFlashControl.clear();
215 }
216 mHasFlashlightMap.add(id, hasFlash);
217 }
218
219 mFlashlightMapInitialized = true;
220 return OK;
221}
222
223bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800224 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800225 return hasFlashUnitLocked(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800226}
227
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800228bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
229 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700230 ALOGE("%s: findFlashUnits() must be called before this method.",
231 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800232 return false;
233 }
234
235 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
236 if (index == NAME_NOT_FOUND) {
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800237 // Might be external camera
238 ALOGW("%s: camera %s not present when findFlashUnits() was called",
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800239 __FUNCTION__, cameraId.string());
240 return false;
241 }
242
243 return mHasFlashlightMap.valueAt(index);
244}
245
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700246bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
247 bool backwardCompatibleMode = false;
Emilian Peevf53f66e2017-04-11 14:29:43 +0100248 if (mProviderManager != nullptr &&
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700249 !mProviderManager->supportSetTorchMode(cameraId.string())) {
250 backwardCompatibleMode = true;
251 }
252 return backwardCompatibleMode;
253}
254
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800255status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800256 ALOGV("%s: prepare for device open", __FUNCTION__);
257
258 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800259 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700260 ALOGE("%s: findFlashUnits() must be called before this method.",
261 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800262 return NO_INIT;
263 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800264
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700265 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800266 // framework is going to open a camera device, all flash light control
267 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800268 mFlashControl.clear();
269
270 if (mOpenedCameraIds.size() == 0) {
271 // notify torch unavailable for all cameras with a flash
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700272 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800273 int numCameras = static_cast<int>(ids.size());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800274 for (int i = 0; i < numCameras; i++) {
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800275 String8 id8(ids[i].c_str());
276 if (hasFlashUnitLocked(id8)) {
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800277 mCallbacks->onTorchStatusChanged(
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800278 id8, TorchModeStatus::NOT_AVAILABLE);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800279 }
280 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800281 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800282
283 // close flash control that may be opened by calling hasFlashUnitLocked.
284 mFlashControl.clear();
285 }
286
287 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
288 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800289 }
290
291 return OK;
292}
293
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800294status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
295 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
296
297 Mutex::Autolock l(mLock);
298 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700299 ALOGE("%s: findFlashUnits() must be called before this method.",
300 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800301 return NO_INIT;
302 }
303
304 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
305 if (index == NAME_NOT_FOUND) {
306 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
307 cameraId.string());
308 } else {
309 mOpenedCameraIds.removeAt(index);
310 }
311
312 // Cannot do anything until all cameras are closed.
313 if (mOpenedCameraIds.size() != 0)
314 return OK;
315
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700316 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800317 // notify torch available for all cameras with a flash
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700318 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800319 int numCameras = static_cast<int>(ids.size());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800320 for (int i = 0; i < numCameras; i++) {
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800321 String8 id8(ids[i].c_str());
322 if (hasFlashUnitLocked(id8)) {
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800323 mCallbacks->onTorchStatusChanged(
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800324 id8, TorchModeStatus::AVAILABLE_OFF);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800325 }
326 }
327 }
328
329 return OK;
330}
331// CameraFlashlight implementation ends
332
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800333
334FlashControlBase::~FlashControlBase() {
335}
336
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800337/////////////////////////////////////////////////////////////////////
338// ModuleFlashControl implementation begins
339// Flash control for camera module v2.4 and above.
340/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800341ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
342 mProviderManager(providerManager) {
343}
344
345ProviderFlashControl::~ProviderFlashControl() {
346}
347
348status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
349 if (!hasFlash) {
350 return BAD_VALUE;
351 }
352 *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
353 return OK;
354}
355
356status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
357 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
358 cameraId.string(), enabled);
359
360 return mProviderManager->setTorchMode(cameraId.string(), enabled);
361}
Rucha Katakwar38284522021-11-10 11:25:21 -0800362
363status_t ProviderFlashControl::turnOnTorchWithStrengthLevel(const String8& cameraId,
364 int32_t torchStrength) {
365 ALOGV("%s: change torch strength level of camera %s to %d", __FUNCTION__,
366 cameraId.string(), torchStrength);
367
368 return mProviderManager->turnOnTorchWithStrengthLevel(cameraId.string(), torchStrength);
369}
370
371status_t ProviderFlashControl::getTorchStrengthLevel(const String8& cameraId,
372 int32_t* torchStrength) {
373 ALOGV("%s: get torch strength level of camera %s", __FUNCTION__,
374 cameraId.string());
375
376 return mProviderManager->getTorchStrengthLevel(cameraId.string(), torchStrength);
377}
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800378// ProviderFlashControl implementation ends
379
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800380}