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;
}