• 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,camera_module_callbacks_t * callbacks)40 CameraFlashlight::CameraFlashlight(sp<CameraProviderManager> providerManager,
41         camera_module_callbacks_t* callbacks) :
42         mProviderManager(providerManager),
43         mCallbacks(callbacks),
44         mFlashlightMapInitialized(false) {
45 }
46 
~CameraFlashlight()47 CameraFlashlight::~CameraFlashlight() {
48 }
49 
createFlashlightControl(const String8 & cameraId)50 status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
51     ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
52             cameraId.string());
53     if (mFlashControl != NULL) {
54         return INVALID_OPERATION;
55     }
56 
57     if (mProviderManager->supportSetTorchMode(cameraId.string())) {
58         mFlashControl = new ProviderFlashControl(mProviderManager);
59     } else {
60         // Only HAL1 devices do not support setTorchMode
61         mFlashControl =
62                 new CameraHardwareInterfaceFlashControl(mProviderManager, *mCallbacks);
63     }
64 
65     return OK;
66 }
67 
setTorchMode(const String8 & cameraId,bool enabled)68 status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
69     if (!mFlashlightMapInitialized) {
70         ALOGE("%s: findFlashUnits() must be called before this method.",
71                __FUNCTION__);
72         return NO_INIT;
73     }
74 
75     ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
76             cameraId.string(), enabled);
77 
78     status_t res = OK;
79     Mutex::Autolock l(mLock);
80 
81     if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
82         // This case is needed to avoid state corruption during the following call sequence:
83         // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
84         // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
85         // CameraService::setTorchMode for camera ID 0 continues, calls
86         //        CameraFlashlight::setTorchMode
87 
88         // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
89         // to avoid other similar race conditions.
90         ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
91                 __FUNCTION__, cameraId.string());
92         return -EBUSY;
93     }
94 
95     if (mFlashControl == NULL) {
96         res = createFlashlightControl(cameraId);
97         if (res) {
98             return res;
99         }
100         res =  mFlashControl->setTorchMode(cameraId, enabled);
101         return res;
102     }
103 
104     // if flash control already exists, turning on torch mode may fail if it's
105     // tied to another camera device for module v2.3 and below.
106     res = mFlashControl->setTorchMode(cameraId, enabled);
107     if (res == BAD_INDEX) {
108         // flash control is tied to another camera device, need to close it and
109         // try again.
110         mFlashControl.clear();
111         res = createFlashlightControl(cameraId);
112         if (res) {
113             return res;
114         }
115         res = mFlashControl->setTorchMode(cameraId, enabled);
116     }
117 
118     return res;
119 }
120 
getNumberOfCameras()121 int CameraFlashlight::getNumberOfCameras() {
122     return mProviderManager->getAPI1CompatibleCameraCount();
123 }
124 
findFlashUnits()125 status_t CameraFlashlight::findFlashUnits() {
126     Mutex::Autolock l(mLock);
127     status_t res;
128 
129     std::vector<String8> cameraIds;
130     int numberOfCameras = getNumberOfCameras();
131     cameraIds.resize(numberOfCameras);
132     // No module, must be provider
133     std::vector<std::string> ids = mProviderManager->getAPI1CompatibleCameraDeviceIds();
134     for (size_t i = 0; i < cameraIds.size(); i++) {
135         cameraIds[i] = String8(ids[i].c_str());
136     }
137 
138     mFlashControl.clear();
139 
140     for (auto &id : cameraIds) {
141         ssize_t index = mHasFlashlightMap.indexOfKey(id);
142         if (0 <= index) {
143             continue;
144         }
145 
146         bool hasFlash = false;
147         res = createFlashlightControl(id);
148         if (res) {
149             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
150                     id.string());
151         } else {
152             res = mFlashControl->hasFlashUnit(id, &hasFlash);
153             if (res == -EUSERS || res == -EBUSY) {
154                 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
155                         "camera devices may be opened", __FUNCTION__,
156                         id.string());
157                 return res;
158             } else if (res) {
159                 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
160                         " (%d)", __FUNCTION__, id.string(), strerror(-res),
161                         res);
162             }
163 
164             mFlashControl.clear();
165         }
166         mHasFlashlightMap.add(id, hasFlash);
167     }
168 
169     mFlashlightMapInitialized = true;
170     return OK;
171 }
172 
hasFlashUnit(const String8 & cameraId)173 bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
174     Mutex::Autolock l(mLock);
175     return hasFlashUnitLocked(cameraId);
176 }
177 
hasFlashUnitLocked(const String8 & cameraId)178 bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
179     if (!mFlashlightMapInitialized) {
180         ALOGE("%s: findFlashUnits() must be called before this method.",
181                __FUNCTION__);
182         return false;
183     }
184 
185     ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
186     if (index == NAME_NOT_FOUND) {
187         ALOGE("%s: camera %s not present when findFlashUnits() was called",
188                 __FUNCTION__, cameraId.string());
189         return false;
190     }
191 
192     return mHasFlashlightMap.valueAt(index);
193 }
194 
isBackwardCompatibleMode(const String8 & cameraId)195 bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
196     bool backwardCompatibleMode = false;
197     if (mProviderManager != nullptr &&
198             !mProviderManager->supportSetTorchMode(cameraId.string())) {
199         backwardCompatibleMode = true;
200     }
201     return backwardCompatibleMode;
202 }
203 
prepareDeviceOpen(const String8 & cameraId)204 status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
205     ALOGV("%s: prepare for device open", __FUNCTION__);
206 
207     Mutex::Autolock l(mLock);
208     if (!mFlashlightMapInitialized) {
209         ALOGE("%s: findFlashUnits() must be called before this method.",
210                __FUNCTION__);
211         return NO_INIT;
212     }
213 
214     if (isBackwardCompatibleMode(cameraId)) {
215         // framework is going to open a camera device, all flash light control
216         // should be closed for backward compatible support.
217         mFlashControl.clear();
218 
219         if (mOpenedCameraIds.size() == 0) {
220             // notify torch unavailable for all cameras with a flash
221             int numCameras = getNumberOfCameras();
222             for (int i = 0; i < numCameras; i++) {
223                 if (hasFlashUnitLocked(String8::format("%d", i))) {
224                     mCallbacks->torch_mode_status_change(mCallbacks,
225                             String8::format("%d", i).string(),
226                             TORCH_MODE_STATUS_NOT_AVAILABLE);
227                 }
228             }
229         }
230 
231         // close flash control that may be opened by calling hasFlashUnitLocked.
232         mFlashControl.clear();
233     }
234 
235     if (mOpenedCameraIds.indexOf(cameraId) == NAME_NOT_FOUND) {
236         mOpenedCameraIds.add(cameraId);
237     }
238 
239     return OK;
240 }
241 
deviceClosed(const String8 & cameraId)242 status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
243     ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
244 
245     Mutex::Autolock l(mLock);
246     if (!mFlashlightMapInitialized) {
247         ALOGE("%s: findFlashUnits() must be called before this method.",
248                __FUNCTION__);
249         return NO_INIT;
250     }
251 
252     ssize_t index = mOpenedCameraIds.indexOf(cameraId);
253     if (index == NAME_NOT_FOUND) {
254         ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
255                 cameraId.string());
256     } else {
257         mOpenedCameraIds.removeAt(index);
258     }
259 
260     // Cannot do anything until all cameras are closed.
261     if (mOpenedCameraIds.size() != 0)
262         return OK;
263 
264     if (isBackwardCompatibleMode(cameraId)) {
265         // notify torch available for all cameras with a flash
266         int numCameras = getNumberOfCameras();
267         for (int i = 0; i < numCameras; i++) {
268             if (hasFlashUnitLocked(String8::format("%d", i))) {
269                 mCallbacks->torch_mode_status_change(mCallbacks,
270                         String8::format("%d", i).string(),
271                         TORCH_MODE_STATUS_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 // CameraHardwareInterfaceFlashControl implementation begins
313 // Flash control for camera module <= v2.3 and camera HAL v1
314 /////////////////////////////////////////////////////////////////////
315 
CameraHardwareInterfaceFlashControl(sp<CameraProviderManager> manager,const camera_module_callbacks_t & callbacks)316 CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
317         sp<CameraProviderManager> manager,
318         const camera_module_callbacks_t& callbacks) :
319         mProviderManager(manager),
320         mCallbacks(&callbacks),
321         mTorchEnabled(false) {
322 }
323 
~CameraHardwareInterfaceFlashControl()324 CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
325     disconnectCameraDevice();
326 
327     mSurface.clear();
328     mSurfaceTexture.clear();
329     mProducer.clear();
330     mConsumer.clear();
331 
332     if (mTorchEnabled) {
333         if (mCallbacks) {
334             ALOGV("%s: notify the framework that torch was turned off",
335                     __FUNCTION__);
336             mCallbacks->torch_mode_status_change(mCallbacks,
337                     mCameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
338         }
339     }
340 }
341 
setTorchMode(const String8 & cameraId,bool enabled)342 status_t CameraHardwareInterfaceFlashControl::setTorchMode(
343         const String8& cameraId, bool enabled) {
344     Mutex::Autolock l(mLock);
345 
346     // pre-check
347     status_t res;
348     if (enabled) {
349         bool hasFlash = false;
350         // Check if it has a flash unit and leave camera device open.
351         res = hasFlashUnitLocked(cameraId, &hasFlash, /*keepDeviceOpen*/true);
352         // invalid camera?
353         if (res) {
354             // hasFlashUnitLocked() returns BAD_INDEX if mDevice is connected to
355             // another camera device.
356             return res == BAD_INDEX ? BAD_INDEX : -EINVAL;
357         }
358         // no flash unit?
359         if (!hasFlash) {
360             // Disconnect camera device if it has no flash.
361             disconnectCameraDevice();
362             return -ENOSYS;
363         }
364     } else if (mDevice == NULL || cameraId != mCameraId) {
365         // disabling the torch mode of an un-opened or different device.
366         return OK;
367     } else {
368         // disabling the torch mode of currently opened device
369         disconnectCameraDevice();
370         mTorchEnabled = false;
371         mCallbacks->torch_mode_status_change(mCallbacks,
372             cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_OFF);
373         return OK;
374     }
375 
376     res = startPreviewAndTorch();
377     if (res) {
378         return res;
379     }
380 
381     mTorchEnabled = true;
382     mCallbacks->torch_mode_status_change(mCallbacks,
383             cameraId.string(), TORCH_MODE_STATUS_AVAILABLE_ON);
384     return OK;
385 }
386 
hasFlashUnit(const String8 & cameraId,bool * hasFlash)387 status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
388         const String8& cameraId, bool *hasFlash) {
389     Mutex::Autolock l(mLock);
390     // Close device after checking if it has a flash unit.
391     return hasFlashUnitLocked(cameraId, hasFlash, /*keepDeviceOpen*/false);
392 }
393 
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash,bool keepDeviceOpen)394 status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
395         const String8& cameraId, bool *hasFlash, bool keepDeviceOpen) {
396     bool closeCameraDevice = false;
397 
398     if (!hasFlash) {
399         return BAD_VALUE;
400     }
401 
402     status_t res;
403     if (mDevice == NULL) {
404         // Connect to camera device to query if it has a flash unit.
405         res = connectCameraDevice(cameraId);
406         if (res) {
407             return res;
408         }
409         // Close camera device only when it is just opened and the caller doesn't want to keep
410         // the camera device open.
411         closeCameraDevice = !keepDeviceOpen;
412     }
413 
414     if (cameraId != mCameraId) {
415         return BAD_INDEX;
416     }
417 
418     const char *flashMode =
419             mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
420     if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
421         *hasFlash = true;
422     } else {
423         *hasFlash = false;
424     }
425 
426     if (closeCameraDevice) {
427         res = disconnectCameraDevice();
428         if (res != OK) {
429             ALOGE("%s: Failed to disconnect camera device. %s (%d)", __FUNCTION__,
430                     strerror(-res), res);
431             return res;
432         }
433     }
434 
435     return OK;
436 }
437 
startPreviewAndTorch()438 status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
439     status_t res = OK;
440     res = mDevice->startPreview();
441     if (res) {
442         ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
443                 strerror(-res), res);
444         return res;
445     }
446 
447     mParameters.set(CameraParameters::KEY_FLASH_MODE,
448             CameraParameters::FLASH_MODE_TORCH);
449 
450     return mDevice->setParameters(mParameters);
451 }
452 
getSmallestSurfaceSize(int32_t * width,int32_t * height)453 status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
454         int32_t *width, int32_t *height) {
455     if (!width || !height) {
456         return BAD_VALUE;
457     }
458 
459     int32_t w = INT32_MAX;
460     int32_t h = 1;
461     Vector<Size> sizes;
462 
463     mParameters.getSupportedPreviewSizes(sizes);
464     for (size_t i = 0; i < sizes.size(); i++) {
465         Size s = sizes[i];
466         if (w * h > s.width * s.height) {
467             w = s.width;
468             h = s.height;
469         }
470     }
471 
472     if (w == INT32_MAX) {
473         return NAME_NOT_FOUND;
474     }
475 
476     *width = w;
477     *height = h;
478 
479     return OK;
480 }
481 
initializePreviewWindow(const sp<CameraHardwareInterface> & device,int32_t width,int32_t height)482 status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
483         const sp<CameraHardwareInterface>& device, int32_t width, int32_t height) {
484     status_t res;
485     BufferQueue::createBufferQueue(&mProducer, &mConsumer);
486 
487     mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
488             true, true);
489     if (mSurfaceTexture == NULL) {
490         return NO_MEMORY;
491     }
492 
493     int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
494     res = mSurfaceTexture->setDefaultBufferSize(width, height);
495     if (res) {
496         return res;
497     }
498     res = mSurfaceTexture->setDefaultBufferFormat(format);
499     if (res) {
500         return res;
501     }
502 
503     mSurface = new Surface(mProducer, /*useAsync*/ true);
504     if (mSurface == NULL) {
505         return NO_MEMORY;
506     }
507 
508     res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
509     if (res) {
510         ALOGE("%s: Unable to connect to native window", __FUNCTION__);
511         return res;
512     }
513 
514     return device->setPreviewWindow(mSurface);
515 }
516 
connectCameraDevice(const String8 & cameraId)517 status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
518         const String8& cameraId) {
519     sp<CameraHardwareInterface> device =
520             new CameraHardwareInterface(cameraId.string());
521 
522     status_t res = device->initialize(mProviderManager);
523     if (res) {
524         ALOGE("%s: initializing camera %s failed", __FUNCTION__,
525                 cameraId.string());
526         return res;
527     }
528 
529     // need to set __get_memory in set_callbacks().
530     device->setCallbacks(NULL, NULL, NULL, NULL, NULL);
531 
532     mParameters = device->getParameters();
533 
534     int32_t width, height;
535     res = getSmallestSurfaceSize(&width, &height);
536     if (res) {
537         ALOGE("%s: failed to get smallest surface size for camera %s",
538                 __FUNCTION__, cameraId.string());
539         return res;
540     }
541 
542     res = initializePreviewWindow(device, width, height);
543     if (res) {
544         ALOGE("%s: failed to initialize preview window for camera %s",
545                 __FUNCTION__, cameraId.string());
546         return res;
547     }
548 
549     mCameraId = cameraId;
550     mDevice = device;
551     return OK;
552 }
553 
disconnectCameraDevice()554 status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
555     if (mDevice == NULL) {
556         return OK;
557     }
558 
559     if (mParameters.get(CameraParameters::KEY_FLASH_MODE)) {
560         // There is a flash, turn if off.
561         // (If there isn't one, leave the parameter null)
562         mParameters.set(CameraParameters::KEY_FLASH_MODE,
563                 CameraParameters::FLASH_MODE_OFF);
564         mDevice->setParameters(mParameters);
565     }
566     mDevice->stopPreview();
567     status_t res = native_window_api_disconnect(mSurface.get(),
568             NATIVE_WINDOW_API_CAMERA);
569     if (res) {
570         ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
571                 __FUNCTION__, strerror(-res), res);
572     }
573     mDevice->setPreviewWindow(NULL);
574     mDevice->release();
575     mDevice = NULL;
576 
577     return OK;
578 }
579 // CameraHardwareInterfaceFlashControl implementation ends
580 
581 }
582