• 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 using hardware::camera::common::V1_0::TorchModeStatus;
36 
37 /////////////////////////////////////////////////////////////////////
38 // CameraFlashlight implementation begins
39 // used by camera service to control flashflight.
40 /////////////////////////////////////////////////////////////////////
41 
CameraFlashlight(sp<CameraProviderManager> providerManager,CameraProviderManager::StatusListener * callbacks)42 CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
43         CameraProviderManager::StatusListener* callbacks) :
44         mProviderManager(providerManager),
45         mCallbacks(callbacks),
46         mFlashlightMapInitialized(false) {
47 }
48 
~CameraFlashlight()49 CameraFlashlight::~CameraFlashlight() {
50 }
51 
createFlashlightControl(const String8 & cameraId)52 status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
53     ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
54             cameraId.string());
55     if (mFlashControl != NULL) {
56         return INVALID_OPERATION;
57     }
58 
59     if (mProviderManager->supportSetTorchMode(cameraId.string())) {
60         mFlashControl = new ProviderFlashControl(mProviderManager);
61     } else {
62         ALOGE("Flashlight control not supported by this device!");
63         return NO_INIT;
64     }
65 
66     return OK;
67 }
68 
setTorchMode(const String8 & cameraId,bool enabled)69 status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
70     if (!mFlashlightMapInitialized) {
71         ALOGE("%s: findFlashUnits() must be called before this method.",
72                __FUNCTION__);
73         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 
82     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 
96     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 
findFlashUnits()122 status_t CameraFlashlight::findFlashUnits() {
123     Mutex::Autolock l(mLock);
124     status_t res;
125 
126     std::vector<String8> cameraIds;
127     std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
128     int numberOfCameras = static_cast<int>(ids.size());
129     cameraIds.resize(numberOfCameras);
130     // No module, must be provider
131     for (size_t i = 0; i < cameraIds.size(); i++) {
132         cameraIds[i] = String8(ids[i].c_str());
133     }
134 
135     mFlashControl.clear();
136 
137     for (auto &id : cameraIds) {
138         ssize_t index = mHasFlashlightMap.indexOfKey(id);
139         if (0 <= index) {
140             continue;
141         }
142 
143         bool hasFlash = false;
144         res = createFlashlightControl(id);
145         if (res) {
146             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
147                     id.string());
148         } else {
149             res = mFlashControl->hasFlashUnit(id, &hasFlash);
150             if (res == -EUSERS || res == -EBUSY) {
151                 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
152                         "camera devices may be opened", __FUNCTION__,
153                         id.string());
154                 return res;
155             } else if (res) {
156                 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
157                         " (%d)", __FUNCTION__, id.string(), strerror(-res),
158                         res);
159             }
160 
161             mFlashControl.clear();
162         }
163         mHasFlashlightMap.add(id, hasFlash);
164     }
165 
166     mFlashlightMapInitialized = true;
167     return OK;
168 }
169 
hasFlashUnit(const String8 & cameraId)170 bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
171     Mutex::Autolock l(mLock);
172     return hasFlashUnitLocked(cameraId);
173 }
174 
hasFlashUnitLocked(const String8 & cameraId)175 bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
176     if (!mFlashlightMapInitialized) {
177         ALOGE("%s: findFlashUnits() must be called before this method.",
178                __FUNCTION__);
179         return false;
180     }
181 
182     ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
183     if (index == NAME_NOT_FOUND) {
184         // Might be external camera
185         ALOGW("%s: camera %s not present when findFlashUnits() was called",
186                 __FUNCTION__, cameraId.string());
187         return false;
188     }
189 
190     return mHasFlashlightMap.valueAt(index);
191 }
192 
isBackwardCompatibleMode(const String8 & cameraId)193 bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
194     bool backwardCompatibleMode = false;
195     if (mProviderManager != nullptr &&
196             !mProviderManager->supportSetTorchMode(cameraId.string())) {
197         backwardCompatibleMode = true;
198     }
199     return backwardCompatibleMode;
200 }
201 
prepareDeviceOpen(const String8 & cameraId)202 status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
203     ALOGV("%s: prepare for device open", __FUNCTION__);
204 
205     Mutex::Autolock l(mLock);
206     if (!mFlashlightMapInitialized) {
207         ALOGE("%s: findFlashUnits() must be called before this method.",
208                __FUNCTION__);
209         return NO_INIT;
210     }
211 
212     if (isBackwardCompatibleMode(cameraId)) {
213         // framework is going to open a camera device, all flash light control
214         // should be closed for backward compatible support.
215         mFlashControl.clear();
216 
217         if (mOpenedCameraIds.size() == 0) {
218             // notify torch unavailable for all cameras with a flash
219             std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
220             int numCameras = static_cast<int>(ids.size());
221             for (int i = 0; i < numCameras; i++) {
222                 String8 id8(ids[i].c_str());
223                 if (hasFlashUnitLocked(id8)) {
224                     mCallbacks->onTorchStatusChanged(
225                             id8, TorchModeStatus::NOT_AVAILABLE);
226                 }
227             }
228         }
229 
230         // close flash control that may be opened by calling hasFlashUnitLocked.
231         mFlashControl.clear();
232     }
233 
234     if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
235         mOpenedCameraIds.add(cameraId);
236     }
237 
238     return OK;
239 }
240 
deviceClosed(const String8 & cameraId)241 status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
242     ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
243 
244     Mutex::Autolock l(mLock);
245     if (!mFlashlightMapInitialized) {
246         ALOGE("%s: findFlashUnits() must be called before this method.",
247                __FUNCTION__);
248         return NO_INIT;
249     }
250 
251     ssize_t index = mOpenedCameraIds.indexOf(cameraId);
252     if (index == NAME_NOT_FOUND) {
253         ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
254                 cameraId.string());
255     } else {
256         mOpenedCameraIds.removeAt(index);
257     }
258 
259     // Cannot do anything until all cameras are closed.
260     if (mOpenedCameraIds.size() != 0)
261         return OK;
262 
263     if (isBackwardCompatibleMode(cameraId)) {
264         // notify torch available for all cameras with a flash
265         std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
266         int numCameras = static_cast<int>(ids.size());
267         for (int i = 0; i < numCameras; i++) {
268             String8 id8(ids[i].c_str());
269             if (hasFlashUnitLocked(id8)) {
270                 mCallbacks->onTorchStatusChanged(
271                         id8, TorchModeStatus::AVAILABLE_OFF);
272             }
273         }
274     }
275 
276     return OK;
277 }
278 // CameraFlashlight implementation ends
279 
280 
~FlashControlBase()281 FlashControlBase::~FlashControlBase() {
282 }
283 
284 /////////////////////////////////////////////////////////////////////
285 // ModuleFlashControl implementation begins
286 // Flash control for camera module v2.4 and above.
287 /////////////////////////////////////////////////////////////////////
ProviderFlashControl(sp<CameraProviderManager> providerManager)288 ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
289         mProviderManager(providerManager) {
290 }
291 
~ProviderFlashControl()292 ProviderFlashControl::~ProviderFlashControl() {
293 }
294 
hasFlashUnit(const String8 & cameraId,bool * hasFlash)295 status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
296     if (!hasFlash) {
297         return BAD_VALUE;
298     }
299     *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
300     return OK;
301 }
302 
setTorchMode(const String8 & cameraId,bool enabled)303 status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
304     ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
305             cameraId.string(), enabled);
306 
307     return mProviderManager->setTorchMode(cameraId.string(), enabled);
308 }
309 // ProviderFlashControl implementation ends
310 
311 }
312