From ba9a6ce97aead81c2bddd7bd4b79e8205fbd39a1 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 26 Feb 2021 02:55:29 +0000 Subject: Add support for querying resonant frequency and Q factor. Bug: 181276733 Test: atest libvibratorservice_test Change-Id: I7bebc96ddc09fe13716ce8ea51cbf99cf4054955 --- services/vibratorservice/VibratorHalController.cpp | 12 ++++ services/vibratorservice/VibratorHalWrapper.cpp | 35 ++++++++++ .../vibratorservice/VibratorHalController.h | 3 + .../include/vibratorservice/VibratorHalWrapper.h | 17 +++++ .../test/VibratorHalControllerTest.cpp | 54 +++++++++++---- .../test/VibratorHalWrapperAidlTest.cpp | 76 ++++++++++++++++++++++ 6 files changed, 184 insertions(+), 13 deletions(-) diff --git a/services/vibratorservice/VibratorHalController.cpp b/services/vibratorservice/VibratorHalController.cpp index 537e49bc0a..2de2e0e133 100644 --- a/services/vibratorservice/VibratorHalController.cpp +++ b/services/vibratorservice/VibratorHalController.cpp @@ -209,6 +209,18 @@ HalResult> HalController::getSupportedPrimitives return apply(getSupportedPrimitivesFn, "getSupportedPrimitives"); } +HalResult HalController::getResonantFrequency() { + hal_fn getResonantFrequencyFn = [](std::shared_ptr hal) { + return hal->getResonantFrequency(); + }; + return apply(getResonantFrequencyFn, "getResonantFrequency"); +} + +HalResult HalController::getQFactor() { + hal_fn getQFactorFn = [](std::shared_ptr hal) { return hal->getQFactor(); }; + return apply(getQFactorFn, "getQFactor"); +} + HalResult HalController::performEffect( Effect effect, EffectStrength strength, const std::function& completionCallback) { hal_fn performEffectFn = [&](std::shared_ptr hal) { diff --git a/services/vibratorservice/VibratorHalWrapper.cpp b/services/vibratorservice/VibratorHalWrapper.cpp index 6faab38c51..3d20fa1273 100644 --- a/services/vibratorservice/VibratorHalWrapper.cpp +++ b/services/vibratorservice/VibratorHalWrapper.cpp @@ -205,6 +205,17 @@ HalResult> AidlHalWrapper::getSupportedPrimitive mSupportedPrimitives); } +HalResult AidlHalWrapper::getResonantFrequency() { + std::lock_guard lock(mResonantFrequencyMutex); + return loadCached(std::bind(&AidlHalWrapper::getResonantFrequencyInternal, this), + mResonantFrequency); +} + +HalResult AidlHalWrapper::getQFactor() { + std::lock_guard lock(mQFactorMutex); + return loadCached(std::bind(&AidlHalWrapper::getQFactorInternal, this), mQFactor); +} + HalResult AidlHalWrapper::performEffect( Effect effect, EffectStrength strength, const std::function& completionCallback) { HalResult capabilities = getCapabilities(); @@ -283,6 +294,18 @@ HalResult> AidlHalWrapper::getSupportedPrimitive return HalResult>::fromStatus(result, supportedPrimitives); } +HalResult AidlHalWrapper::getResonantFrequencyInternal() { + float f0 = 0; + auto result = getHal()->getResonantFrequency(&f0); + return HalResult::fromStatus(result, f0); +} + +HalResult AidlHalWrapper::getQFactorInternal() { + float qFactor = 0; + auto result = getHal()->getQFactor(&qFactor); + return HalResult::fromStatus(result, qFactor); +} + sp AidlHalWrapper::getHal() { std::lock_guard lock(mHandleMutex); return mHandle; @@ -365,6 +388,18 @@ HalResult> HidlHalWrapper::getSupportedPrimit return HalResult>::unsupported(); } +template +HalResult HidlHalWrapper::getResonantFrequency() { + ALOGV("Skipped getResonantFrequency because Vibrator HAL AIDL is not available"); + return HalResult::unsupported(); +} + +template +HalResult HidlHalWrapper::getQFactor() { + ALOGV("Skipped getQFactor because Vibrator HAL AIDL is not available"); + return HalResult::unsupported(); +} + template HalResult HidlHalWrapper::performComposedEffect( const std::vector&, const std::function&) { diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalController.h b/services/vibratorservice/include/vibratorservice/VibratorHalController.h index 16d571d2af..14ec7b29d8 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalController.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalController.h @@ -73,6 +73,9 @@ public: HalResult> getSupportedPrimitives() final override; + HalResult getResonantFrequency() final override; + HalResult getQFactor() final override; + HalResult performEffect( hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, const std::function& completionCallback) final override; diff --git a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h index e22ad340a3..039a2d99c3 100644 --- a/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h +++ b/services/vibratorservice/include/vibratorservice/VibratorHalWrapper.h @@ -185,6 +185,9 @@ public: virtual HalResult> getSupportedPrimitives() = 0; + virtual HalResult getResonantFrequency() = 0; + virtual HalResult getQFactor() = 0; + virtual HalResult performEffect( hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, const std::function& completionCallback) = 0; @@ -232,6 +235,9 @@ public: HalResult> getSupportedPrimitives() override final; + HalResult getResonantFrequency() override final; + HalResult getQFactor() override final; + HalResult performEffect( hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength, const std::function& completionCallback) override final; @@ -246,6 +252,8 @@ private: std::mutex mCapabilitiesMutex; std::mutex mSupportedEffectsMutex; std::mutex mSupportedPrimitivesMutex; + std::mutex mResonantFrequencyMutex; + std::mutex mQFactorMutex; sp mHandle GUARDED_BY(mHandleMutex); std::optional mCapabilities GUARDED_BY(mCapabilitiesMutex); std::optional> mSupportedEffects @@ -254,6 +262,8 @@ private: GUARDED_BY(mSupportedPrimitivesMutex); std::vector> mPrimitiveDurations GUARDED_BY(mSupportedPrimitivesMutex); + std::optional mResonantFrequency GUARDED_BY(mResonantFrequencyMutex); + std::optional mQFactor GUARDED_BY(mQFactorMutex); // Loads and caches from IVibrator. HalResult getPrimitiveDuration( @@ -263,6 +273,10 @@ private: HalResult getCapabilitiesInternal(); HalResult> getSupportedEffectsInternal(); HalResult> getSupportedPrimitivesInternal(); + + HalResult getResonantFrequencyInternal(); + HalResult getQFactorInternal(); + sp getHal(); }; @@ -293,6 +307,9 @@ public: HalResult> getSupportedPrimitives() override final; + HalResult getResonantFrequency() override final; + HalResult getQFactor() override final; + HalResult performComposedEffect( const std::vector& primitiveEffects, const std::function& completionCallback) override final; diff --git a/services/vibratorservice/test/VibratorHalControllerTest.cpp b/services/vibratorservice/test/VibratorHalControllerTest.cpp index c4b39edec4..0c3924772c 100644 --- a/services/vibratorservice/test/VibratorHalControllerTest.cpp +++ b/services/vibratorservice/test/VibratorHalControllerTest.cpp @@ -67,6 +67,10 @@ public: MOCK_METHOD(vibrator::HalResult>, getSupportedEffects, (), (override)); MOCK_METHOD(vibrator::HalResult>, getSupportedPrimitives, (), (override)); + + MOCK_METHOD(vibrator::HalResult, getResonantFrequency, (), (override)); + MOCK_METHOD(vibrator::HalResult, getQFactor, (), (override)); + MOCK_METHOD(vibrator::HalResult, performEffect, (Effect effect, EffectStrength strength, const std::function& completionCallback), @@ -106,6 +110,8 @@ protected: vibrator::HalResult capabilitiesResult, vibrator::HalResult> effectsResult, vibrator::HalResult> primitivesResult, + vibrator::HalResult resonantFrequencyResult, + vibrator::HalResult qFactorResult, vibrator::HalResult durationResult) { EXPECT_CALL(*mMockHal.get(), ping()) .Times(Exactly(cardinality)) @@ -138,6 +144,12 @@ protected: EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives()) .Times(Exactly(cardinality)) .WillRepeatedly(Return(primitivesResult)); + EXPECT_CALL(*mMockHal.get(), getResonantFrequency()) + .Times(Exactly(cardinality)) + .WillRepeatedly(Return(resonantFrequencyResult)); + EXPECT_CALL(*mMockHal.get(), getQFactor()) + .Times(Exactly(cardinality)) + .WillRepeatedly(Return(qFactorResult)); EXPECT_CALL(*mMockHal.get(), performEffect(Eq(Effect::CLICK), Eq(EffectStrength::LIGHT), _)) .Times(Exactly(cardinality)) .WillRepeatedly(Return(durationResult)); @@ -147,7 +159,7 @@ protected: if (cardinality > 1) { // One reconnection call after each failure. - EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(12 * cardinality)); + EXPECT_CALL(*mMockHal.get(), tryReconnect()).Times(Exactly(14 * cardinality)); } } }; @@ -164,23 +176,21 @@ TEST_F(VibratorHalControllerTest, TestInit) { } TEST_F(VibratorHalControllerTest, TestApiCallsAreForwardedToHal) { - std::vector effects; - effects.push_back(Effect::CLICK); - effects.push_back(Effect::TICK); - std::vector primitives; - primitives.push_back(CompositePrimitive::CLICK); - primitives.push_back(CompositePrimitive::THUD); - std::vector compositeEffects; - compositeEffects.push_back( - vibrator::TestFactory::createCompositeEffect(CompositePrimitive::SPIN, 100ms, 0.5f)); - compositeEffects.push_back( - vibrator::TestFactory::createCompositeEffect(CompositePrimitive::THUD, 1000ms, 1.0f)); + std::vector effects = {Effect::CLICK, Effect::TICK}; + std::vector primitives = {CompositePrimitive::CLICK, + CompositePrimitive::THUD}; + constexpr float F0 = 123.f; + constexpr float Q_FACTOR = 12.f; + const std::vector compositeEffects = + {vibrator::TestFactory::createCompositeEffect(CompositePrimitive::SPIN, 100ms, 0.5f), + vibrator::TestFactory::createCompositeEffect(CompositePrimitive::THUD, 1000ms, 1.0f)}; setHalExpectations(/* cardinality= */ 1, compositeEffects, vibrator::HalResult::ok(), vibrator::HalResult::ok( vibrator::Capabilities::ON_CALLBACK), vibrator::HalResult>::ok(effects), vibrator::HalResult>::ok(primitives), + vibrator::HalResult::ok(F0), vibrator::HalResult::ok(Q_FACTOR), vibrator::HalResult::ok(100ms)); ASSERT_TRUE(mController->ping().isOk()); @@ -203,6 +213,14 @@ TEST_F(VibratorHalControllerTest, TestApiCallsAreForwardedToHal) { ASSERT_TRUE(getSupportedPrimitivesResult.isOk()); ASSERT_EQ(primitives, getSupportedPrimitivesResult.value()); + auto getResonantFrequencyResult = mController->getResonantFrequency(); + ASSERT_TRUE(getResonantFrequencyResult.isOk()); + ASSERT_EQ(F0, getResonantFrequencyResult.value()); + + auto getQFactorResult = mController->getQFactor(); + ASSERT_TRUE(getQFactorResult.isOk()); + ASSERT_EQ(Q_FACTOR, getQFactorResult.value()); + auto performEffectResult = mController->performEffect(Effect::CLICK, EffectStrength::LIGHT, []() {}); ASSERT_TRUE(performEffectResult.isOk()); @@ -222,6 +240,8 @@ TEST_F(VibratorHalControllerTest, TestUnsupportedApiResultDoNotResetHalConnectio vibrator::HalResult::unsupported(), vibrator::HalResult>::unsupported(), vibrator::HalResult>::unsupported(), + vibrator::HalResult::unsupported(), + vibrator::HalResult::unsupported(), vibrator::HalResult::unsupported()); ASSERT_EQ(0, mConnectCounter); @@ -237,6 +257,8 @@ TEST_F(VibratorHalControllerTest, TestUnsupportedApiResultDoNotResetHalConnectio ASSERT_TRUE(mController->getCapabilities().isUnsupported()); ASSERT_TRUE(mController->getSupportedEffects().isUnsupported()); ASSERT_TRUE(mController->getSupportedPrimitives().isUnsupported()); + ASSERT_TRUE(mController->getResonantFrequency().isUnsupported()); + ASSERT_TRUE(mController->getQFactor().isUnsupported()); ASSERT_TRUE(mController->performEffect(Effect::CLICK, EffectStrength::LIGHT, []() {}) .isUnsupported()); ASSERT_TRUE(mController->performComposedEffect(std::vector(), []() {}) @@ -251,6 +273,8 @@ TEST_F(VibratorHalControllerTest, TestFailedApiResultResetsHalConnection) { vibrator::HalResult::failed("message"), vibrator::HalResult>::failed("message"), vibrator::HalResult>::failed("message"), + vibrator::HalResult::failed("message"), + vibrator::HalResult::failed("message"), vibrator::HalResult::failed("message")); ASSERT_EQ(0, mConnectCounter); @@ -265,6 +289,8 @@ TEST_F(VibratorHalControllerTest, TestFailedApiResultResetsHalConnection) { ASSERT_TRUE(mController->getCapabilities().isFailed()); ASSERT_TRUE(mController->getSupportedEffects().isFailed()); ASSERT_TRUE(mController->getSupportedPrimitives().isFailed()); + ASSERT_TRUE(mController->getResonantFrequency().isFailed()); + ASSERT_TRUE(mController->getQFactor().isFailed()); ASSERT_TRUE( mController->performEffect(Effect::CLICK, EffectStrength::LIGHT, []() {}).isFailed()); ASSERT_TRUE( @@ -327,13 +353,15 @@ TEST_F(VibratorHalControllerTest, TestNoVibratorReturnsUnsupportedAndAttemptsToR ASSERT_TRUE(mController->getCapabilities().isUnsupported()); ASSERT_TRUE(mController->getSupportedEffects().isUnsupported()); ASSERT_TRUE(mController->getSupportedPrimitives().isUnsupported()); + ASSERT_TRUE(mController->getResonantFrequency().isUnsupported()); + ASSERT_TRUE(mController->getQFactor().isUnsupported()); ASSERT_TRUE(mController->performEffect(Effect::CLICK, EffectStrength::LIGHT, []() {}) .isUnsupported()); ASSERT_TRUE(mController->performComposedEffect(std::vector(), []() {}) .isUnsupported()); // One connection attempt per api call. - ASSERT_EQ(13, mConnectCounter); + ASSERT_EQ(15, mConnectCounter); } TEST_F(VibratorHalControllerTest, TestScheduledCallbackSurvivesReconnection) { diff --git a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp index 8b5caa5f82..5d77595b6b 100644 --- a/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp +++ b/services/vibratorservice/test/VibratorHalWrapperAidlTest.cpp @@ -413,6 +413,82 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetSupportedPrimitivesCachesResult) { ASSERT_EQ(supportedPrimitives, result.value()); } +TEST_F(VibratorHalWrapperAidlTest, TestGetResonantFrequencyDoesNotCacheFailedResult) { + constexpr float F0 = 123.f; + EXPECT_CALL(*mMockHal.get(), getResonantFrequency(_)) + .Times(Exactly(3)) + .WillOnce( + Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) + .WillRepeatedly(DoAll(SetArgPointee<0>(F0), Return(Status()))); + + ASSERT_TRUE(mWrapper->getResonantFrequency().isUnsupported()); + ASSERT_TRUE(mWrapper->getResonantFrequency().isFailed()); + + auto result = mWrapper->getResonantFrequency(); + ASSERT_TRUE(result.isOk()); + ASSERT_EQ(F0, result.value()); +} + +TEST_F(VibratorHalWrapperAidlTest, TestGetResonantFrequencyCachesResult) { + constexpr float F0 = 123.f; + EXPECT_CALL(*mMockHal.get(), getResonantFrequency(_)) + .Times(Exactly(1)) + .WillRepeatedly(DoAll(SetArgPointee<0>(F0), Return(Status()))); + + std::vector threads; + for (int i = 0; i < 10; i++) { + threads.push_back(std::thread([&]() { + auto result = mWrapper->getResonantFrequency(); + ASSERT_TRUE(result.isOk()); + ASSERT_EQ(F0, result.value()); + })); + } + std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); + + auto result = mWrapper->getResonantFrequency(); + ASSERT_TRUE(result.isOk()); + ASSERT_EQ(F0, result.value()); +} + +TEST_F(VibratorHalWrapperAidlTest, TestGetQFactorDoesNotCacheFailedResult) { + constexpr float Q_FACTOR = 123.f; + EXPECT_CALL(*mMockHal.get(), getQFactor(_)) + .Times(Exactly(3)) + .WillOnce( + Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION))) + .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY))) + .WillRepeatedly(DoAll(SetArgPointee<0>(Q_FACTOR), Return(Status()))); + + ASSERT_TRUE(mWrapper->getQFactor().isUnsupported()); + ASSERT_TRUE(mWrapper->getQFactor().isFailed()); + + auto result = mWrapper->getQFactor(); + ASSERT_TRUE(result.isOk()); + ASSERT_EQ(Q_FACTOR, result.value()); +} + +TEST_F(VibratorHalWrapperAidlTest, TestGetQFactorCachesResult) { + constexpr float Q_FACTOR = 123.f; + EXPECT_CALL(*mMockHal.get(), getQFactor(_)) + .Times(Exactly(1)) + .WillRepeatedly(DoAll(SetArgPointee<0>(Q_FACTOR), Return(Status()))); + + std::vector threads; + for (int i = 0; i < 10; i++) { + threads.push_back(std::thread([&]() { + auto result = mWrapper->getQFactor(); + ASSERT_TRUE(result.isOk()); + ASSERT_EQ(Q_FACTOR, result.value()); + })); + } + std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); }); + + auto result = mWrapper->getQFactor(); + ASSERT_TRUE(result.isOk()); + ASSERT_EQ(Q_FACTOR, result.value()); +} + TEST_F(VibratorHalWrapperAidlTest, TestPerformEffectWithCallbackSupport) { { InSequence seq; -- cgit v1.2.3-59-g8ed1b