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

Commit 92f2af5c authored by Lais Andrade's avatar Lais Andrade
Browse files

Implement PWLE support

Implement support to new API method composePwle and related frequency
control getters.

Bug: 167947076
Test: libvibratorservice_test
Change-Id: I6f47ea771a19b1ae46370c5d82671f6420e39f8b
parent 965284b7
Loading
Loading
Loading
Loading
+80 −24
Original line number Diff line number Diff line
@@ -26,10 +26,12 @@
#include <vibratorservice/VibratorCallbackScheduler.h>
#include <vibratorservice/VibratorHalWrapper.h>

using android::hardware::vibrator::Braking;
using android::hardware::vibrator::CompositeEffect;
using android::hardware::vibrator::CompositePrimitive;
using android::hardware::vibrator::Effect;
using android::hardware::vibrator::EffectStrength;
using android::hardware::vibrator::PrimitivePwle;

using std::chrono::milliseconds;

@@ -45,20 +47,6 @@ namespace vibrator {

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

template <class T>
HalResult<T> loadCached(const std::function<HalResult<T>()>& loadFn, std::optional<T>& cache) {
    if (cache.has_value()) {
        // Return copy of cached value.
        return HalResult<T>::ok(*cache);
    }
    HalResult<T> ret = loadFn();
    if (ret.isOk()) {
        // Cache copy of returned value.
        cache.emplace(ret.value());
    }
    return ret;
}

template <class T>
bool isStaticCastValid(Effect effect) {
    T castEffect = static_cast<T>(effect);
@@ -141,15 +129,39 @@ Info HalWrapper::getInfo() {
    if (mInfoCache.mSupportedEffects.isFailed()) {
        mInfoCache.mSupportedEffects = getSupportedEffectsInternal();
    }
    if (mInfoCache.mSupportedBraking.isFailed()) {
        mInfoCache.mSupportedBraking = getSupportedBrakingInternal();
    }
    if (mInfoCache.mMinFrequency.isFailed()) {
        mInfoCache.mMinFrequency = getMinFrequencyInternal();
    }
    if (mInfoCache.mResonantFrequency.isFailed()) {
        mInfoCache.mResonantFrequency = getResonantFrequencyInternal();
    }
    if (mInfoCache.mFrequencyResolution.isFailed()) {
        mInfoCache.mFrequencyResolution = getFrequencyResolutionInternal();
    }
    if (mInfoCache.mQFactor.isFailed()) {
        mInfoCache.mQFactor = getQFactorInternal();
    }
    if (mInfoCache.mMaxAmplitudes.isFailed()) {
        mInfoCache.mMaxAmplitudes = getMaxAmplitudesInternal();
    }
    return mInfoCache.get();
}

HalResult<milliseconds> HalWrapper::performComposedEffect(const std::vector<CompositeEffect>&,
                                                          const std::function<void()>&) {
    ALOGV("Skipped performComposedEffect because it's not available in Vibrator HAL");
    return HalResult<milliseconds>::unsupported();
}

HalResult<void> HalWrapper::performPwleEffect(const std::vector<PrimitivePwle>&,
                                              const std::function<void()>&) {
    ALOGV("Skipped performPwleEffect because it's not available in Vibrator HAL");
    return HalResult<void>::unsupported();
}

HalResult<Capabilities> HalWrapper::getCapabilities() {
    std::lock_guard<std::mutex> lock(mInfoMutex);
    if (mInfoCache.mCapabilities.isFailed()) {
@@ -178,6 +190,11 @@ HalResult<std::vector<Effect>> HalWrapper::getSupportedEffectsInternal() {
    return HalResult<std::vector<Effect>>::unsupported();
}

HalResult<std::vector<Braking>> HalWrapper::getSupportedBrakingInternal() {
    ALOGV("Skipped getSupportedBraking because it's not available in Vibrator HAL");
    return HalResult<std::vector<Braking>>::unsupported();
}

HalResult<std::vector<CompositePrimitive>> HalWrapper::getSupportedPrimitivesInternal() {
    ALOGV("Skipped getSupportedPrimitives because it's not available in Vibrator HAL");
    return HalResult<std::vector<CompositePrimitive>>::unsupported();
@@ -189,16 +206,31 @@ HalResult<std::vector<milliseconds>> HalWrapper::getPrimitiveDurationsInternal(
    return HalResult<std::vector<milliseconds>>::unsupported();
}

HalResult<float> HalWrapper::getMinFrequencyInternal() {
    ALOGV("Skipped getMinFrequency because it's not available in Vibrator HAL");
    return HalResult<float>::unsupported();
}

HalResult<float> HalWrapper::getResonantFrequencyInternal() {
    ALOGV("Skipped getResonantFrequency because it's not available in Vibrator HAL");
    return HalResult<float>::unsupported();
}

HalResult<float> HalWrapper::getFrequencyResolutionInternal() {
    ALOGV("Skipped getFrequencyResolution because it's not available in Vibrator HAL");
    return HalResult<float>::unsupported();
}

HalResult<float> HalWrapper::getQFactorInternal() {
    ALOGV("Skipped getQFactor because it's not available in Vibrator HAL");
    return HalResult<float>::unsupported();
}

HalResult<std::vector<float>> HalWrapper::getMaxAmplitudesInternal() {
    ALOGV("Skipped getMaxAmplitudes because it's not available in Vibrator HAL");
    return HalResult<std::vector<float>>::unsupported();
}

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

HalResult<void> AidlHalWrapper::ping() {
@@ -272,14 +304,14 @@ HalResult<milliseconds> AidlHalWrapper::performEffect(
}

HalResult<milliseconds> AidlHalWrapper::performComposedEffect(
        const std::vector<CompositeEffect>& primitiveEffects,
        const std::vector<CompositeEffect>& primitives,
        const std::function<void()>& completionCallback) {
    // This method should always support callbacks, so no need to double check.
    auto cb = new HalCallbackWrapper(completionCallback);

    auto durations = getPrimitiveDurations().valueOr({});
    milliseconds duration(0);
    for (const auto& effect : primitiveEffects) {
    for (const auto& effect : primitives) {
        auto primitiveIdx = static_cast<size_t>(effect.primitive);
        if (primitiveIdx < durations.size()) {
            duration += durations[primitiveIdx];
@@ -290,7 +322,14 @@ HalResult<milliseconds> AidlHalWrapper::performComposedEffect(
        duration += milliseconds(effect.delayMs);
    }

    return HalResult<milliseconds>::fromStatus(getHal()->compose(primitiveEffects, cb), duration);
    return HalResult<milliseconds>::fromStatus(getHal()->compose(primitives, cb), duration);
}

HalResult<void> AidlHalWrapper::performPwleEffect(const std::vector<PrimitivePwle>& primitives,
                                                  const std::function<void()>& completionCallback) {
    // This method should always support callbacks, so no need to double check.
    auto cb = new HalCallbackWrapper(completionCallback);
    return HalResult<void>::fromStatus(getHal()->composePwle(primitives, cb));
}

HalResult<Capabilities> AidlHalWrapper::getCapabilitiesInternal() {
@@ -305,6 +344,12 @@ HalResult<std::vector<Effect>> AidlHalWrapper::getSupportedEffectsInternal() {
    return HalResult<std::vector<Effect>>::fromStatus(result, supportedEffects);
}

HalResult<std::vector<Braking>> AidlHalWrapper::getSupportedBrakingInternal() {
    std::vector<Braking> supportedBraking;
    auto result = getHal()->getSupportedBraking(&supportedBraking);
    return HalResult<std::vector<Braking>>::fromStatus(result, supportedBraking);
}

HalResult<std::vector<CompositePrimitive>> AidlHalWrapper::getSupportedPrimitivesInternal() {
    std::vector<CompositePrimitive> supportedPrimitives;
    auto result = getHal()->getSupportedPrimitives(&supportedPrimitives);
@@ -335,18 +380,36 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern
    return HalResult<std::vector<milliseconds>>::ok(durations);
}

HalResult<float> AidlHalWrapper::getMinFrequencyInternal() {
    float minFrequency = 0;
    auto result = getHal()->getFrequencyMinimum(&minFrequency);
    return HalResult<float>::fromStatus(result, minFrequency);
}

HalResult<float> AidlHalWrapper::getResonantFrequencyInternal() {
    float f0 = 0;
    auto result = getHal()->getResonantFrequency(&f0);
    return HalResult<float>::fromStatus(result, f0);
}

HalResult<float> AidlHalWrapper::getFrequencyResolutionInternal() {
    float frequencyResolution = 0;
    auto result = getHal()->getFrequencyResolution(&frequencyResolution);
    return HalResult<float>::fromStatus(result, frequencyResolution);
}

HalResult<float> AidlHalWrapper::getQFactorInternal() {
    float qFactor = 0;
    auto result = getHal()->getQFactor(&qFactor);
    return HalResult<float>::fromStatus(result, qFactor);
}

HalResult<std::vector<float>> AidlHalWrapper::getMaxAmplitudesInternal() {
    std::vector<float> amplitudes;
    auto result = getHal()->getBandwidthAmplitudeMap(&amplitudes);
    return HalResult<std::vector<float>>::fromStatus(result, amplitudes);
}

sp<Aidl::IVibrator> AidlHalWrapper::getHal() {
    std::lock_guard<std::mutex> lock(mHandleMutex);
    return mHandle;
@@ -411,13 +474,6 @@ HalResult<void> HidlHalWrapper<I>::alwaysOnDisable(int32_t) {
    return HalResult<void>::unsupported();
}

template <typename I>
HalResult<std::chrono::milliseconds> HidlHalWrapper<I>::performComposedEffect(
        const std::vector<CompositeEffect>&, const std::function<void()>&) {
    ALOGV("Skipped composed effect because Vibrator HAL AIDL is not available");
    return HalResult<std::chrono::milliseconds>::unsupported();
}

template <typename I>
HalResult<Capabilities> HidlHalWrapper<I>::getCapabilitiesInternal() {
    hardware::Return<bool> result = getHal()->supportsAmplitudeControl();
+40 −11
Original line number Diff line number Diff line
@@ -148,7 +148,8 @@ enum class Capabilities : int32_t {
    EXTERNAL_CONTROL = hardware::vibrator::IVibrator::CAP_EXTERNAL_CONTROL,
    EXTERNAL_AMPLITUDE_CONTROL = hardware::vibrator::IVibrator::CAP_EXTERNAL_AMPLITUDE_CONTROL,
    COMPOSE_EFFECTS = hardware::vibrator::IVibrator::CAP_COMPOSE_EFFECTS,
    ALWAYS_ON_CONTROL = hardware::vibrator::IVibrator::CAP_ALWAYS_ON_CONTROL
    COMPOSE_PWLE_EFFECTS = hardware::vibrator::IVibrator::CAP_COMPOSE_PWLE_EFFECTS,
    ALWAYS_ON_CONTROL = hardware::vibrator::IVibrator::CAP_ALWAYS_ON_CONTROL,
};

inline Capabilities operator|(Capabilities lhs, Capabilities rhs) {
@@ -175,26 +176,36 @@ class Info {
public:
    const HalResult<Capabilities> capabilities;
    const HalResult<std::vector<hardware::vibrator::Effect>> supportedEffects;
    const HalResult<std::vector<hardware::vibrator::Braking>> supportedBraking;
    const HalResult<std::vector<hardware::vibrator::CompositePrimitive>> supportedPrimitives;
    const HalResult<std::vector<std::chrono::milliseconds>> primitiveDurations;
    const HalResult<float> minFrequency;
    const HalResult<float> resonantFrequency;
    const HalResult<float> frequencyResolution;
    const HalResult<float> qFactor;
    const HalResult<std::vector<float>> maxAmplitudes;

    bool checkAndLogFailure(const char*) const {
        return capabilities.checkAndLogFailure("getCapabilities") ||
                supportedEffects.checkAndLogFailure("getSupportedEffects") ||
                supportedBraking.checkAndLogFailure("getSupportedBraking") ||
                supportedPrimitives.checkAndLogFailure("getSupportedPrimitives") ||
                primitiveDurations.checkAndLogFailure("getPrimitiveDuration") ||
                minFrequency.checkAndLogFailure("getMinFrequency") ||
                resonantFrequency.checkAndLogFailure("getResonantFrequency") ||
                qFactor.checkAndLogFailure("getQFactor");
                frequencyResolution.checkAndLogFailure("getFrequencyResolution") ||
                qFactor.checkAndLogFailure("getQFactor") ||
                maxAmplitudes.checkAndLogFailure("getMaxAmplitudes");
    }
};

class InfoCache {
public:
    Info get() {
        return {mCapabilities,       mSupportedEffects,  mSupportedPrimitives,
                mPrimitiveDurations, mResonantFrequency, mQFactor};
        return {mCapabilities,        mSupportedEffects,    mSupportedBraking,
                mSupportedPrimitives, mPrimitiveDurations,  mMinFrequency,
                mResonantFrequency,   mFrequencyResolution, mQFactor,
                mMaxAmplitudes};
    }

private:
@@ -202,12 +213,17 @@ private:
    HalResult<Capabilities> mCapabilities = HalResult<Capabilities>::failed(MSG);
    HalResult<std::vector<hardware::vibrator::Effect>> mSupportedEffects =
            HalResult<std::vector<hardware::vibrator::Effect>>::failed(MSG);
    HalResult<std::vector<hardware::vibrator::Braking>> mSupportedBraking =
            HalResult<std::vector<hardware::vibrator::Braking>>::failed(MSG);
    HalResult<std::vector<hardware::vibrator::CompositePrimitive>> mSupportedPrimitives =
            HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG);
    HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations =
            HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG);
    HalResult<float> mMinFrequency = HalResult<float>::failed(MSG);
    HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG);
    HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG);
    HalResult<float> mQFactor = HalResult<float>::failed(MSG);
    HalResult<std::vector<float>> mMaxAmplitudes = HalResult<std::vector<float>>::failed(MSG);

    friend class HalWrapper;
};
@@ -243,8 +259,12 @@ public:
            const std::function<void()>& completionCallback) = 0;

    virtual HalResult<std::chrono::milliseconds> performComposedEffect(
            const std::vector<hardware::vibrator::CompositeEffect>& primitiveEffects,
            const std::function<void()>& completionCallback) = 0;
            const std::vector<hardware::vibrator::CompositeEffect>& primitives,
            const std::function<void()>& completionCallback);

    virtual HalResult<void> performPwleEffect(
            const std::vector<hardware::vibrator::PrimitivePwle>& primitives,
            const std::function<void()>& completionCallback);

protected:
    // Shared pointer to allow CallbackScheduler to outlive this wrapper.
@@ -257,12 +277,16 @@ protected:
    // Request vibrator info to HAL skipping cache.
    virtual HalResult<Capabilities> getCapabilitiesInternal() = 0;
    virtual HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffectsInternal();
    virtual HalResult<std::vector<hardware::vibrator::Braking>> getSupportedBrakingInternal();
    virtual HalResult<std::vector<hardware::vibrator::CompositePrimitive>>
    getSupportedPrimitivesInternal();
    virtual HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
            const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives);
    virtual HalResult<float> getMinFrequencyInternal();
    virtual HalResult<float> getResonantFrequencyInternal();
    virtual HalResult<float> getFrequencyResolutionInternal();
    virtual HalResult<float> getQFactorInternal();
    virtual HalResult<std::vector<float>> getMaxAmplitudesInternal();

private:
    std::mutex mInfoMutex;
@@ -303,19 +327,28 @@ public:
            const std::function<void()>& completionCallback) override final;

    HalResult<std::chrono::milliseconds> performComposedEffect(
            const std::vector<hardware::vibrator::CompositeEffect>& primitiveEffects,
            const std::vector<hardware::vibrator::CompositeEffect>& primitives,
            const std::function<void()>& completionCallback) override final;

    HalResult<void> performPwleEffect(
            const std::vector<hardware::vibrator::PrimitivePwle>& primitives,
            const std::function<void()>& completionCallback) override final;

protected:
    HalResult<Capabilities> getCapabilitiesInternal() override final;
    HalResult<std::vector<hardware::vibrator::Effect>> getSupportedEffectsInternal() override final;
    HalResult<std::vector<hardware::vibrator::Braking>> getSupportedBrakingInternal()
            override final;
    HalResult<std::vector<hardware::vibrator::CompositePrimitive>> getSupportedPrimitivesInternal()
            override final;
    HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
            const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives)
            override final;
    HalResult<float> getMinFrequencyInternal() override final;
    HalResult<float> getResonantFrequencyInternal() override final;
    HalResult<float> getFrequencyResolutionInternal() override final;
    HalResult<float> getQFactorInternal() override final;
    HalResult<std::vector<float>> getMaxAmplitudesInternal() override final;

private:
    const std::function<HalResult<sp<hardware::vibrator::IVibrator>>()> mReconnectFn;
@@ -347,10 +380,6 @@ public:
                                   hardware::vibrator::EffectStrength strength) override final;
    HalResult<void> alwaysOnDisable(int32_t id) override final;

    HalResult<std::chrono::milliseconds> performComposedEffect(
            const std::vector<hardware::vibrator::CompositeEffect>& primitiveEffects,
            const std::function<void()>& completionCallback) override final;

protected:
    std::mutex mHandleMutex;
    sp<I> mHandle GUARDED_BY(mHandleMutex);
+0 −6
Original line number Diff line number Diff line
@@ -31,8 +31,6 @@

#include "test_utils.h"

using android::hardware::vibrator::CompositeEffect;
using android::hardware::vibrator::CompositePrimitive;
using android::hardware::vibrator::Effect;
using android::hardware::vibrator::EffectStrength;

@@ -71,10 +69,6 @@ public:
                (Effect effect, EffectStrength strength,
                 const std::function<void()>& completionCallback),
                (override));
    MOCK_METHOD(vibrator::HalResult<milliseconds>, performComposedEffect,
                (const std::vector<CompositeEffect>& primitiveEffects,
                 const std::function<void()>& completionCallback),
                (override));
    MOCK_METHOD(vibrator::HalResult<vibrator::Capabilities>, getCapabilitiesInternal, (),
                (override));

+92 −9

File changed.

Preview size limit exceeded, changes collapsed.

+25 −0
Original line number Diff line number Diff line
@@ -31,11 +31,13 @@

namespace V1_0 = android::hardware::vibrator::V1_0;

using android::hardware::vibrator::Braking;
using android::hardware::vibrator::CompositeEffect;
using android::hardware::vibrator::CompositePrimitive;
using android::hardware::vibrator::Effect;
using android::hardware::vibrator::EffectStrength;
using android::hardware::vibrator::IVibrator;
using android::hardware::vibrator::PrimitivePwle;

using namespace android;
using namespace std::chrono_literals;
@@ -201,10 +203,14 @@ TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoDoesNotCacheFailedResult) {
    vibrator::Info info = mWrapper->getInfo();
    ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, info.capabilities.value());
    ASSERT_TRUE(info.supportedEffects.isUnsupported());
    ASSERT_TRUE(info.supportedBraking.isUnsupported());
    ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
    ASSERT_TRUE(info.primitiveDurations.isUnsupported());
    ASSERT_TRUE(info.minFrequency.isUnsupported());
    ASSERT_TRUE(info.resonantFrequency.isUnsupported());
    ASSERT_TRUE(info.frequencyResolution.isUnsupported());
    ASSERT_TRUE(info.qFactor.isUnsupported());
    ASSERT_TRUE(info.maxAmplitudes.isUnsupported());
}

TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoWithoutAmplitudeControl) {
@@ -230,10 +236,14 @@ TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoCachesResult) {
    vibrator::Info info = mWrapper->getInfo();
    ASSERT_EQ(vibrator::Capabilities::AMPLITUDE_CONTROL, info.capabilities.value());
    ASSERT_TRUE(info.supportedEffects.isUnsupported());
    ASSERT_TRUE(info.supportedBraking.isUnsupported());
    ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
    ASSERT_TRUE(info.primitiveDurations.isUnsupported());
    ASSERT_TRUE(info.minFrequency.isUnsupported());
    ASSERT_TRUE(info.resonantFrequency.isUnsupported());
    ASSERT_TRUE(info.frequencyResolution.isUnsupported());
    ASSERT_TRUE(info.qFactor.isUnsupported());
    ASSERT_TRUE(info.maxAmplitudes.isUnsupported());
}

TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformEffect) {
@@ -320,3 +330,18 @@ TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformComposedEffectUnsupported) {
    // No callback is triggered.
    ASSERT_EQ(0, *callbackCounter.get());
}

TEST_F(VibratorHalWrapperHidlV1_0Test, TestPerformPwleEffectUnsupported) {
    std::vector<PrimitivePwle> emptyPrimitives, multiplePrimitives;
    multiplePrimitives.push_back(vibrator::TestFactory::createActivePwle(0, 1, 0, 1, 10ms));
    multiplePrimitives.push_back(vibrator::TestFactory::createBrakingPwle(Braking::NONE, 100ms));

    std::unique_ptr<int32_t> callbackCounter = std::make_unique<int32_t>();
    auto callback = vibrator::TestFactory::createCountingCallback(callbackCounter.get());

    ASSERT_TRUE(mWrapper->performPwleEffect(emptyPrimitives, callback).isUnsupported());
    ASSERT_TRUE(mWrapper->performPwleEffect(multiplePrimitives, callback).isUnsupported());

    // No callback is triggered.
    ASSERT_EQ(0, *callbackCounter.get());
}
Loading