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

Commit e0f94c5a authored by Lais Andrade's avatar Lais Andrade Committed by Android (Google) Code Review
Browse files

Merge "Implement PWLE support" into sc-dev

parents b6209ad5 92f2af5c
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