status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) { if (!mFlashlightMapInitialized) { ALOGE("%s: findFlashUnits() must be called before this method.", __FUNCTION__); return NO_INIT; } ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__, cameraId.string(), enabled); status_t res = OK; Mutex::Autolock l(mLock); if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) { // This case is needed to avoid state corruption during the following call sequence: // CameraService::setTorchMode for camera ID 0 begins, does torch status checks // CameraService::connect for camera ID 0 begins, calls prepareDeviceOpen, ends // CameraService::setTorchMode for camera ID 0 continues, calls // CameraFlashlight::setTorchMode // TODO: Move torch status checks and state updates behind this CameraFlashlight lock // to avoid other similar race conditions. ALOGE("%s: Camera device %s is in use, cannot set torch mode.", __FUNCTION__, cameraId.string()); return -EBUSY; } if (mFlashControl == NULL) { if (enabled == false) { return OK; } res = createFlashlightControl(cameraId); if (res) { return res; } res = mFlashControl->setTorchMode(cameraId, enabled); return res; } // if flash control already exists, turning on torch mode may fail if it's // tied to another camera device for module v2.3 and below. res = mFlashControl->setTorchMode(cameraId, enabled); if (res == BAD_INDEX) { // flash control is tied to another camera device, need to close it and // try again. mFlashControl.clear(); res = createFlashlightControl(cameraId); if (res) { return res; } res = mFlashControl->setTorchMode(cameraId, enabled); } return res; }
status_t CameraFlashlight::findFlashUnits() { Mutex::Autolock l(mLock); status_t res; int32_t numCameras = mCameraModule->getNumberOfCameras(); mHasFlashlightMap.clear(); mFlashlightMapInitialized = false; for (int32_t i = 0; i < numCameras; i++) { bool hasFlash = false; String8 id = String8::format("%d", i); res = createFlashlightControl(id); if (res) { ALOGE("%s: failed to create flash control for %s", __FUNCTION__, id.string()); } else { res = mFlashControl->hasFlashUnit(id, &hasFlash); if (res == -EUSERS || res == -EBUSY) { ALOGE("%s: failed to check if camera %s has a flash unit. Some " "camera devices may be opened", __FUNCTION__, id.string()); return res; } else if (res) { ALOGE("%s: failed to check if camera %s has a flash unit. %s" " (%d)", __FUNCTION__, id.string(), strerror(-res), res); } mFlashControl.clear(); } mHasFlashlightMap.add(id, hasFlash); } mFlashlightMapInitialized = true; return OK; }