Camera: Add support for torch strength control.
This change consists of support to control flashunit brightness level
and getting the current brightness level for the flash unit associated
with camera device.
Test: Flashlight CTS
Bug: 200174275
Change-Id: I7f0b4c826e6ccef157ec22a3b3b8cf75a6b2152d
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index 78a77d4..3687b15 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -173,6 +173,13 @@
void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder);
+ // Change the brightness level of the flash unit associated with cameraId to strengthLevel.
+ // If the torch is in OFF state and strengthLevel > 0 then the torch will also be turned ON.
+ void turnOnTorchWithStrengthLevel(String cameraId, int strengthLevel, IBinder clientBinder);
+
+ // Get the brightness level of the flash unit associated with cameraId.
+ int getTorchStrengthLevel(String cameraId);
+
/**
* Notify the camera service of a system event. Should only be called from system_server.
*
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index c54813c..5f17f5b 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -83,6 +83,8 @@
oneway void onTorchStatusChanged(int status, String cameraId);
+ oneway void onTorchStrengthLevelChanged(String cameraId, int newTorchStrength);
+
/**
* Notify registered clients about camera access priority changes.
* Clients which were previously unable to open a certain camera device
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index da887a2..d53d809 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -95,6 +95,9 @@
virtual binder::Status onTorchStatusChanged(int32_t, const String16&) {
return binder::Status::ok();
}
+ virtual binder::Status onTorchStrengthLevelChanged(const String16&, int32_t) {
+ return binder::Status::ok();
+ }
virtual binder::Status onCameraAccessPrioritiesChanged();
virtual binder::Status onCameraOpened(const String16&, const String16&) {
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 9f2f430..17ea512 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -96,6 +96,12 @@
return binder::Status::ok();
};
+ virtual binder::Status onTorchStrengthLevelChanged(const String16& /*cameraId*/,
+ int32_t /*torchStrength*/) {
+ // No op
+ return binder::Status::ok();
+ }
+
virtual binder::Status onCameraAccessPrioritiesChanged() {
// No op
return binder::Status::ok();
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index ccdd9e5..015ae2f 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -119,6 +119,59 @@
return res;
}
+status_t CameraFlashlight::turnOnTorchWithStrengthLevel(const String8& cameraId,
+ int32_t torchStrength) {
+ if (!mFlashlightMapInitialized) {
+ ALOGE("%s: findFlashUnits() must be called before this method.",
+ __FUNCTION__);
+ return NO_INIT;
+ }
+
+ ALOGV("%s: set torch strength of camera %s to %d", __FUNCTION__,
+ cameraId.string(), torchStrength);
+ status_t res = OK;
+ Mutex::Autolock l(mLock);
+
+ if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
+ ALOGE("%s: Camera device %s is in use, cannot be turned ON.",
+ __FUNCTION__, cameraId.string());
+ return -EBUSY;
+ }
+
+ if (mFlashControl == NULL) {
+ res = createFlashlightControl(cameraId);
+ if (res) {
+ return res;
+ }
+ }
+
+ res = mFlashControl->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
+ return res;
+}
+
+
+status_t CameraFlashlight::getTorchStrengthLevel(const String8& cameraId,
+ int32_t* torchStrength) {
+ status_t res = OK;
+ if (!mFlashlightMapInitialized) {
+ ALOGE("%s: findFlashUnits() must be called before this method.",
+ __FUNCTION__);
+ return false;
+ }
+
+ Mutex::Autolock l(mLock);
+
+ if (mFlashControl == NULL) {
+ res = createFlashlightControl(cameraId);
+ if (res) {
+ return res;
+ }
+ }
+
+ res = mFlashControl->getTorchStrengthLevel(cameraId, torchStrength);
+ return res;
+}
+
status_t CameraFlashlight::findFlashUnits() {
Mutex::Autolock l(mLock);
status_t res;
@@ -306,6 +359,22 @@
return mProviderManager->setTorchMode(cameraId.string(), enabled);
}
+
+status_t ProviderFlashControl::turnOnTorchWithStrengthLevel(const String8& cameraId,
+ int32_t torchStrength) {
+ ALOGV("%s: change torch strength level of camera %s to %d", __FUNCTION__,
+ cameraId.string(), torchStrength);
+
+ return mProviderManager->turnOnTorchWithStrengthLevel(cameraId.string(), torchStrength);
+}
+
+status_t ProviderFlashControl::getTorchStrengthLevel(const String8& cameraId,
+ int32_t* torchStrength) {
+ ALOGV("%s: get torch strength level of camera %s", __FUNCTION__,
+ cameraId.string());
+
+ return mProviderManager->getTorchStrengthLevel(cameraId.string(), torchStrength);
+}
// ProviderFlashControl implementation ends
}
diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h
index b97fa5f..1703ddc 100644
--- a/services/camera/libcameraservice/CameraFlashlight.h
+++ b/services/camera/libcameraservice/CameraFlashlight.h
@@ -44,6 +44,14 @@
// set the torch mode to on or off.
virtual status_t setTorchMode(const String8& cameraId,
bool enabled) = 0;
+
+ // Change the brightness level of the torch. If the torch is OFF and
+ // torchStrength >= 1, then the torch will also be turned ON.
+ virtual status_t turnOnTorchWithStrengthLevel(const String8& cameraId,
+ int32_t torchStrength) = 0;
+
+ // Returns the torch strength level.
+ virtual status_t getTorchStrengthLevel(const String8& cameraId, int32_t* torchStrength) = 0;
};
/**
@@ -67,6 +75,12 @@
// set the torch mode to on or off.
status_t setTorchMode(const String8& cameraId, bool enabled);
+ // Change the torch strength level of the flash unit in torch mode.
+ status_t turnOnTorchWithStrengthLevel(const String8& cameraId, int32_t torchStrength);
+
+ // Get the torch strength level
+ status_t getTorchStrengthLevel(const String8& cameraId, int32_t* torchStrength);
+
// Notify CameraFlashlight that camera service is going to open a camera
// device. CameraFlashlight will free the resources that may cause the
// camera open to fail. Camera service must call this function before
@@ -115,6 +129,8 @@
// FlashControlBase
status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
status_t setTorchMode(const String8& cameraId, bool enabled);
+ status_t turnOnTorchWithStrengthLevel(const String8& cameraId, int32_t torchStrength);
+ status_t getTorchStrengthLevel(const String8& cameraId, int32_t* torchStrength);
private:
sp<CameraProviderManager> mProviderManager;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 569ab63..e65a27a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -569,6 +569,15 @@
onTorchStatusChangedLocked(cameraId, newStatus, systemCameraKind);
}
+void CameraService::broadcastTorchStrengthLevel(const String8& cameraId,
+ int32_t newStrengthLevel) {
+ Mutex::Autolock lock(mStatusListenerLock);
+ for (auto& i : mListenerList) {
+ i->getListener()->onTorchStrengthLevelChanged(String16{cameraId},
+ newStrengthLevel);
+ }
+}
+
void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d",
@@ -804,6 +813,31 @@
return ret;
}
+Status CameraService::getTorchStrengthLevel(const String16& cameraId,
+ int32_t* torchStrength) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mServiceLock);
+ if (!mInitialized) {
+ ALOGE("%s: Camera HAL couldn't be initialized.", __FUNCTION__);
+ return STATUS_ERROR(ERROR_DISCONNECTED, "Camera HAL couldn't be initialized.");
+ }
+
+ if(torchStrength == NULL) {
+ ALOGE("%s: strength level must not be null.", __FUNCTION__);
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Strength level should not be null.");
+ }
+
+ status_t res = mCameraProviderManager->getTorchStrengthLevel(String8(cameraId).string(),
+ torchStrength);
+ if (res != OK) {
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve torch "
+ "strength level for device %s: %s (%d)", String8(cameraId).string(),
+ strerror(-res), res);
+ }
+ ALOGI("%s: Torch strength level is: %d", __FUNCTION__, *torchStrength);
+ return Status::ok();
+}
+
String8 CameraService::getFormattedCurrentTime() {
time_t now = time(nullptr);
char formattedTime[64];
@@ -2004,6 +2038,132 @@
return OK;
}
+Status CameraService::turnOnTorchWithStrengthLevel(const String16& cameraId, int32_t torchStrength,
+ const sp<IBinder>& clientBinder) {
+ Mutex::Autolock lock(mServiceLock);
+
+ ATRACE_CALL();
+ if (clientBinder == nullptr) {
+ ALOGE("%s: torch client binder is NULL", __FUNCTION__);
+ return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
+ "Torch client binder in null.");
+ }
+
+ String8 id = String8(cameraId.string());
+ int uid = CameraThreadState::getCallingUid();
+
+ if (shouldRejectSystemCameraConnection(id)) {
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to change the strength level"
+ "for system only device %s: ", id.string());
+ }
+
+ // verify id is valid
+ auto state = getCameraState(id);
+ if (state == nullptr) {
+ ALOGE("%s: camera id is invalid %s", __FUNCTION__, id.string());
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
+ "Camera ID \"%s\" is a not valid camera ID", id.string());
+ }
+
+ StatusInternal cameraStatus = state->getStatus();
+ if (cameraStatus != StatusInternal::NOT_AVAILABLE &&
+ cameraStatus != StatusInternal::PRESENT) {
+ ALOGE("%s: camera id is invalid %s, status %d", __FUNCTION__, id.string(),
+ (int)cameraStatus);
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
+ "Camera ID \"%s\" is a not valid camera ID", id.string());
+ }
+
+ {
+ Mutex::Autolock al(mTorchStatusMutex);
+ TorchModeStatus status;
+ status_t err = getTorchStatusLocked(id, &status);
+ if (err != OK) {
+ if (err == NAME_NOT_FOUND) {
+ return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
+ "Camera \"%s\" does not have a flash unit", id.string());
+ }
+ ALOGE("%s: getting current torch status failed for camera %s",
+ __FUNCTION__, id.string());
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
+ "Error changing torch strength level for camera \"%s\": %s (%d)",
+ id.string(), strerror(-err), err);
+ }
+
+ if (status == TorchModeStatus::NOT_AVAILABLE) {
+ if (cameraStatus == StatusInternal::NOT_AVAILABLE) {
+ ALOGE("%s: torch mode of camera %s is not available because "
+ "camera is in use.", __FUNCTION__, id.string());
+ return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
+ "Torch for camera \"%s\" is not available due to an existing camera user",
+ id.string());
+ } else {
+ ALOGE("%s: torch mode of camera %s is not available due to "
+ "insufficient resources", __FUNCTION__, id.string());
+ return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
+ "Torch for camera \"%s\" is not available due to insufficient resources",
+ id.string());
+ }
+ }
+ }
+
+ {
+ Mutex::Autolock al(mTorchUidMapMutex);
+ updateTorchUidMapLocked(cameraId, uid);
+ }
+ // Check if the current torch strength level is same as the new one.
+ bool shouldSkipTorchStrengthUpdates = mCameraProviderManager->shouldSkipTorchStrengthUpdate(
+ id.string(), torchStrength);
+
+ status_t err = mFlashlight->turnOnTorchWithStrengthLevel(id, torchStrength);
+
+ if (err != OK) {
+ int32_t errorCode;
+ String8 msg;
+ switch (err) {
+ case -ENOSYS:
+ msg = String8::format("Camera \"%s\" has no flashlight.",
+ id.string());
+ errorCode = ERROR_ILLEGAL_ARGUMENT;
+ break;
+ case -EBUSY:
+ msg = String8::format("Camera \"%s\" is in use",
+ id.string());
+ errorCode = ERROR_CAMERA_IN_USE;
+ break;
+ default:
+ msg = String8::format("Changing torch strength level failed.");
+ errorCode = ERROR_INVALID_OPERATION;
+
+ }
+ ALOGE("%s: %s", __FUNCTION__, msg.string());
+ return STATUS_ERROR(errorCode, msg.string());
+ }
+
+ {
+ // update the link to client's death
+ // Store the last client that turns on each camera's torch mode.
+ Mutex::Autolock al(mTorchClientMapMutex);
+ ssize_t index = mTorchClientMap.indexOfKey(id);
+ if (index == NAME_NOT_FOUND) {
+ mTorchClientMap.add(id, clientBinder);
+ } else {
+ mTorchClientMap.valueAt(index)->unlinkToDeath(this);
+ mTorchClientMap.replaceValueAt(index, clientBinder);
+ }
+ clientBinder->linkToDeath(this);
+ }
+
+ int clientPid = CameraThreadState::getCallingPid();
+ const char *id_cstr = id.c_str();
+ ALOGI("%s: Torch strength for camera id %s changed to %d for client PID %d",
+ __FUNCTION__, id_cstr, torchStrength, clientPid);
+ if (!shouldSkipTorchStrengthUpdates) {
+ broadcastTorchStrengthLevel(id, torchStrength);
+ }
+ return Status::ok();
+}
+
Status CameraService::setTorchMode(const String16& cameraId, bool enabled,
const sp<IBinder>& clientBinder) {
Mutex::Autolock lock(mServiceLock);
@@ -2075,13 +2235,7 @@
// Update UID map - this is used in the torch status changed callbacks, so must be done
// before setTorchMode
Mutex::Autolock al(mTorchUidMapMutex);
- if (mTorchUidMap.find(id) == mTorchUidMap.end()) {
- mTorchUidMap[id].first = uid;
- mTorchUidMap[id].second = uid;
- } else {
- // Set the pending UID
- mTorchUidMap[id].first = uid;
- }
+ updateTorchUidMapLocked(cameraId, uid);
}
status_t err = mFlashlight->setTorchMode(id, enabled);
@@ -2136,6 +2290,17 @@
return Status::ok();
}
+void CameraService::updateTorchUidMapLocked(const String16& cameraId, int uid) {
+ String8 id = String8(cameraId.string());
+ if (mTorchUidMap.find(id) == mTorchUidMap.end()) {
+ mTorchUidMap[id].first = uid;
+ mTorchUidMap[id].second = uid;
+ } else {
+ // Set the pending UID
+ mTorchUidMap[id].first = uid;
+ }
+}
+
Status CameraService::notifySystemEvent(int32_t eventId,
const std::vector<int32_t>& args) {
const int pid = CameraThreadState::getCallingPid();
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 51c734f..060f075 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -172,6 +172,12 @@
virtual binder::Status setTorchMode(const String16& cameraId, bool enabled,
const sp<IBinder>& clientBinder);
+ virtual binder::Status turnOnTorchWithStrengthLevel(const String16& cameraId,
+ int32_t torchStrength, const sp<IBinder>& clientBinder);
+
+ virtual binder::Status getTorchStrengthLevel(const String16& cameraId,
+ int32_t* torchStrength);
+
virtual binder::Status notifySystemEvent(int32_t eventId,
const std::vector<int32_t>& args);
@@ -1232,6 +1238,8 @@
hardware::camera::common::V1_0::TorchModeStatus status,
SystemCameraKind systemCameraKind);
+ void broadcastTorchStrengthLevel(const String8& cameraId, int32_t newTorchStrengthLevel);
+
void disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect);
// Regular online and offline devices must not be in conflict at camera service layer.
@@ -1310,6 +1318,8 @@
bool mInjectionInitPending = false;
// Guard mInjectionInternalCamId and mInjectionInitPending.
Mutex mInjectionParametersLock;
+
+ void updateTorchUidMapLocked(const String16& cameraId, int uid);
};
} // namespace android
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 0cce2ca..d37d717 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -20,7 +20,7 @@
#include "CameraProviderManager.h"
-#include <android/hardware/camera/device/3.7/ICameraDevice.h>
+#include <android/hardware/camera/device/3.8/ICameraDevice.h>
#include <algorithm>
#include <chrono>
@@ -307,6 +307,50 @@
return OK;
}
+status_t CameraProviderManager::getTorchStrengthLevel(const std::string &id,
+ int32_t* torchStrength /*out*/) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ return deviceInfo->getTorchStrengthLevel(torchStrength);
+}
+
+status_t CameraProviderManager::turnOnTorchWithStrengthLevel(const std::string &id,
+ int32_t torchStrength) {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ return deviceInfo->turnOnTorchWithStrengthLevel(torchStrength);
+}
+
+bool CameraProviderManager::shouldSkipTorchStrengthUpdate(const std::string &id,
+ int32_t torchStrength) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ if (deviceInfo->mTorchStrengthLevel == torchStrength) {
+ ALOGV("%s: Skipping torch strength level updates prev_level: %d, new_level: %d",
+ __FUNCTION__, deviceInfo->mTorchStrengthLevel, torchStrength);
+ return true;
+ }
+ return false;
+}
+
+int32_t CameraProviderManager::getTorchDefaultStrengthLevel(const std::string &id) const {
+ std::lock_guard<std::mutex> lock(mInterfaceMutex);
+
+ auto deviceInfo = findDeviceInfoLocked(id);
+ if (deviceInfo == nullptr) return NAME_NOT_FOUND;
+
+ return deviceInfo->mTorchDefaultStrengthLevel;
+}
+
bool CameraProviderManager::supportSetTorchMode(const std::string &id) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
for (auto& provider : mProviders) {
@@ -2385,6 +2429,22 @@
mHasFlashUnit = false;
}
+ camera_metadata_entry entry =
+ mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL);
+ if (entry.count == 1) {
+ mTorchDefaultStrengthLevel = entry.data.i32[0];
+ } else {
+ mTorchDefaultStrengthLevel = 0;
+ }
+
+ entry = mCameraCharacteristics.find(ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL);
+ if (entry.count == 1) {
+ mTorchMaximumStrengthLevel = entry.data.i32[0];
+ } else {
+ mTorchMaximumStrengthLevel = 0;
+ }
+
+ mTorchStrengthLevel = 0;
queryPhysicalCameraIds();
// Get physical camera characteristics if applicable
@@ -2468,6 +2528,80 @@
return setTorchModeForDevice<InterfaceT>(enabled);
}
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::turnOnTorchWithStrengthLevel(
+ int32_t torchStrength) {
+ const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
+ startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ if (castResult_3_8.isOk()) {
+ interface_3_8 = castResult_3_8;
+ }
+
+ if (interface_3_8 == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ Status s = interface_3_8->turnOnTorchWithStrengthLevel(torchStrength);
+ if (s == Status::OK) {
+ mTorchStrengthLevel = torchStrength;
+ }
+ return mapToStatusT(s);
+}
+
+status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getTorchStrengthLevel(
+ int32_t *torchStrength) {
+ if (torchStrength == nullptr) {
+ return BAD_VALUE;
+ }
+ const sp<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT> interface =
+ startDeviceInterface<CameraProviderManager::ProviderInfo::DeviceInfo3::InterfaceT>();
+ if (interface == nullptr) {
+ return DEAD_OBJECT;
+ }
+ auto castResult_3_8 = device::V3_8::ICameraDevice::castFrom(interface);
+ sp<hardware::camera::device::V3_8::ICameraDevice> interface_3_8 = nullptr;
+ if (castResult_3_8.isOk()) {
+ interface_3_8 = castResult_3_8;
+ }
+
+ if (interface_3_8 == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ Status callStatus;
+ status_t res;
+ hardware::Return<void> ret = interface_3_8->getTorchStrengthLevel([&callStatus, &torchStrength]
+ (Status status, const int32_t& torchStrengthLevel) {
+ callStatus = status;
+ if (status == Status::OK) {
+ *torchStrength = torchStrengthLevel;
+ } });
+
+ if (ret.isOk()) {
+ switch (callStatus) {
+ case Status::OK:
+ // Expected case, do nothing.
+ res = OK;
+ break;
+ case Status::METHOD_NOT_SUPPORTED:
+ res = INVALID_OPERATION;
+ break;
+ default:
+ ALOGE("%s: Get torch strength level failed: %d", __FUNCTION__, callStatus);
+ res = UNKNOWN_ERROR;
+ }
+ } else {
+ ALOGE("%s: Unexpected binder error: %s", __FUNCTION__, ret.description().c_str());
+ res = UNKNOWN_ERROR;
+ }
+
+ return res;
+}
+
status_t CameraProviderManager::ProviderInfo::DeviceInfo3::getCameraInfo(
hardware::CameraInfo *info) const {
if (info == nullptr) return BAD_VALUE;
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index f28d128..7d13941 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -258,6 +258,17 @@
bool supportSetTorchMode(const std::string &id) const;
/**
+ * Check if torch strength update should be skipped or not.
+ */
+ bool shouldSkipTorchStrengthUpdate(const std::string &id, int32_t torchStrength) const;
+
+ /**
+ * Return the default torch strength level if the torch strength control
+ * feature is supported.
+ */
+ int32_t getTorchDefaultStrengthLevel(const std::string &id) const;
+
+ /**
* Turn on or off the flashlight on a given camera device.
* May fail if the device does not support this API, is in active use, or if the device
* doesn't exist, etc.
@@ -265,6 +276,24 @@
status_t setTorchMode(const std::string &id, bool enabled);
/**
+ * Change the brightness level of the flash unit associated with the cameraId and
+ * set it to the value in torchStrength.
+ * If the torch is OFF and torchStrength > 0, the torch will be turned ON with the
+ * specified strength level. If the torch is ON, only the brightness level will be
+ * changed.
+ *
+ * This operation will fail if the device does not have flash unit, has flash unit
+ * but does not support this API, torchStrength is invalid or if the device doesn't
+ * exist etc.
+ */
+ status_t turnOnTorchWithStrengthLevel(const std::string &id, int32_t torchStrength);
+
+ /**
+ * Return the torch strength level of this camera device.
+ */
+ status_t getTorchStrengthLevel(const std::string &id, int32_t* torchStrength);
+
+ /**
* Setup vendor tags for all registered providers
*/
status_t setUpVendorTags();
@@ -475,10 +504,17 @@
hardware::camera::common::V1_0::CameraDeviceStatus mStatus;
wp<ProviderInfo> mParentProvider;
+ // Torch strength default, maximum levels if the torch strength control
+ // feature is supported.
+ int32_t mTorchStrengthLevel;
+ int32_t mTorchMaximumStrengthLevel;
+ int32_t mTorchDefaultStrengthLevel;
bool hasFlashUnit() const { return mHasFlashUnit; }
bool supportNativeZoomRatio() const { return mSupportNativeZoomRatio; }
virtual status_t setTorchMode(bool enabled) = 0;
+ virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) = 0;
+ virtual status_t getTorchStrengthLevel(int32_t *torchStrength) = 0;
virtual status_t getCameraInfo(hardware::CameraInfo *info) const = 0;
virtual bool isAPI1Compatible() const = 0;
virtual status_t dumpState(int fd) = 0;
@@ -551,6 +587,9 @@
typedef hardware::camera::device::V3_2::ICameraDevice InterfaceT;
virtual status_t setTorchMode(bool enabled) override;
+ virtual status_t turnOnTorchWithStrengthLevel(int32_t torchStrength) override;
+ virtual status_t getTorchStrengthLevel(int32_t *torchStrength) override;
+
virtual status_t getCameraInfo(hardware::CameraInfo *info) const override;
virtual bool isAPI1Compatible() const override;
virtual status_t dumpState(int fd) override;
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
index 8e619e1..cca3f2e 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
@@ -70,6 +70,11 @@
return binder::Status::ok();
}
+::android::binder::Status H2BCameraServiceListener::onTorchStrengthLevelChanged(
+ const ::android::String16&, int32_t) {
+ return binder::Status::ok();
+}
+
} // implementation
} // V2_0
} // common
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 7148035..7ef413f 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -54,6 +54,8 @@
virtual ::android::binder::Status onTorchStatusChanged(
int32_t status, const ::android::String16& cameraId) override;
+ virtual ::android::binder::Status onTorchStrengthLevelChanged(
+ const ::android::String16& cameraId, int32_t newStrengthLevel) override;
virtual binder::Status onCameraAccessPrioritiesChanged() {
// TODO: no implementation yet.
return binder::Status::ok();
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index e46bf74..97d7bf4 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -466,6 +466,12 @@
// No op
return binder::Status::ok();
}
+
+ virtual binder::Status onTorchStrengthLevelChanged(const String16& /*cameraId*/,
+ int32_t /*torchStrength*/) {
+ // No op
+ return binder::Status::ok();
+ }
};
class TestCameraDeviceCallbacks : public hardware::camera2::BnCameraDeviceCallbacks {