xref: /aosp_15_r20/frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
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
19 // #define LOG_NDEBUG 0
20 
21 #include <utils/Log.h>
22 #include <utils/Trace.h>
23 #include <cutils/properties.h>
24 
25 #include "CameraFlashlight.h"
26 #include "camera/CameraMetadata.h"
27 #include "camera/camera2/CaptureRequest.h"
28 
29 namespace android {
30 
31 /////////////////////////////////////////////////////////////////////
32 // CameraFlashlight implementation begins
33 // used by camera service to control flashflight.
34 /////////////////////////////////////////////////////////////////////
35 
CameraFlashlight(sp<CameraProviderManager> providerManager,CameraProviderManager::StatusListener * callbacks)36 CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
37         CameraProviderManager::StatusListener* callbacks) :
38         mProviderManager(providerManager),
39         mCallbacks(callbacks),
40         mFlashlightMapInitialized(false) {
41 }
42 
~CameraFlashlight()43 CameraFlashlight::~CameraFlashlight() {
44 }
45 
createFlashlightControl(const std::string & cameraId)46 status_t CameraFlashlight::createFlashlightControl(const std::string& cameraId) {
47     ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
48             cameraId.c_str());
49     if (mFlashControl != NULL) {
50         return INVALID_OPERATION;
51     }
52 
53     if (mProviderManager->supportSetTorchMode(cameraId)) {
54         mFlashControl = new ProviderFlashControl(mProviderManager);
55     } else {
56         ALOGE("Flashlight control not supported by this device!");
57         return NO_INIT;
58     }
59 
60     return OK;
61 }
62 
setTorchMode(const std::string & cameraId,bool enabled)63 status_t CameraFlashlight::setTorchMode(const std::string& cameraId, bool enabled) {
64     if (!mFlashlightMapInitialized) {
65         ALOGE("%s: findFlashUnits() must be called before this method.",
66                __FUNCTION__);
67         return NO_INIT;
68     }
69 
70     ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
71             cameraId.c_str(), enabled);
72 
73     status_t res = OK;
74     Mutex::Autolock l(mLock);
75 
76     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.",
86                 __FUNCTION__, cameraId.c_str());
87         return -EBUSY;
88     }
89 
90     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 
turnOnTorchWithStrengthLevel(const std::string & cameraId,int32_t torchStrength)116 status_t CameraFlashlight::turnOnTorchWithStrengthLevel(const std::string& cameraId,
117             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__,
125             cameraId.c_str(), torchStrength);
126     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.",
131                 __FUNCTION__, cameraId.c_str());
132         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 
getTorchStrengthLevel(const std::string & cameraId,int32_t * torchStrength)147 status_t CameraFlashlight::getTorchStrengthLevel(const std::string& cameraId,
148             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 
findFlashUnits()169 status_t CameraFlashlight::findFlashUnits() {
170     Mutex::Autolock l(mLock);
171     status_t res;
172 
173     std::vector<std::string> cameraIds;
174     std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
175     int numberOfCameras = static_cast<int>(ids.size());
176     cameraIds.resize(numberOfCameras);
177     // No module, must be provider
178     for (size_t i = 0; i < cameraIds.size(); i++) {
179         cameraIds[i] = ids[i];
180     }
181 
182     mFlashControl.clear();
183 
184     for (auto &id : cameraIds) {
185         ssize_t index = mHasFlashlightMap.indexOfKey(id);
186         if (0 <= index) {
187             continue;
188         }
189 
190         bool hasFlash = false;
191         res = createFlashlightControl(id);
192         if (res) {
193             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
194                     id.c_str());
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.c_str());
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.c_str(), 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 
hasFlashUnit(const std::string & cameraId)217 bool CameraFlashlight::hasFlashUnit(const std::string& cameraId) {
218     Mutex::Autolock l(mLock);
219     return hasFlashUnitLocked(cameraId);
220 }
221 
hasFlashUnitLocked(const std::string & cameraId)222 bool CameraFlashlight::hasFlashUnitLocked(const std::string& cameraId) {
223     if (!mFlashlightMapInitialized) {
224         ALOGE("%s: findFlashUnits() must be called before this method.",
225                __FUNCTION__);
226         return false;
227     }
228 
229     ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
230     if (index == NAME_NOT_FOUND) {
231         // Might be external camera
232         ALOGW("%s: camera %s not present when findFlashUnits() was called",
233                 __FUNCTION__, cameraId.c_str());
234         return false;
235     }
236 
237     return mHasFlashlightMap.valueAt(index);
238 }
239 
isBackwardCompatibleMode(const std::string & cameraId)240 bool CameraFlashlight::isBackwardCompatibleMode(const std::string& cameraId) {
241     bool backwardCompatibleMode = false;
242     if (mProviderManager != nullptr &&
243             !mProviderManager->supportSetTorchMode(cameraId)) {
244         backwardCompatibleMode = true;
245     }
246     return backwardCompatibleMode;
247 }
248 
prepareDeviceOpen(const std::string & cameraId)249 status_t CameraFlashlight::prepareDeviceOpen(const std::string& cameraId) {
250     ALOGV("%s: prepare for device open", __FUNCTION__);
251 
252     Mutex::Autolock l(mLock);
253     if (!mFlashlightMapInitialized) {
254         ALOGE("%s: findFlashUnits() must be called before this method.",
255                __FUNCTION__);
256         return NO_INIT;
257     }
258 
259     if (isBackwardCompatibleMode(cameraId)) {
260         // framework is going to open a camera device, all flash light control
261         // should be closed for backward compatible support.
262         mFlashControl.clear();
263 
264         if (mOpenedCameraIds.size() == 0) {
265             // notify torch unavailable for all cameras with a flash
266             std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
267             int numCameras = static_cast<int>(ids.size());
268             for (int i = 0; i < numCameras; i++) {
269                 if (hasFlashUnitLocked(ids[i])) {
270                     mCallbacks->onTorchStatusChanged(
271                             ids[i], TorchModeStatus::NOT_AVAILABLE);
272                 }
273             }
274         }
275 
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);
282     }
283 
284     return OK;
285 }
286 
deviceClosed(const std::string & cameraId)287 status_t CameraFlashlight::deviceClosed(const std::string& cameraId) {
288     ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.c_str());
289 
290     Mutex::Autolock l(mLock);
291     if (!mFlashlightMapInitialized) {
292         ALOGE("%s: findFlashUnits() must be called before this method.",
293                __FUNCTION__);
294         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__,
300                 cameraId.c_str());
301     } 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 
309     if (isBackwardCompatibleMode(cameraId)) {
310         // notify torch available for all cameras with a flash
311         std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
312         int numCameras = static_cast<int>(ids.size());
313         for (int i = 0; i < numCameras; i++) {
314             if (hasFlashUnitLocked(ids[i])) {
315                 mCallbacks->onTorchStatusChanged(
316                         ids[i], TorchModeStatus::AVAILABLE_OFF);
317             }
318         }
319     }
320 
321     return OK;
322 }
323 // CameraFlashlight implementation ends
324 
325 
~FlashControlBase()326 FlashControlBase::~FlashControlBase() {
327 }
328 
329 /////////////////////////////////////////////////////////////////////
330 // ModuleFlashControl implementation begins
331 // Flash control for camera module v2.4 and above.
332 /////////////////////////////////////////////////////////////////////
ProviderFlashControl(sp<CameraProviderManager> providerManager)333 ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
334         mProviderManager(providerManager) {
335 }
336 
~ProviderFlashControl()337 ProviderFlashControl::~ProviderFlashControl() {
338 }
339 
hasFlashUnit(const std::string & cameraId,bool * hasFlash)340 status_t ProviderFlashControl::hasFlashUnit(const std::string& cameraId, bool *hasFlash) {
341     if (!hasFlash) {
342         return BAD_VALUE;
343     }
344     *hasFlash = mProviderManager->hasFlashUnit(cameraId);
345     return OK;
346 }
347 
setTorchMode(const std::string & cameraId,bool enabled)348 status_t ProviderFlashControl::setTorchMode(const std::string& cameraId, bool enabled) {
349     ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
350             cameraId.c_str(), enabled);
351 
352     return mProviderManager->setTorchMode(cameraId, enabled);
353 }
354 
turnOnTorchWithStrengthLevel(const std::string & cameraId,int32_t torchStrength)355 status_t ProviderFlashControl::turnOnTorchWithStrengthLevel(const std::string& cameraId,
356             int32_t torchStrength) {
357     ALOGV("%s: change torch strength level of camera %s to %d", __FUNCTION__,
358             cameraId.c_str(), torchStrength);
359 
360     return mProviderManager->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
361 }
362 
getTorchStrengthLevel(const std::string & cameraId,int32_t * torchStrength)363 status_t ProviderFlashControl::getTorchStrengthLevel(const std::string& cameraId,
364             int32_t* torchStrength) {
365     ALOGV("%s: get torch strength level of camera %s", __FUNCTION__,
366             cameraId.c_str());
367 
368     return mProviderManager->getTorchStrengthLevel(cameraId, torchStrength);
369 }
370 // ProviderFlashControl implementation ends
371 
372 }
373