Camera: Add 3.8 version of ICameraDevice.
The new version of ICameraDevice supports interfaces for torch
strength control feature. New VTS test has been added to test the
emulator HAL-side implementation of the newly added interfaces.
bug: 200174275
Test: Camera VTS test pass.
Change-Id: Ia5652a96e09bd716b5079fe9ed071dffc53b5b12
diff --git a/camera/device/3.8/ICameraDevice.hal b/camera/device/3.8/ICameraDevice.hal
index 448f176..1101819 100644
--- a/camera/device/3.8/ICameraDevice.hal
+++ b/camera/device/3.8/ICameraDevice.hal
@@ -16,6 +16,7 @@
package android.hardware.camera.device@3.8;
+import android.hardware.camera.common@1.0::Status;
import @3.7::ICameraDevice;
/**
@@ -29,4 +30,81 @@
* @3.7::ICameraDeviceSession.
*/
interface ICameraDevice extends @3.7::ICameraDevice {
+ /**
+ * turnOnTorchWithStrengthLevel:
+ *
+ * Change the brightness level of the flash unit associated with this camera device
+ * and set it to value in torchStrength. This function also turns ON the torch
+ * with specified torchStrength if the torch is OFF.
+ *
+ * The torchStrength value must be within the valid range i.e. >=1 and
+ * <= FLASH_INFO_STRENGTH_MAXIMUM_LEVEL. Whenever the torch is turned OFF,
+ * the brightness level will reset to FLASH_INFO_STRENGTH_DEFAULT_LEVEL.
+ * When the client calls setTorchMode(ON) after turnOnTorchWithStrengthLevel(N),
+ * the flash unit will have brightness level equal to N. This level does not
+ * represent the real brightness units. It is linear in nature i.e. flashlight
+ * at level 10 is twice as bright as at level 5.
+ *
+ * @param torchStrength Brightness level to be set for the flashlight.
+ *
+ * @return status Status code for the operation, one of:
+ * OK:
+ * On a successful change to the torch strength level.
+ * INTERNAL_ERROR:
+ * The flash unit cannot be operated due to an unexpected internal
+ * error.
+ * CAMERA_IN_USE:
+ * This status code is returned when:
+ * - This camera device has been opened, so the torch cannot be
+ * controlled until it is closed.
+ * - Due to other camera devices being open, or due to other
+ * resource constraints, the torch cannot be controlled currently.
+ * ILLEGAL_ARGUMENT:
+ * If the torchStrength value is not within the range i.e. < 1 or
+ * > FLASH_INFO_STRENGTH_MAXIMUM_LEVEL.
+ * METHOD_NOT_SUPPORTED:
+ * This status code is returned when:
+ * - This camera device does not support direct operation of flashlight
+ * torch mode. The framework must open the camera device and turn
+ * the torch on through the device interface.
+ * - This camera device does not have a flash unit.
+ * - This camera device has flash unit but does not support torch
+ * strength control.
+ * CAMERA_DISCONNECTED:
+ * An external camera device has been disconnected, and is no longer
+ * available. This camera device interface is now stale, and a new
+ * instance must be acquired if the device is reconnected. All
+ * subsequent calls on this interface must return
+ * CAMERA_DISCONNECTED.
+ *
+ */
+ turnOnTorchWithStrengthLevel(int32_t torchStrength) generates (Status status);
+
+ /**
+ * getTorchStrengthLevel:
+ *
+ * Get current torch strength level.
+ * If the device supports torch strength control, when the torch is OFF the
+ * strength level will reset to default level, so the return
+ * value in this case will be equal to FLASH_INFO_STRENGTH_DEFAULT_LEVEL.
+ *
+ * @return status Status code for the operation, one of:
+ * OK:
+ * On success.
+ * INTERNAL_ERROR:
+ * An unexpected error occurred and the information is not
+ * available.
+ * METHOD_NOT_SUPPORTED:
+ * This status code is returned when:
+ * - This camera device does not support direct operation of flashlight
+ * torch mode. The framework must open the camera device and turn
+ * the torch on through the device interface.
+ * - This camera device does not have a flash unit.
+ * - This camera device has flash unit but does not support torch
+ * strength control.
+ *
+ * @return torchStrength Current torch strength level.
+ *
+ */
+ getTorchStrengthLevel() generates (Status status, int32_t torchStrength);
};
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 77974fc..01ec9cb 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -41,6 +41,7 @@
#include <android/hardware/camera/device/3.6/ICameraDevice.h>
#include <android/hardware/camera/device/3.6/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraDevice.h>
+#include <android/hardware/camera/device/3.8/ICameraDevice.h>
#include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
#include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
#include <android/hardware/camera/device/3.8/ICameraDeviceCallback.h>
@@ -911,6 +912,7 @@
uint32_t* outBufSize);
static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
static Status isLogicalMultiCamera(const camera_metadata_t *staticMeta);
+ static bool isTorchStrengthControlSupported(const camera_metadata_t *staticMeta);
static Status isOfflineSessionSupported(const camera_metadata_t *staticMeta);
static Status getPhysicalCameraIds(const camera_metadata_t *staticMeta,
std::unordered_set<std::string> *physicalIds/*out*/);
@@ -2933,6 +2935,137 @@
}
}
+// Verify that the torch strength level can be set and retrieved successfully.
+TEST_P(CameraHidlTest, turnOnTorchWithStrengthLevel) {
+ hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ bool torchControlSupported = false;
+ bool torchStrengthControlSupported = false;
+ Return<void> ret;
+
+ ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) {
+ ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support);
+ ASSERT_EQ(Status::OK, status);
+ torchControlSupported = support;
+ });
+
+ sp<TorchProviderCb> cb = new TorchProviderCb(this);
+ Return<Status> returnStatus = mProvider->setCallback(cb);
+ ASSERT_TRUE(returnStatus.isOk());
+ ASSERT_EQ(Status::OK, returnStatus);
+
+ for (const auto& name : cameraDeviceNames) {
+ int deviceVersion = getCameraDeviceVersion(name, mProviderType);
+ int32_t defaultLevel;
+ switch (deviceVersion) {
+ case CAMERA_DEVICE_API_VERSION_3_8: {
+ ::android::sp<::android::hardware::camera::device::V3_8::ICameraDevice> device3_8;
+ ALOGI("%s: Testing camera device %s", __FUNCTION__, name.c_str());
+ ret = mProvider->getCameraDeviceInterface_V3_x(
+ name, [&](auto status, const auto& device) {
+ ASSERT_EQ(Status::OK, status);
+ ASSERT_NE(device, nullptr);
+ auto castResult = device::V3_8::ICameraDevice::castFrom(device);
+ ASSERT_TRUE(castResult.isOk());
+ device3_8 = castResult;
+ });
+ ASSERT_TRUE(ret.isOk());
+
+ ret = device3_8->getCameraCharacteristics([&] (auto s, const auto& chars) {
+ ASSERT_EQ(Status::OK, s);
+ const camera_metadata_t* staticMeta =
+ reinterpret_cast<const camera_metadata_t*>(chars.data());
+ ASSERT_NE(nullptr, staticMeta);
+ torchStrengthControlSupported = isTorchStrengthControlSupported(staticMeta);
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(staticMeta,
+ ANDROID_FLASH_INFO_STRENGTH_DEFAULT_LEVEL, &entry);
+ if (torchStrengthControlSupported) {
+ ASSERT_EQ(rc, 0);
+ ASSERT_GT(entry.count, 0);
+ defaultLevel = *entry.data.i32;
+ ALOGI("Default level is:%d", defaultLevel);
+ }
+ });
+ ASSERT_TRUE(ret.isOk());
+ // If torchStrengthControl is supported, torchControlSupported should be true.
+ if (torchStrengthControlSupported) {
+ ASSERT_TRUE(torchControlSupported);
+ }
+ mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+ returnStatus = device3_8->turnOnTorchWithStrengthLevel(2);
+ ASSERT_TRUE(returnStatus.isOk());
+ // Method_not_supported check
+ if (!torchStrengthControlSupported) {
+ ALOGI("Torch strength control not supported.");
+ ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
+ } else {
+ ASSERT_EQ(Status::OK, returnStatus);
+ if (returnStatus == Status::OK) {
+ {
+ std::unique_lock<std::mutex> l(mTorchLock);
+ while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+ auto timeout = std::chrono::system_clock::now() +
+ std::chrono::seconds(kTorchTimeoutSec);
+ ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
+ timeout));
+ }
+ ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
+ mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+ }
+ ALOGI("getTorchStrengthLevel: Testing");
+ ret = device3_8->getTorchStrengthLevel([&]
+ (auto status, const auto& strengthLevel) {
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(Status::OK, status);
+ ALOGI("Torch strength level is : %d", strengthLevel);
+ ASSERT_EQ(strengthLevel, 2);
+ });
+ // Turn OFF the torch and verify torch strength level is reset to default level.
+ ALOGI("Testing torch strength level reset after turning the torch OFF.");
+ returnStatus = device3_8->setTorchMode(TorchMode::OFF);
+ ASSERT_TRUE(returnStatus.isOk());
+ ASSERT_EQ(Status::OK, returnStatus);
+ {
+ std::unique_lock<std::mutex> l(mTorchLock);
+ while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+ auto timeout = std::chrono::system_clock::now() +
+ std::chrono::seconds(kTorchTimeoutSec);
+ ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l,
+ timeout));
+ }
+ ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
+ }
+ ret = device3_8->getTorchStrengthLevel([&]
+ (auto status, const auto& strengthLevel) {
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_EQ(Status::OK, status);
+ ALOGI("Torch strength level after turning OFF torch is : %d",
+ strengthLevel);
+ ASSERT_EQ(strengthLevel, defaultLevel);
+ });
+ }
+ }
+ }
+ break;
+ case CAMERA_DEVICE_API_VERSION_3_7:
+ case CAMERA_DEVICE_API_VERSION_3_6:
+ case CAMERA_DEVICE_API_VERSION_3_5:
+ case CAMERA_DEVICE_API_VERSION_3_4:
+ case CAMERA_DEVICE_API_VERSION_3_3:
+ case CAMERA_DEVICE_API_VERSION_3_2:
+ case CAMERA_DEVICE_API_VERSION_1_0: {
+ ALOGI("Torch strength control feature not supported.");
+ }
+ break;
+ default: {
+ ALOGI("Invalid device version.");
+ ADD_FAILURE();
+ }
+ break;
+ }
+ }
+}
+
//In case it is supported verify that torch can be enabled.
//Check for corresponding toch callbacks as well.
TEST_P(CameraHidlTest, setTorchMode) {
@@ -6600,6 +6733,22 @@
return ret;
}
+bool CameraHidlTest::isTorchStrengthControlSupported(const camera_metadata_t *staticMetadata) {
+ int32_t maxLevel = 0;
+ camera_metadata_ro_entry maxEntry;
+ int rc = find_camera_metadata_ro_entry(staticMetadata,
+ ANDROID_FLASH_INFO_STRENGTH_MAXIMUM_LEVEL, &maxEntry);
+ if (rc != 0) {
+ return false;
+ }
+ maxLevel = *maxEntry.data.i32;
+ if (maxLevel > 1) {
+ ALOGI("Torch strength control supported.");
+ return true;
+ }
+ return false;
+}
+
// Check if the camera device has logical multi-camera capability.
Status CameraHidlTest::isOfflineSessionSupported(const camera_metadata_t *staticMeta) {
Status ret = Status::METHOD_NOT_SUPPORTED;