Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab0ee0d2 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Cache results from Vibrator HAL getters in wrapper"

parents 770ac348 d39ff7de
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
*.iml
*.pyc
.idea/
+49 −23
Original line number Diff line number Diff line
@@ -43,6 +43,18 @@ namespace vibrator {

// -------------------------------------------------------------------------------------------------

template <class T>
HalResult<T> loadCached(const std::function<HalResult<T>()>& loadFn, std::optional<T>& cache) {
    if (cache.has_value()) {
        return HalResult<T>::ok(cache.value());
    }
    HalResult<T> ret = loadFn();
    if (ret.isOk()) {
        cache.emplace(ret.value());
    }
    return ret;
}

template <class T>
bool isStaticCastValid(Effect effect) {
    T castEffect = static_cast<T>(effect);
@@ -214,15 +226,23 @@ HalResult<void> AidlHalWrapper::alwaysOnDisable(int32_t id) {
}

HalResult<Capabilities> AidlHalWrapper::getCapabilities() {
    std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
    static auto loadFn = [this]() {
        int32_t capabilities = 0;
        auto result = mHandle->getCapabilities(&capabilities);
        return HalResult<Capabilities>::fromStatus(result, static_cast<Capabilities>(capabilities));
    };
    return loadCached<Capabilities>(loadFn, mCapabilities);
}

HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffects() {
    std::lock_guard<std::mutex> lock(mSupportedEffectsMutex);
    static auto loadFn = [this]() {
        std::vector<Effect> supportedEffects;
        auto result = mHandle->getSupportedEffects(&supportedEffects);
        return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
    };
    return loadCached<std::vector<Effect>>(loadFn, mSupportedEffects);
}

HalResult<milliseconds> AidlHalWrapper::performEffect(
@@ -279,10 +299,9 @@ HalResult<void> HidlHalWrapperV1_0::alwaysOnDisable(int32_t) {
}

HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilities() {
    hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
    Capabilities capabilities =
            result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
    return HalResult<Capabilities>::fromReturn(result, capabilities);
    std::lock_guard<std::mutex> lock(mCapabilitiesMutex);
    return loadCached<Capabilities>(std::bind(&HidlHalWrapperV1_0::getCapabilitiesInternal, this),
                                    mCapabilities);
}

HalResult<std::vector<Effect>> HidlHalWrapperV1_0::getSupportedEffects() {
@@ -308,6 +327,13 @@ HalResult<void> HidlHalWrapperV1_0::performComposedEffect(const std::vector<Comp
    return HalResult<void>::unsupported();
}

HalResult<Capabilities> HidlHalWrapperV1_0::getCapabilitiesInternal() {
    hardware::Return<bool> result = mHandleV1_0->supportsAmplitudeControl();
    Capabilities capabilities =
            result.withDefault(false) ? Capabilities::AMPLITUDE_CONTROL : Capabilities::NONE;
    return HalResult<Capabilities>::fromReturn(result, capabilities);
}

// -------------------------------------------------------------------------------------------------

HalResult<milliseconds> HidlHalWrapperV1_1::performEffect(Effect effect, EffectStrength strength,
@@ -355,19 +381,6 @@ HalResult<void> HidlHalWrapperV1_3::setExternalControl(bool enabled) {
    return HalResult<void>::fromStatus(result.withDefault(V1_0::Status::UNKNOWN_ERROR));
}

HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilities() {
    HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilities();
    if (!parentResult.isOk()) {
        // Loading for versions up to v1.2 already failed, so propagate failure.
        return parentResult;
    }

    Capabilities capabilities = parentResult.value();
    auto result = mHandleV1_3->supportsExternalControl();
    capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
    return HalResult<Capabilities>::fromReturn(result, capabilities);
}

HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(Effect effect, EffectStrength strength,
                                                          const std::function<void()>&) {
    if (isStaticCastValid<V1_0::Effect>(effect)) {
@@ -392,6 +405,19 @@ HalResult<milliseconds> HidlHalWrapperV1_3::performEffect(Effect effect, EffectS
    return HalResult<milliseconds>::unsupported();
}

HalResult<Capabilities> HidlHalWrapperV1_3::getCapabilitiesInternal() {
    HalResult<Capabilities> parentResult = HidlHalWrapperV1_2::getCapabilitiesInternal();
    if (!parentResult.isOk()) {
        // Loading for previous HAL versions already failed, so propagate failure.
        return parentResult;
    }

    Capabilities capabilities = parentResult.value();
    auto result = mHandleV1_3->supportsExternalControl();
    capabilities |= result.withDefault(false) ? Capabilities::EXTERNAL_CONTROL : Capabilities::NONE;
    return HalResult<Capabilities>::fromReturn(result, capabilities);
}

// -------------------------------------------------------------------------------------------------

}; // namespace vibrator
+12 −1
Original line number Diff line number Diff line
@@ -181,6 +181,11 @@ public:

private:
    const sp<hardware::vibrator::IVibrator> mHandle;
    std::mutex mCapabilitiesMutex;
    std::mutex mSupportedEffectsMutex;
    std::optional<Capabilities> mCapabilities GUARDED_BY(mCapabilitiesMutex);
    std::optional<std::vector<hardware::vibrator::Effect>> mSupportedEffects
            GUARDED_BY(mSupportedEffectsMutex);
};

// Wrapper for the HDIL Vibrator HAL v1.0.
@@ -215,6 +220,11 @@ public:

protected:
    const sp<hardware::vibrator::V1_0::IVibrator> mHandleV1_0;
    std::mutex mCapabilitiesMutex;
    std::optional<Capabilities> mCapabilities GUARDED_BY(mCapabilitiesMutex);

    // Loads directly from IVibrator handle, skipping the mCapabilities cache.
    virtual HalResult<Capabilities> getCapabilitiesInternal();
};

// Wrapper for the HDIL Vibrator HAL v1.1.
@@ -255,7 +265,6 @@ public:
            mHandleV1_3(hardware::vibrator::V1_3::IVibrator::castFrom(handleV1_0)) {}

    virtual HalResult<void> setExternalControl(bool enabled) override;
    virtual HalResult<Capabilities> getCapabilities() override;

    virtual HalResult<std::chrono::milliseconds> performEffect(
            hardware::vibrator::Effect effect, hardware::vibrator::EffectStrength strength,
@@ -263,6 +272,8 @@ public:

protected:
    const sp<hardware::vibrator::V1_3::IVibrator> mHandleV1_3;

    virtual HalResult<Capabilities> getCapabilitiesInternal() override;
};

// -------------------------------------------------------------------------------------------------
+49 −10
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>

#include <utils/Log.h>
#include <thread>

#include <vibratorservice/VibratorHalWrapper.h>

@@ -243,38 +244,76 @@ TEST_F(VibratorHalWrapperAidlTest, TestAlwaysOnDisable) {
    ASSERT_TRUE(mWrapper->alwaysOnDisable(3).isFailed());
}

TEST_F(VibratorHalWrapperAidlTest, TestGetCapabilities) {
TEST_F(VibratorHalWrapperAidlTest, TestGetCapabilitiesDoesNotCacheFailedResult) {
    EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
            .Times(Exactly(3))
            .WillOnce(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status())))
            .WillOnce(
                    Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
            .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)));
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
            .WillRepeatedly(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status())));

    ASSERT_TRUE(mWrapper->getCapabilities().isUnsupported());
    ASSERT_TRUE(mWrapper->getCapabilities().isFailed());

    auto result = mWrapper->getCapabilities();
    ASSERT_TRUE(result.isOk());
    ASSERT_EQ(vibrator::Capabilities::ON_CALLBACK, result.value());
    ASSERT_TRUE(mWrapper->getCapabilities().isUnsupported());
    ASSERT_TRUE(mWrapper->getCapabilities().isFailed());
}

