blob: d21241b843baef3fdfa5e2d737409d7ce1a14d06 [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
Chien-Yu Chen3068d732015-02-09 13:29:57 -080025#include "CameraFlashlight.h"
Jim Shargo7bc756d2024-07-01 16:41:32 +000026#include "camera/CameraMetadata.h"
Chien-Yu Chen3068d732015-02-09 13:29:57 -080027#include "camera/camera2/CaptureRequest.h"
Chien-Yu Chen3068d732015-02-09 13:29:57 -080028
29namespace android {
30
Chien-Yu Chen88da5262015-02-17 13:56:46 -080031/////////////////////////////////////////////////////////////////////
32// CameraFlashlight implementation begins
33// used by camera service to control flashflight.
34/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080035
36CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -080037 CameraProviderManager::StatusListener* callbacks) :
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -080038 mProviderManager(providerManager),
39 mCallbacks(callbacks),
Chien-Yu Chen88da5262015-02-17 13:56:46 -080040 mFlashlightMapInitialized(false) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080041}
42
43CameraFlashlight::~CameraFlashlight() {
44}
45
Austin Borger1c1bee02023-06-01 16:51:35 -070046status_t CameraFlashlight::createFlashlightControl(const std::string& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -080047 ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
Austin Borger1c1bee02023-06-01 16:51:35 -070048 cameraId.c_str());
Chien-Yu Chen3068d732015-02-09 13:29:57 -080049 if (mFlashControl != NULL) {
50 return INVALID_OPERATION;
51 }
52
Austin Borger1c1bee02023-06-01 16:51:35 -070053 if (mProviderManager->supportSetTorchMode(cameraId)) {
Emilian Peevf53f66e2017-04-11 14:29:43 +010054 mFlashControl = new ProviderFlashControl(mProviderManager);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080055 } else {
Eino-Ville Talvalaa976df82019-06-13 18:01:58 -070056 ALOGE("Flashlight control not supported by this device!");
57 return NO_INIT;
Chien-Yu Chen3068d732015-02-09 13:29:57 -080058 }
59
60 return OK;
61}
62
Austin Borger1c1bee02023-06-01 16:51:35 -070063status_t CameraFlashlight::setTorchMode(const std::string& cameraId, bool enabled) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -080064 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -070065 ALOGE("%s: findFlashUnits() must be called before this method.",
66 __FUNCTION__);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080067 return NO_INIT;
68 }
69
70 ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
Austin Borger1c1bee02023-06-01 16:51:35 -070071 cameraId.c_str(), enabled);
Chien-Yu Chen3068d732015-02-09 13:29:57 -080072
73 status_t res = OK;
74 Mutex::Autolock l(mLock);
75
Ruben Brunkcc776712015-02-17 20:18:47 -080076 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
77 // This case is needed to avoid state corruption during the following call sequence:
78 // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
79 // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
80 // CameraService::setTorchMode for camera ID 0 continues, calls
81 // CameraFlashlight::setTorchMode
82
83 // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
84 // to avoid other similar race conditions.
85 ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
Austin Borger1c1bee02023-06-01 16:51:35 -070086 __FUNCTION__, cameraId.c_str());
Ruben Brunkcc776712015-02-17 20:18:47 -080087 return -EBUSY;
88 }
89
Chien-Yu Chen3068d732015-02-09 13:29:57 -080090 if (mFlashControl == NULL) {
91 res = createFlashlightControl(cameraId);
92 if (res) {
93 return res;
94 }
95 res = mFlashControl->setTorchMode(cameraId, enabled);
96 return res;
97 }
98
99 // if flash control already exists, turning on torch mode may fail if it's
100 // tied to another camera device for module v2.3 and below.
101 res = mFlashControl->setTorchMode(cameraId, enabled);
102 if (res == BAD_INDEX) {
103 // flash control is tied to another camera device, need to close it and
104 // try again.
105 mFlashControl.clear();
106 res = createFlashlightControl(cameraId);
107 if (res) {
108 return res;
109 }
110 res = mFlashControl->setTorchMode(cameraId, enabled);
111 }
112
113 return res;
114}
115
Austin Borger1c1bee02023-06-01 16:51:35 -0700116status_t CameraFlashlight::turnOnTorchWithStrengthLevel(const std::string& cameraId,
Rucha Katakwar38284522021-11-10 11:25:21 -0800117 int32_t torchStrength) {
118 if (!mFlashlightMapInitialized) {
119 ALOGE("%s: findFlashUnits() must be called before this method.",
120 __FUNCTION__);
121 return NO_INIT;
122 }
123
124 ALOGV("%s: set torch strength of camera %s to %d", __FUNCTION__,
Austin Borger1c1bee02023-06-01 16:51:35 -0700125 cameraId.c_str(), torchStrength);
Rucha Katakwar38284522021-11-10 11:25:21 -0800126 status_t res = OK;
127 Mutex::Autolock l(mLock);
128
129 if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
130 ALOGE("%s: Camera device %s is in use, cannot be turned ON.",
Austin Borger1c1bee02023-06-01 16:51:35 -0700131 __FUNCTION__, cameraId.c_str());
Rucha Katakwar38284522021-11-10 11:25:21 -0800132 return -EBUSY;
133 }
134
135 if (mFlashControl == NULL) {
136 res = createFlashlightControl(cameraId);
137 if (res) {
138 return res;
139 }
140 }
141
142 res = mFlashControl->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
143 return res;
144}
145
146
Austin Borger1c1bee02023-06-01 16:51:35 -0700147status_t CameraFlashlight::getTorchStrengthLevel(const std::string& cameraId,
Rucha Katakwar38284522021-11-10 11:25:21 -0800148 int32_t* torchStrength) {
149 status_t res = OK;
150 if (!mFlashlightMapInitialized) {
151 ALOGE("%s: findFlashUnits() must be called before this method.",
152 __FUNCTION__);
153 return false;
154 }
155
156 Mutex::Autolock l(mLock);
157
158 if (mFlashControl == NULL) {
159 res = createFlashlightControl(cameraId);
160 if (res) {
161 return res;
162 }
163 }
164
165 res = mFlashControl->getTorchStrengthLevel(cameraId, torchStrength);
166 return res;
167}
168
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800169status_t CameraFlashlight::findFlashUnits() {
170 Mutex::Autolock l(mLock);
171 status_t res;
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800172
Austin Borger1c1bee02023-06-01 16:51:35 -0700173 std::vector<std::string> cameraIds;
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700174 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800175 int numberOfCameras = static_cast<int>(ids.size());
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700176 cameraIds.resize(numberOfCameras);
Emilian Peevf53f66e2017-04-11 14:29:43 +0100177 // No module, must be provider
Emilian Peevf53f66e2017-04-11 14:29:43 +0100178 for (size_t i = 0; i < cameraIds.size(); i++) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700179 cameraIds[i] = ids[i];
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800180 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800181
Emilian Peevaee727d2017-05-04 16:35:48 +0100182 mFlashControl.clear();
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800183
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800184 for (auto &id : cameraIds) {
Emilian Peevaee727d2017-05-04 16:35:48 +0100185 ssize_t index = mHasFlashlightMap.indexOfKey(id);
186 if (0 <= index) {
187 continue;
188 }
189
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__,
Austin Borger1c1bee02023-06-01 16:51:35 -0700194 id.c_str());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800195 } 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__,
Austin Borger1c1bee02023-06-01 16:51:35 -0700200 id.c_str());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800201 return res;
202 } else if (res) {
203 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
Austin Borger1c1bee02023-06-01 16:51:35 -0700204 " (%d)", __FUNCTION__, id.c_str(), strerror(-res),
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800205 res);
206 }
207
208 mFlashControl.clear();
209 }
210 mHasFlashlightMap.add(id, hasFlash);
211 }
212
213 mFlashlightMapInitialized = true;
214 return OK;
215}
216
Austin Borger1c1bee02023-06-01 16:51:35 -0700217bool CameraFlashlight::hasFlashUnit(const std::string& 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
Austin Borger1c1bee02023-06-01 16:51:35 -0700222bool CameraFlashlight::hasFlashUnitLocked(const std::string& cameraId) {
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 false;
227 }
228
229 ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
230 if (index == NAME_NOT_FOUND) {
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800231 // Might be external camera
232 ALOGW("%s: camera %s not present when findFlashUnits() was called",
Austin Borger1c1bee02023-06-01 16:51:35 -0700233 __FUNCTION__, cameraId.c_str());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800234 return false;
235 }
236
237 return mHasFlashlightMap.valueAt(index);
238}
239
Austin Borger1c1bee02023-06-01 16:51:35 -0700240bool CameraFlashlight::isBackwardCompatibleMode(const std::string& cameraId) {
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700241 bool backwardCompatibleMode = false;
Emilian Peevf53f66e2017-04-11 14:29:43 +0100242 if (mProviderManager != nullptr &&
Austin Borger1c1bee02023-06-01 16:51:35 -0700243 !mProviderManager->supportSetTorchMode(cameraId)) {
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700244 backwardCompatibleMode = true;
245 }
246 return backwardCompatibleMode;
247}
248
Austin Borger1c1bee02023-06-01 16:51:35 -0700249status_t CameraFlashlight::prepareDeviceOpen(const std::string& cameraId) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800250 ALOGV("%s: prepare for device open", __FUNCTION__);
251
252 Mutex::Autolock l(mLock);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800253 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700254 ALOGE("%s: findFlashUnits() must be called before this method.",
255 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800256 return NO_INIT;
257 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800258
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700259 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800260 // framework is going to open a camera device, all flash light control
261 // should be closed for backward compatible support.
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800262 mFlashControl.clear();
263
264 if (mOpenedCameraIds.size() == 0) {
265 // notify torch unavailable for all cameras with a flash
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700266 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800267 int numCameras = static_cast<int>(ids.size());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800268 for (int i = 0; i < numCameras; i++) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700269 if (hasFlashUnitLocked(ids[i])) {
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800270 mCallbacks->onTorchStatusChanged(
Austin Borger1c1bee02023-06-01 16:51:35 -0700271 ids[i], TorchModeStatus::NOT_AVAILABLE);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800272 }
273 }
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800274 }
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800275
276 // close flash control that may be opened by calling hasFlashUnitLocked.
277 mFlashControl.clear();
278 }
279
280 if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
281 mOpenedCameraIds.add(cameraId);
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800282 }
283
284 return OK;
285}
286
Austin Borger1c1bee02023-06-01 16:51:35 -0700287status_t CameraFlashlight::deviceClosed(const std::string& cameraId) {
288 ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.c_str());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800289
290 Mutex::Autolock l(mLock);
291 if (!mFlashlightMapInitialized) {
Ranjith Kagathi Ananda32ab9fd2015-10-08 16:41:09 -0700292 ALOGE("%s: findFlashUnits() must be called before this method.",
293 __FUNCTION__);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800294 return NO_INIT;
295 }
296
297 ssize_t index = mOpenedCameraIds.indexOf(cameraId);
298 if (index == NAME_NOT_FOUND) {
299 ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
Austin Borger1c1bee02023-06-01 16:51:35 -0700300 cameraId.c_str());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800301 } else {
302 mOpenedCameraIds.removeAt(index);
303 }
304
305 // Cannot do anything until all cameras are closed.
306 if (mOpenedCameraIds.size() != 0)
307 return OK;
308
Yin-Chia Yehdc3134e2017-03-23 15:26:59 -0700309 if (isBackwardCompatibleMode(cameraId)) {
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800310 // notify torch available for all cameras with a flash
Yin-Chia Yeh98c72a82018-08-28 11:20:16 -0700311 std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
Yin-Chia Yeh6b1f6112018-02-28 13:05:59 -0800312 int numCameras = static_cast<int>(ids.size());
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800313 for (int i = 0; i < numCameras; i++) {
Austin Borger1c1bee02023-06-01 16:51:35 -0700314 if (hasFlashUnitLocked(ids[i])) {
Yin-Chia Yehc3e9d6f2018-02-06 10:56:32 -0800315 mCallbacks->onTorchStatusChanged(
Austin Borger1c1bee02023-06-01 16:51:35 -0700316 ids[i], TorchModeStatus::AVAILABLE_OFF);
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800317 }
318 }
319 }
320
321 return OK;
322}
323// CameraFlashlight implementation ends
324
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800325
326FlashControlBase::~FlashControlBase() {
327}
328
Chien-Yu Chen88da5262015-02-17 13:56:46 -0800329/////////////////////////////////////////////////////////////////////
330// ModuleFlashControl implementation begins
331// Flash control for camera module v2.4 and above.
332/////////////////////////////////////////////////////////////////////
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800333ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
334 mProviderManager(providerManager) {
335}
336
337ProviderFlashControl::~ProviderFlashControl() {
338}
339
Austin Borger1c1bee02023-06-01 16:51:35 -0700340status_t ProviderFlashControl::hasFlashUnit(const std::string& cameraId, bool *hasFlash) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800341 if (!hasFlash) {
342 return BAD_VALUE;
343 }
Austin Borger1c1bee02023-06-01 16:51:35 -0700344 *hasFlash = mProviderManager->hasFlashUnit(cameraId);
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800345 return OK;
346}
347
Austin Borger1c1bee02023-06-01 16:51:35 -0700348status_t ProviderFlashControl::setTorchMode(const std::string& cameraId, bool enabled) {
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800349 ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
Austin Borger1c1bee02023-06-01 16:51:35 -0700350 cameraId.c_str(), enabled);
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800351
Austin Borger1c1bee02023-06-01 16:51:35 -0700352 return mProviderManager->setTorchMode(cameraId, enabled);
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800353}
Rucha Katakwar38284522021-11-10 11:25:21 -0800354
Austin Borger1c1bee02023-06-01 16:51:35 -0700355status_t ProviderFlashControl::turnOnTorchWithStrengthLevel(const std::string& cameraId,
Rucha Katakwar38284522021-11-10 11:25:21 -0800356 int32_t torchStrength) {
357 ALOGV("%s: change torch strength level of camera %s to %d", __FUNCTION__,
Austin Borger1c1bee02023-06-01 16:51:35 -0700358 cameraId.c_str(), torchStrength);
Rucha Katakwar38284522021-11-10 11:25:21 -0800359
Austin Borger1c1bee02023-06-01 16:51:35 -0700360 return mProviderManager->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
Rucha Katakwar38284522021-11-10 11:25:21 -0800361}
362
Austin Borger1c1bee02023-06-01 16:51:35 -0700363status_t ProviderFlashControl::getTorchStrengthLevel(const std::string& cameraId,
Rucha Katakwar38284522021-11-10 11:25:21 -0800364 int32_t* torchStrength) {
365 ALOGV("%s: get torch strength level of camera %s", __FUNCTION__,
Austin Borger1c1bee02023-06-01 16:51:35 -0700366 cameraId.c_str());
Rucha Katakwar38284522021-11-10 11:25:21 -0800367
Austin Borger1c1bee02023-06-01 16:51:35 -0700368 return mProviderManager->getTorchStrengthLevel(cameraId, torchStrength);
Rucha Katakwar38284522021-11-10 11:25:21 -0800369}
Eino-Ville Talvala2f09bac2016-12-13 11:29:54 -0800370// ProviderFlashControl implementation ends
371
Chien-Yu Chen3068d732015-02-09 13:29:57 -0800372}