diff --git a/camera/device/3.8/ICameraDevice.hal b/camera/device/3.8/ICameraDevice.hal index 448f176220..1101819a4d 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 @@ import @3.7::ICameraDevice; * @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 77974fcbe4..01ec9cb2fc 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 #include #include +#include #include #include #include @@ -911,6 +912,7 @@ public: 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 *physicalIds/*out*/); @@ -2933,6 +2935,137 @@ TEST_P(CameraHidlTest, getCameraCharacteristics) { } } +// Verify that the torch strength level can be set and retrieved successfully. +TEST_P(CameraHidlTest, turnOnTorchWithStrengthLevel) { + hidl_vec cameraDeviceNames = getCameraDeviceNames(mProvider); + bool torchControlSupported = false; + bool torchStrengthControlSupported = false; + Return 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 cb = new TorchProviderCb(this); + Return 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(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 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 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 @@ Status CameraHidlTest::isLogicalMultiCamera(const camera_metadata_t *staticMeta) 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;