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