TEST_F(VibratorHalWrapperAidlTest, TestGetSupportedEffects) {
TEST_F(VibratorHalWrapperAidlTest, TestGetCapabilitiesCachesResult) {
    EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<0>(IVibrator::CAP_ON_CALLBACK), Return(Status())));

    std::vector<std::thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.push_back(std::thread([&]() {
            auto result = mWrapper->getCapabilities();
            ASSERT_TRUE(result.isOk());
            ASSERT_EQ(vibrator::Capabilities::ON_CALLBACK, result.value());
        }));
    }
    std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
}

TEST_F(VibratorHalWrapperAidlTest, TestGetSupportedEffectsDoesNotCacheFailedResult) {
    std::vector<Effect> supportedEffects;
    supportedEffects.push_back(Effect::CLICK);
    supportedEffects.push_back(Effect::TICK);

    EXPECT_CALL(*mMockHal.get(), getSupportedEffects(_))
            .Times(Exactly(3))
            .WillOnce(DoAll(SetArgPointee<0>(supportedEffects), Return(Status())))
            .WillOnce(
                    Return(Status::fromExceptionCode(Status::Exception::EX_UNSUPPORTED_OPERATION)))
            .WillRepeatedly(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)));
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
            .WillRepeatedly(DoAll(SetArgPointee<0>(supportedEffects), Return(Status())));

    ASSERT_TRUE(mWrapper->getSupportedEffects().isUnsupported());
    ASSERT_TRUE(mWrapper->getSupportedEffects().isFailed());

    auto result = mWrapper->getSupportedEffects();
    ASSERT_TRUE(result.isOk());
    ASSERT_EQ(supportedEffects, result.value());
    ASSERT_TRUE(mWrapper->getSupportedEffects().isUnsupported());
    ASSERT_TRUE(mWrapper->getSupportedEffects().isFailed());
}

