• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "camera/CameraMetadata.h"
26 #include "CameraFlashlight.h"
27 #include "gui/IGraphicBufferConsumer.h"
28 #include "gui/BufferQueue.h"
29 #include "camera/camera2/CaptureRequest.h"
30 #include "device3/Camera3Device.h"
31 
32 
33 namespace android {
34 
35 /////////////////////////////////////////////////////////////////////
36 // CameraFlashlight implementation begins
37 // used by camera service to control flashflight.
38 /////////////////////////////////////////////////////////////////////
39 
CameraFlashlight(sp<CameraProviderManager> providerManager,CameraProviderManager::StatusListener * callbacks)40 CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
41         CameraProviderManager::StatusListener* callbacks) :
42         mProviderManager(providerManager),
43         mCallbacks(callbacks),
44         mFlashlightMapInitialized(false) {
45 }
46 
~CameraFlashlight()47 CameraFlashlight::~CameraFlashlight() {
48 }
49 
createFlashlightControl(const std::string & cameraId)50 status_t CameraFlashlight::createFlashlightControl(const std::string& cameraId) {
51     ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
52             cameraId.c_str());
53     if (mFlashControl != NULL) {
54         return INVALID_OPERATION;
55     }
56 
57     if (mProviderManager->supportSetTorchMode(cameraId)) {
58         mFlashControl = new ProviderFlashControl(mProviderManager);
59     } else {
60         ALOGE("Flashlight control not supported by this device!");
61         return NO_INIT;
62     }
63 
64     return OK;
65 }
66 
setTorchMode(const std::string & cameraId,bool enabled)67 status_t CameraFlashlight::setTorchMode(const std::string& cameraId, bool enabled) {
68     if (!mFlashlightMapInitialized) {
69         ALOGE("%s: findFlashUnits() must be called before this method.",
70                __FUNCTION__);
71         return NO_INIT;
72     }
73 
74     ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
75             cameraId.c_str(), enabled);
76 
77     status_t res = OK;
78     Mutex::Autolock l(mLock);
79 
80     if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
81         // This case is needed to avoid state corruption during the following call sequence:
82         // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
83         // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
84         // CameraService::setTorchMode for camera ID 0 continues, calls
85         //        CameraFlashlight::setTorchMode
86 
87         // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
88         // to avoid other similar race conditions.
89         ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
90                 __FUNCTION__, cameraId.c_str());
91         return -EBUSY;
92     }
93 
94     if (mFlashControl == NULL) {
95         res = createFlashlightControl(cameraId);
96         if (res) {
97             return res;
98         }
99         res =  mFlashControl->setTorchMode(cameraId, enabled);
100         return res;
101     }
102 
103     // if flash control already exists, turning on torch mode may fail if it's
104     // tied to another camera device for module v2.3 and below.
105     res = mFlashControl->setTorchMode(cameraId, enabled);
106     if (res == BAD_INDEX) {
107         // flash control is tied to another camera device, need to close it and
108         // try again.
109         mFlashControl.clear();
110         res = createFlashlightControl(cameraId);
111         if (res) {
112             return res;
113         }
114         res = mFlashControl->setTorchMode(cameraId, enabled);
115     }
116 
117     return res;
118 }
119 
turnOnTorchWithStrengthLevel(const std::string & cameraId,int32_t torchStrength)120 status_t CameraFlashlight::turnOnTorchWithStrengthLevel(const std::string& cameraId,
121             int32_t torchStrength) {
122     if (!mFlashlightMapInitialized) {
123         ALOGE("%s: findFlashUnits() must be called before this method.",
124                __FUNCTION__);
125         return NO_INIT;
126     }
127 
128     ALOGV("%s: set torch strength of camera %s to %d", __FUNCTION__,
129             cameraId.c_str(), torchStrength);
130     status_t res = OK;
131     Mutex::Autolock l(mLock);
132 
133     if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
134         ALOGE("%s: Camera device %s is in use, cannot be turned ON.",
135                 __FUNCTION__, cameraId.c_str());
136         return -EBUSY;
137     }
138 
139     if (mFlashControl == NULL) {
140         res = createFlashlightControl(cameraId);
141         if (res) {
142             return res;
143         }
144     }
145 
146     res = mFlashControl->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
147     return res;
148 }
149 
150 
getTorchStrengthLevel(const std::string & cameraId,int32_t * torchStrength)151 status_t CameraFlashlight::getTorchStrengthLevel(const std::string& cameraId,
152             int32_t* torchStrength) {
153     status_t res = OK;
154     if (!mFlashlightMapInitialized) {
155         ALOGE("%s: findFlashUnits() must be called before this method.",
156             __FUNCTION__);
157         return false;
158     }
159 
160     Mutex::Autolock l(mLock);
161 
162     if (mFlashControl == NULL) {
163         res = createFlashlightControl(cameraId);
164         if (res) {
165             return res;
166         }
167     }
168 
169     res = mFlashControl->getTorchStrengthLevel(cameraId, torchStrength);
170     return res;
171 }
172 
findFlashUnits()173 status_t CameraFlashlight::findFlashUnits() {
174     Mutex::Autolock l(mLock);
175     status_t res;
176 
177     std::vector<std::string> cameraIds;
178     std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
179     int numberOfCameras = static_cast<int>(ids.size());
180     cameraIds.resize(numberOfCameras);
181     // No module, must be provider
182     for (size_t i = 0; i < cameraIds.size(); i++) {
183         cameraIds[i] = ids[i];
184     }
185 
186     mFlashControl.clear();
187 
188     for (auto &id : cameraIds) {
189         ssize_t index = mHasFlashlightMap.indexOfKey(id);
190         if (0 <= index) {
191             continue;
192         }
193 
194         bool hasFlash = false;
195         res = createFlashlightControl(id);
196         if (res) {
197             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
198                     id.c_str());
199         } else {
200             res = mFlashControl->hasFlashUnit(id, &hasFlash);
201             if (res == -EUSERS || res == -EBUSY) {
202                 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
203                         "camera devices may be opened", __FUNCTION__,
204                         id.c_str());
205                 return res;
206             } else if (res) {
207                 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
208                         " (%d)", __FUNCTION__, id.c_str(), strerror(-res),
209                         res);
210             }
211 
212             mFlashControl.clear();
213         }
214         mHasFlashlightMap.add(id, hasFlash);
215     }
216 
217     mFlashlightMapInitialized = true;
218     return OK;
219 }
220 
hasFlashUnit(const std::string & cameraId)221 bool CameraFlashlight::hasFlashUnit(const std::string& cameraId) {
222     Mutex::Autolock l(mLock);
223     return hasFlashUnitLocked(cameraId);
224 }
225 
hasFlashUnitLocked(const std::string & cameraId)226 bool CameraFlashlight::hasFlashUnitLocked(const std::string& cameraId) {
227     if (!mFlashlightMapInitialized) {
228         ALOGE("%s: findFlashUnits() must be called before this method.",
229                __FUNCTION__);
230         return false;
231     }
232 
233     ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
234     if (index == NAME_NOT_FOUND) {
235         // Might be external camera
236         ALOGW("%s: camera %s not present when findFlashUnits() was called",
237                 __FUNCTION__, cameraId.c_str());
238         return false;
239     }
240 
241     return mHasFlashlightMap.valueAt(index);
242 }
243 
isBackwardCompatibleMode(const std::string & cameraId)244 bool CameraFlashlight::isBackwardCompatibleMode(const std::string& cameraId) {
245     bool backwardCompatibleMode = false;
246     if (mProviderManager != nullptr &&
247             !mProviderManager->supportSetTorchMode(cameraId)) {
248         backwardCompatibleMode = true;
249     }
250     return backwardCompatibleMode;
251 }
252 
prepareDeviceOpen(const std::string & cameraId)253 status_t CameraFlashlight::prepareDeviceOpen(const std::string& cameraId) {
254     ALOGV("%s: prepare for device open", __FUNCTION__);
255 
256     Mutex::Autolock l(mLock);
257     if (!mFlashlightMapInitialized) {
258         ALOGE("%s: findFlashUnits() must be called before this method.",
259                __FUNCTION__);
260         return NO_INIT;
261     }
262 
263     if (isBackwardCompatibleMode(cameraId)) {
264         // framework is going to open a camera device, all flash light control
265         // should be closed for backward compatible support.
266         mFlashControl.clear();
267 
268         if (mOpenedCameraIds.size() == 0) {
269             // notify torch unavailable for all cameras with a flash
270             std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
271             int numCameras = static_cast<int>(ids.size());
272             for (int i = 0; i < numCameras; i++) {
273                 if (hasFlashUnitLocked(ids[i])) {
274                     mCallbacks->onTorchStatusChanged(
275                             ids[i], TorchModeStatus::NOT_AVAILABLE);
276                 }
277             }
278         }
279 
280         // close flash control that may be opened by calling hasFlashUnitLocked.
281         mFlashControl.clear();
282     }
283 
284     if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
285         mOpenedCameraIds.add(cameraId);
286     }
287 
288     return OK;
289 }
290 
deviceClosed(const std::string & cameraId)291 status_t CameraFlashlight::deviceClosed(const std::string& cameraId) {
292     ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.c_str());
293 
294     Mutex::Autolock l(mLock);
295     if (!mFlashlightMapInitialized) {
296         ALOGE("%s: findFlashUnits() must be called before this method.",
297                __FUNCTION__);
298         return NO_INIT;
299     }
300 
301     ssize_t index = mOpenedCameraIds.indexOf(cameraId);
302     if (index == NAME_NOT_FOUND) {
303         ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
304                 cameraId.c_str());
305     } else {
306         mOpenedCameraIds.removeAt(index);
307     }
308 
309     // Cannot do anything until all cameras are closed.
310     if (mOpenedCameraIds.size() != 0)
311         return OK;
312 
313     if (isBackwardCompatibleMode(cameraId)) {
314         // notify torch available for all cameras with a flash
315         std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
316         int numCameras = static_cast<int>(ids.size());
317         for (int i = 0; i < numCameras; i++) {
318             if (hasFlashUnitLocked(ids[i])) {
319                 mCallbacks->onTorchStatusChanged(
320                         ids[i], TorchModeStatus::AVAILABLE_OFF);
321             }
322         }
323     }
324 
325     return OK;
326 }
327 // CameraFlashlight implementation ends
328 
329 
~FlashControlBase()330 FlashControlBase::~FlashControlBase() {
331 }
332 
333 /////////////////////////////////////////////////////////////////////
334 // ModuleFlashControl implementation begins
335 // Flash control for camera module v2.4 and above.
336 /////////////////////////////////////////////////////////////////////
ProviderFlashControl(sp<CameraProviderManager> providerManager)337 ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
338         mProviderManager(providerManager) {
339 }
340 
~ProviderFlashControl()341 ProviderFlashControl::~ProviderFlashControl() {
342 }
343 
hasFlashUnit(const std::string & cameraId,bool * hasFlash)344 status_t ProviderFlashControl::hasFlashUnit(const std::string& cameraId, bool *hasFlash) {
345     if (!hasFlash) {
346         return BAD_VALUE;
347     }
348     *hasFlash = mProviderManager->hasFlashUnit(cameraId);
349     return OK;
350 }
351 
setTorchMode(const std::string & cameraId,bool enabled)352 status_t ProviderFlashControl::setTorchMode(const std::string& cameraId, bool enabled) {
353     ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
354             cameraId.c_str(), enabled);
355 
356     return mProviderManager->setTorchMode(cameraId, enabled);
357 }
358 
turnOnTorchWithStrengthLevel(const std::string & cameraId,int32_t torchStrength)359 status_t ProviderFlashControl::turnOnTorchWithStrengthLevel(const std::string& cameraId,
360             int32_t torchStrength) {
361     ALOGV("%s: change torch strength level of camera %s to %d", __FUNCTION__,
362             cameraId.c_str(), torchStrength);
363 
364     return mProviderManager->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
365 }
366 
getTorchStrengthLevel(const std::string & cameraId,int32_t * torchStrength)367 status_t ProviderFlashControl::getTorchStrengthLevel(const std::string& cameraId,
368             int32_t* torchStrength) {
369     ALOGV("%s: get torch strength level of camera %s", __FUNCTION__,
370             cameraId.c_str());
371 
372     return mProviderManager->getTorchStrengthLevel(cameraId, torchStrength);
373 }
374 // ProviderFlashControl implementation ends
375 
376 }
377