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         // Only HAL1 devices do not support setTorchMode
63         mFlashControl =
64                 new CameraHardwareInterfaceFlashControl(mProviderManager, mCallbacks);
65     }
66 
67     return OK;
68 }
69 
setTorchMode(const String8 & cameraId,bool enabled)70 status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
71     if (!mFlashlightMapInitialized) {
72         ALOGE("%s: findFlashUnits() must be called before this method.",
73                __FUNCTION__);
74         return NO_INIT;
75     }
76 
77     ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
78             cameraId.string(), enabled);
79 
80     status_t res = OK;
81     Mutex::Autolock l(mLock);
82 
83     if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
84         // This case is needed to avoid state corruption during the following call sequence:
85         // CameraService::setTorchMode for camera ID 0 begins, does torch status checks
86         // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends
87         // CameraService::setTorchMode for camera ID 0 continues, calls
88         //        CameraFlashlight::setTorchMode
89 
90         // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
91         // to avoid other similar race conditions.
92         ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
93                 __FUNCTION__, cameraId.string());
94         return -EBUSY;
95     }
96 
97     if (mFlashControl == NULL) {
98         res = createFlashlightControl(cameraId);
99         if (res) {
100             return res;
101         }
102         res =  mFlashControl->setTorchMode(cameraId, enabled);
103         return res;
104     }
105 
106     // if flash control already exists, turning on torch mode may fail if it's
107     // tied to another camera device for module v2.3 and below.
108     res = mFlashControl->setTorchMode(cameraId, enabled);
109     if (res == BAD_INDEX) {
110         // flash control is tied to another camera device, need to close it and
111         // try again.
112         mFlashControl.clear();
113         res = createFlashlightControl(cameraId);
114         if (res) {
115             return res;
116         }
117         res = mFlashControl->setTorchMode(cameraId, enabled);
118     }
119 
120     return res;
121 }
122 
findFlashUnits()123 status_t CameraFlashlight::findFlashUnits() {
124     Mutex::Autolock l(mLock);
125     status_t res;
126 
127     std::vector<String8> cameraIds;
128     std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
129     int numberOfCameras = static_cast<int>(ids.size());
130     cameraIds.resize(numberOfCameras);
131     // No module, must be provider
132     for (size_t i = 0; i < cameraIds.size(); i++) {
133         cameraIds[i] = String8(ids[i].c_str());
134     }
135 
136     mFlashControl.clear();
137 
138     for (auto &id : cameraIds) {
139         ssize_t index = mHasFlashlightMap.indexOfKey(id);
140         if (0 <= index) {
141             continue;
142         }
143 
144         bool hasFlash = false;
145         res = createFlashlightControl(id);
146         if (res) {
147             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
148                     id.string());
149         } else {
150             res = mFlashControl->hasFlashUnit(id, &hasFlash);
151             if (res == -EUSERS || res == -EBUSY) {
152                 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
153                         "camera devices may be opened", __FUNCTION__,
154                         id.string());
155                 return res;
156             } else if (res) {
157                 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
158                         " (%d)", __FUNCTION__, id.string(), strerror(-res),
159                         res);
160             }
161 
162             mFlashControl.clear();
163         }
164         mHasFlashlightMap.add(id, hasFlash);
165     }
166 
167     mFlashlightMapInitialized = true;
168     return OK;
169 }
170 
hasFlashUnit(const String8 & cameraId)171 bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
172     Mutex::Autolock l(mLock);
173     return hasFlashUnitLocked(cameraId);
174 }
175 
hasFlashUnitLocked(const String8 & cameraId)176 bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
177     if (!mFlashlightMapInitialized) {
178         ALOGE("%s: findFlashUnits() must be called before this method.",
179                __FUNCTION__);
180         return false;
181     }
182 
183     ssize_t index = mHasFlashlightMap.indexOfKey(cameraId);
184     if (index == NAME_NOT_FOUND) {
185         // Might be external camera
186         ALOGW("%s: camera %s not present when findFlashUnits() was called",
187                 __FUNCTION__, cameraId.string());
188         return false;
189     }
190 
191     return mHasFlashlightMap.valueAt(index);
192 }
193 
isBackwardCompatibleMode(const String8 & cameraId)194 bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
195     bool backwardCompatibleMode = false;
196     if (mProviderManager != nullptr &&
197             !mProviderManager->supportSetTorchMode(cameraId.string())) {
198         backwardCompatibleMode = true;
199     }
200     return backwardCompatibleMode;
201 }
202 
prepareDeviceOpen(const String8 & cameraId)203 status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
204     ALOGV("%s: prepare for device open", __FUNCTION__);
205 
206     Mutex::Autolock l(mLock);
207     if (!mFlashlightMapInitialized) {
208         ALOGE("%s: findFlashUnits() must be called before this method.",
209                __FUNCTION__);
210         return NO_INIT;
211     }
212 
213     if (isBackwardCompatibleMode(cameraId)) {
214         // framework is going to open a camera device, all flash light control
215         // should be closed for backward compatible support.
216         mFlashControl.clear();
217 
218         if (mOpenedCameraIds.size() == 0) {
219             // notify torch unavailable for all cameras with a flash
220             std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
221             int numCameras = static_cast<int>(ids.size());
222             for (int i = 0; i < numCameras; i++) {
223                 String8 id8(ids[i].c_str());
224                 if (hasFlashUnitLocked(id8)) {
225                     mCallbacks->onTorchStatusChanged(
226                             id8, TorchModeStatus::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         std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
267         int numCameras = static_cast<int>(ids.size());
268         for (int i = 0; i < numCameras; i++) {
269             String8 id8(ids[i].c_str());
270             if (hasFlashUnitLocked(id8)) {
271                 mCallbacks->onTorchStatusChanged(
272                         id8, TorchModeStatus::AVAILABLE_OFF);
273             }
274         }
275     }
276 
277     return OK;
278 }
279 // CameraFlashlight implementation ends
280 
281 
~FlashControlBase()282 FlashControlBase::~FlashControlBase() {
283 }
284 
285 /////////////////////////////////////////////////////////////////////
286 // ModuleFlashControl implementation begins
287 // Flash control for camera module v2.4 and above.
288 /////////////////////////////////////////////////////////////////////
ProviderFlashControl(sp<CameraProviderManager> providerManager)289 ProviderFlashControl::ProviderFlashControl(sp<CameraProviderManager> providerManager) :
290         mProviderManager(providerManager) {
291 }
292 
~ProviderFlashControl()293 ProviderFlashControl::~ProviderFlashControl() {
294 }
295 
hasFlashUnit(const String8 & cameraId,bool * hasFlash)296 status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
297     if (!hasFlash) {
298         return BAD_VALUE;
299     }
300     *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
301     return OK;
302 }
303 
setTorchMode(const String8 & cameraId,bool enabled)304 status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
305     ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
306             cameraId.string(), enabled);
307 
308     return mProviderManager->setTorchMode(cameraId.string(), enabled);
309 }
310 // ProviderFlashControl implementation ends
311 
312 /////////////////////////////////////////////////////////////////////
313 // CameraHardwareInterfaceFlashControl implementation begins
314 // Flash control for camera module <= v2.3 and camera HAL v1
315 /////////////////////////////////////////////////////////////////////
316 
CameraHardwareInterfaceFlashControl(sp<CameraProviderManager> manager,CameraProviderManager::StatusListener * callbacks)317 CameraHardwareInterfaceFlashControl::CameraHardwareInterfaceFlashControl(
318         sp<CameraProviderManager> manager,
319         CameraProviderManager::StatusListener* callbacks) :
320         mProviderManager(manager),
321         mCallbacks(callbacks),
322         mTorchEnabled(false) {
323 }
324 
~CameraHardwareInterfaceFlashControl()325 CameraHardwareInterfaceFlashControl::~CameraHardwareInterfaceFlashControl() {
326     disconnectCameraDevice();
327 
328     mSurface.clear();
329     mSurfaceTexture.clear();
330     mProducer.clear();
331     mConsumer.clear();
332 
333     if (mTorchEnabled) {
334         if (mCallbacks) {
335             ALOGV("%s: notify the framework that torch was turned off",
336                     __FUNCTION__);
337             mCallbacks->onTorchStatusChanged(mCameraId, TorchModeStatus::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->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_OFF);
372         return OK;
373     }
374 
375     res = startPreviewAndTorch();
376     if (res) {
377         return res;
378     }
379 
380     mTorchEnabled = true;
381     mCallbacks->onTorchStatusChanged(cameraId, TorchModeStatus::AVAILABLE_ON);
382     return OK;
383 }
384 
hasFlashUnit(const String8 & cameraId,bool * hasFlash)385 status_t CameraHardwareInterfaceFlashControl::hasFlashUnit(
386         const String8& cameraId, bool *hasFlash) {
387     Mutex::Autolock l(mLock);
388     // Close device after checking if it has a flash unit.
389     return hasFlashUnitLocked(cameraId, hasFlash, /*keepDeviceOpen*/false);
390 }
391 
hasFlashUnitLocked(const String8 & cameraId,bool * hasFlash,bool keepDeviceOpen)392 status_t CameraHardwareInterfaceFlashControl::hasFlashUnitLocked(
393         const String8& cameraId, bool *hasFlash, bool keepDeviceOpen) {
394     bool closeCameraDevice = false;
395 
396     if (!hasFlash) {
397         return BAD_VALUE;
398     }
399 
400     status_t res;
401     if (mDevice == NULL) {
402         // Connect to camera device to query if it has a flash unit.
403         res = connectCameraDevice(cameraId);
404         if (res) {
405             return res;
406         }
407         // Close camera device only when it is just opened and the caller doesn't want to keep
408         // the camera device open.
409         closeCameraDevice = !keepDeviceOpen;
410     }
411 
412     if (cameraId != mCameraId) {
413         return BAD_INDEX;
414     }
415 
416     const char *flashMode =
417             mParameters.get(CameraParameters::KEY_SUPPORTED_FLASH_MODES);
418     if (flashMode && strstr(flashMode, CameraParameters::FLASH_MODE_TORCH)) {
419         *hasFlash = true;
420     } else {
421         *hasFlash = false;
422     }
423 
424     if (closeCameraDevice) {
425         res = disconnectCameraDevice();
426         if (res != OK) {
427             ALOGE("%s: Failed to disconnect camera device. %s (%d)", __FUNCTION__,
428                     strerror(-res), res);
429             return res;
430         }
431     }
432 
433     return OK;
434 }
435 
startPreviewAndTorch()436 status_t CameraHardwareInterfaceFlashControl::startPreviewAndTorch() {
437     status_t res = OK;
438     res = mDevice->startPreview();
439     if (res) {
440         ALOGE("%s: start preview failed. %s (%d)", __FUNCTION__,
441                 strerror(-res), res);
442         return res;
443     }
444 
445     mParameters.set(CameraParameters::KEY_FLASH_MODE,
446             CameraParameters::FLASH_MODE_TORCH);
447 
448     return mDevice->setParameters(mParameters);
449 }
450 
getSmallestSurfaceSize(int32_t * width,int32_t * height)451 status_t CameraHardwareInterfaceFlashControl::getSmallestSurfaceSize(
452         int32_t *width, int32_t *height) {
453     if (!width || !height) {
454         return BAD_VALUE;
455     }
456 
457     int32_t w = INT32_MAX;
458     int32_t h = 1;
459     Vector<Size> sizes;
460 
461     mParameters.getSupportedPreviewSizes(sizes);
462     for (size_t i = 0; i < sizes.size(); i++) {
463         Size s = sizes[i];
464         if (w * h > s.width * s.height) {
465             w = s.width;
466             h = s.height;
467         }
468     }
469 
470     if (w == INT32_MAX) {
471         return NAME_NOT_FOUND;
472     }
473 
474     *width = w;
475     *height = h;
476 
477     return OK;
478 }
479 
initializePreviewWindow(const sp<CameraHardwareInterface> & device,int32_t width,int32_t height)480 status_t CameraHardwareInterfaceFlashControl::initializePreviewWindow(
481         const sp<CameraHardwareInterface>& device, int32_t width, int32_t height) {
482     status_t res;
483     BufferQueue::createBufferQueue(&mProducer, &mConsumer);
484 
485     mSurfaceTexture = new GLConsumer(mConsumer, 0, GLConsumer::TEXTURE_EXTERNAL,
486             true, true);
487     if (mSurfaceTexture == NULL) {
488         return NO_MEMORY;
489     }
490 
491     int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
492     res = mSurfaceTexture->setDefaultBufferSize(width, height);
493     if (res) {
494         return res;
495     }
496     res = mSurfaceTexture->setDefaultBufferFormat(format);
497     if (res) {
498         return res;
499     }
500 
501     mSurface = new Surface(mProducer, /*useAsync*/ true);
502     if (mSurface == NULL) {
503         return NO_MEMORY;
504     }
505 
506     res = native_window_api_connect(mSurface.get(), NATIVE_WINDOW_API_CAMERA);
507     if (res) {
508         ALOGE("%s: Unable to connect to native window", __FUNCTION__);
509         return res;
510     }
511 
512     return device->setPreviewWindow(mSurface);
513 }
514 
connectCameraDevice(const String8 & cameraId)515 status_t CameraHardwareInterfaceFlashControl::connectCameraDevice(
516         const String8& cameraId) {
517     sp<CameraHardwareInterface> device =
518             new CameraHardwareInterface(cameraId.string());
519 
520     status_t res = device->initialize(mProviderManager);
521     if (res) {
522         ALOGE("%s: initializing camera %s failed", __FUNCTION__,
523                 cameraId.string());
524         return res;
525     }
526 
527     // need to set __get_memory in set_callbacks().
528     device->setCallbacks(NULL, NULL, NULL, NULL, NULL);
529 
530     mParameters = device->getParameters();
531 
532     int32_t width, height;
533     res = getSmallestSurfaceSize(&width, &height);
534     if (res) {
535         ALOGE("%s: failed to get smallest surface size for camera %s",
536                 __FUNCTION__, cameraId.string());
537         return res;
538     }
539 
540     res = initializePreviewWindow(device, width, height);
541     if (res) {
542         ALOGE("%s: failed to initialize preview window for camera %s",
543                 __FUNCTION__, cameraId.string());
544         return res;
545     }
546 
547     mCameraId = cameraId;
548     mDevice = device;
549     return OK;
550 }
551 
disconnectCameraDevice()552 status_t CameraHardwareInterfaceFlashControl::disconnectCameraDevice() {
553     if (mDevice == NULL) {
554         return OK;
555     }
556 
557     if (mParameters.get(CameraParameters::KEY_FLASH_MODE)) {
558         // There is a flash, turn if off.
559         // (If there isn't one, leave the parameter null)
560         mParameters.set(CameraParameters::KEY_FLASH_MODE,
561                 CameraParameters::FLASH_MODE_OFF);
562         mDevice->setParameters(mParameters);
563     }
564     mDevice->stopPreview();
565     status_t res = native_window_api_disconnect(mSurface.get(),
566             NATIVE_WINDOW_API_CAMERA);
567     if (res) {
568         ALOGW("%s: native_window_api_disconnect failed: %s (%d)",
569                 __FUNCTION__, strerror(-res), res);
570     }
571     mDevice->setPreviewWindow(NULL);
572     mDevice->release();
573     mDevice = NULL;
574 
575     return OK;
576 }
577 // CameraHardwareInterfaceFlashControl implementation ends
578 
579 }
580