TEST_F(VibratorHalWrapperAidlTest, TestGetSupportedEffectsCachesResult) {
    std::vector<Effect> supportedEffects;
    supportedEffects.push_back(Effect::CLICK);
    supportedEffects.push_back(Effect::TICK);

    EXPECT_CALL(*mMockHal.get(), getSupportedEffects(_))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<0>(supportedEffects), Return(Status())));

    std::vector<std::thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.push_back(std::thread([&]() {
            auto result = mWrapper->getSupportedEffects();
            ASSERT_TRUE(result.isOk());
            ASSERT_EQ(supportedEffects, result.value());
        }));
    }
    std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
}

TEST_F(VibratorHalWrapperAidlTest, TestPerformEffect) {
+31 −11
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <gtest/gtest.h>

#include <utils/Log.h>
#include <thread>

#include <vibratorservice/VibratorHalWrapper.h>

@@ -186,29 +187,48 @@ TEST_F(VibratorHalWrapperHidlV1_0Test, TestAlwaysOnDisableUnsupported) {
    ASSERT_TRUE(mWrapper->alwaysOnDisable(1).isUnsupported());
}

TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetCapabilities) {
TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetCapabilitiesDoesNotCacheFailedResult) {
    EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl())
            .Times(Exactly(3))
            .WillOnce([]() { return hardware::Return<bool>(true); })
            .WillOnce([]() { return hardware::Return<bool>(false); })
            .WillRepeatedly([]() {
            .Times(Exactly(2))
            .WillOnce([]() {
                return hardware::Return<bool>(hardware::Status::fromExceptionCode(-1));
            });
            })
            .WillRepeatedly([]() { return hardware::Return<bool>(true); });

    ASSERT_TRUE(mWrapper->getCapabilities().isFailed());

    // Amplitude control enabled.
    auto result = mWrapper->getCapabilities();
    ASSERT_TRUE(result.isOk());
    ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, result.value());
}

TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetCapabilitiesWithoutAmplitudeControl) {
    EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()).Times(Exactly(1)).WillRepeatedly([]() {
        return hardware::Return<bool>(false);
    });

    // Amplitude control disabled.
    result = mWrapper->getCapabilities();
    auto result = mWrapper->getCapabilities();
    ASSERT_TRUE(result.isOk());
    ASSERT_EQ(vibrator::Capabilities::NONE, result.value());
}

    ASSERT_TRUE(mWrapper->getCapabilities().isFailed());
TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetCapabilitiesCachesResult) {
    EXPECT_CALL(*mMockHal.get(), supportsAmplitudeControl()).Times(Exactly(1)).WillRepeatedly([]() {
        return hardware::Return<bool>(true);
    });

    std::vector<std::thread> threads;
    for (int i = 0; i < 10; i++) {
        threads.push_back(std::thread([&]() {
            auto result = mWrapper->getCapabilities();
            ASSERT_TRUE(result.isOk());
            ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, result.value());
        }));
    }
    std::for_each(threads.begin(), threads.end(), [](std::thread& t) { t.join(); });
}

TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetSupportedEffects) {
TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetSupportedEffectsUnsupported) {
    ASSERT_TRUE(mWrapper->getSupportedEffects().isUnsupported());
}

Loading