From 63624099e39b0493b678b016afe3d28047e7a0be Mon Sep 17 00:00:00 2001 From: "Harpreet \\\"Eli\\\" Sangha" Date: Mon, 9 Sep 2019 11:04:54 +0900 Subject: [PATCH] vibrator: Support Always-On Effects Bug: 138909021 Test: Verify always-on haptics are configured on boot and settings change. Change-Id: I11ce5f2b974267c6e84b1843a750847492a7de15 Signed-off-by: Harpreet \"Eli\" Sangha --- .../android/hardware/vibrator/IVibrator.aidl | 31 +++++++++++++++++++ vibrator/aidl/default/Vibrator.cpp | 25 ++++++++++++++- .../default/include/vibrator-impl/Vibrator.h | 3 ++ .../aidl/vts/VtsHalVibratorTargetTest.cpp | 26 ++++++++++++++++ 4 files changed, 84 insertions(+), 1 deletion(-) diff --git a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl index ebf5faa47a..f553664eeb 100644 --- a/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl +++ b/vibrator/aidl/android/hardware/vibrator/IVibrator.aidl @@ -48,6 +48,10 @@ interface IVibrator { * Whether compose is supported. */ const int CAP_COMPOSE_EFFECTS = 1 << 5; + /** + * Whether alwaysOnEnable/alwaysOnDisable is supported. + */ + const int CAP_ALWAYS_ON_CONTROL = 1 << 6; /** * Determine capabilities of the vibrator HAL (CAP_* mask) @@ -165,4 +169,31 @@ interface IVibrator { */ void compose(in CompositeEffect[] composite, in IVibratorCallback callback); + /** + * List of supported always-on effects. + * + * Return the effects which are supported by the alwaysOnEnable (an effect + * is expected to be supported at every strength level. + */ + Effect[] getSupportedAlwaysOnEffects(); + + /** + * Enable an always-on haptic source, assigning a specific effect. An + * always-on haptic source is a source that can be triggered externally + * once enabled and assigned an effect to play. This may not be supported + * and this support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL). + * + * @param id The device-specific always-on source ID to enable. + * @param effect The type of haptic event to trigger. + * @param strength The intensity of haptic event to trigger. + */ + void alwaysOnEnable(in int id, in Effect effect, in EffectStrength strength); + + /** + * Disable an always-on haptic source. This may not be supported and this + * support is reflected in getCapabilities (CAP_ALWAYS_ON_CONTROL). + * + * @param id The device-specific always-on source ID to disable. + */ + void alwaysOnDisable(in int id); } diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp index befdeab08a..cedd9cb89c 100644 --- a/vibrator/aidl/default/Vibrator.cpp +++ b/vibrator/aidl/default/Vibrator.cpp @@ -31,7 +31,8 @@ ndk::ScopedAStatus Vibrator::getCapabilities(int32_t* _aidl_return) { LOG(INFO) << "Vibrator reporting capabilities"; *_aidl_return = IVibrator::CAP_ON_CALLBACK | IVibrator::CAP_PERFORM_CALLBACK | IVibrator::CAP_AMPLITUDE_CONTROL | IVibrator::CAP_EXTERNAL_CONTROL | - IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS; + IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL | IVibrator::CAP_COMPOSE_EFFECTS | + IVibrator::CAP_ALWAYS_ON_CONTROL; return ndk::ScopedAStatus::ok(); } @@ -151,6 +152,28 @@ ndk::ScopedAStatus Vibrator::compose(const std::vector& composi return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Vibrator::getSupportedAlwaysOnEffects(std::vector* _aidl_return) { + return getSupportedEffects(_aidl_return); +} + +ndk::ScopedAStatus Vibrator::alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) { + std::vector effects; + getSupportedAlwaysOnEffects(&effects); + + if (std::find(effects.begin(), effects.end(), effect) == effects.end()) { + return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); + } else { + LOG(INFO) << "Enabling always-on ID " << id << " with " << toString(effect) << "/" + << toString(strength); + return ndk::ScopedAStatus::ok(); + } +} + +ndk::ScopedAStatus Vibrator::alwaysOnDisable(int32_t id) { + LOG(INFO) << "Disabling always-on ID " << id; + return ndk::ScopedAStatus::ok(); +} + } // namespace vibrator } // namespace hardware } // namespace android diff --git a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h index 817ec805fa..0eb957d9fa 100644 --- a/vibrator/aidl/default/include/vibrator-impl/Vibrator.h +++ b/vibrator/aidl/default/include/vibrator-impl/Vibrator.h @@ -38,6 +38,9 @@ class Vibrator : public BnVibrator { ndk::ScopedAStatus getCompositionSizeMax(int32_t* maxSize); ndk::ScopedAStatus compose(const std::vector& composite, const std::shared_ptr& callback) override; + ndk::ScopedAStatus getSupportedAlwaysOnEffects(std::vector* _aidl_return) override; + ndk::ScopedAStatus alwaysOnEnable(int32_t id, Effect effect, EffectStrength strength) override; + ndk::ScopedAStatus alwaysOnDisable(int32_t id) override; }; } // namespace vibrator diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp index 6f9ba1a96e..f47b10d34f 100644 --- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp +++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp @@ -370,6 +370,32 @@ TEST_P(VibratorAidl, CompseSizeBoundary) { } } +TEST_P(VibratorAidl, AlwaysOn) { + if (capabilities & IVibrator::CAP_ALWAYS_ON_CONTROL) { + std::vector supported; + ASSERT_TRUE(vibrator->getSupportedAlwaysOnEffects(&supported).isOk()); + + for (Effect effect : kEffects) { + bool isEffectSupported = + std::find(supported.begin(), supported.end(), effect) != supported.end(); + + for (EffectStrength strength : kEffectStrengths) { + Status status = vibrator->alwaysOnEnable(0, effect, strength); + + if (isEffectSupported) { + EXPECT_EQ(Status::EX_NONE, status.exceptionCode()) + << toString(effect) << " " << toString(strength); + } else { + EXPECT_EQ(Status::EX_UNSUPPORTED_OPERATION, status.exceptionCode()) + << toString(effect) << " " << toString(strength); + } + } + } + + EXPECT_EQ(Status::EX_NONE, vibrator->alwaysOnDisable(0).exceptionCode()); + } +} + INSTANTIATE_TEST_SUITE_P(Vibrator, VibratorAidl, testing::ValuesIn(android::getAidlHalInstanceNames(IVibrator::descriptor)), android::PrintInstanceNameToString);