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

Commit 4aa80c9d authored by Lais Andrade's avatar Lais Andrade
Browse files

Expose HAL limits for composed and PWLE vibrations

Expose limits to vibrations that use the compose and composePwle
methods, including composition sizes, primitives durations and delay.

Bug: 188431691
Fix: 183517124
Test: libvibratorservice_test
Change-Id: Id57e178cc3b718845afe4c9fb4db4fc818043dda
parent 0aa188a3
Loading
Loading
Loading
Loading
+56 −0
Original line number Original line Diff line number Diff line
@@ -135,6 +135,18 @@ Info HalWrapper::getInfo() {
    if (mInfoCache.mSupportedBraking.isFailed()) {
    if (mInfoCache.mSupportedBraking.isFailed()) {
        mInfoCache.mSupportedBraking = getSupportedBrakingInternal();
        mInfoCache.mSupportedBraking = getSupportedBrakingInternal();
    }
    }
    if (mInfoCache.mPrimitiveDelayMax.isFailed()) {
        mInfoCache.mPrimitiveDelayMax = getPrimitiveDelayMaxInternal();
    }
    if (mInfoCache.mPwlePrimitiveDurationMax.isFailed()) {
        mInfoCache.mPwlePrimitiveDurationMax = getPrimitiveDurationMaxInternal();
    }
    if (mInfoCache.mCompositionSizeMax.isFailed()) {
        mInfoCache.mCompositionSizeMax = getCompositionSizeMaxInternal();
    }
    if (mInfoCache.mPwleSizeMax.isFailed()) {
        mInfoCache.mPwleSizeMax = getPwleSizeMaxInternal();
    }
    if (mInfoCache.mMinFrequency.isFailed()) {
    if (mInfoCache.mMinFrequency.isFailed()) {
        mInfoCache.mMinFrequency = getMinFrequencyInternal();
        mInfoCache.mMinFrequency = getMinFrequencyInternal();
    }
    }
@@ -209,6 +221,26 @@ HalResult<std::vector<milliseconds>> HalWrapper::getPrimitiveDurationsInternal(
    return HalResult<std::vector<milliseconds>>::unsupported();
    return HalResult<std::vector<milliseconds>>::unsupported();
}
}


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

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

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

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

HalResult<float> HalWrapper::getMinFrequencyInternal() {
HalResult<float> HalWrapper::getMinFrequencyInternal() {
    ALOGV("Skipped getMinFrequency because it's not available in Vibrator HAL");
    ALOGV("Skipped getMinFrequency because it's not available in Vibrator HAL");
    return HalResult<float>::unsupported();
    return HalResult<float>::unsupported();
@@ -383,6 +415,30 @@ HalResult<std::vector<milliseconds>> AidlHalWrapper::getPrimitiveDurationsIntern
    return HalResult<std::vector<milliseconds>>::ok(durations);
    return HalResult<std::vector<milliseconds>>::ok(durations);
}
}


HalResult<milliseconds> AidlHalWrapper::getPrimitiveDelayMaxInternal() {
    int32_t delay = 0;
    auto result = getHal()->getCompositionDelayMax(&delay);
    return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
}

HalResult<milliseconds> AidlHalWrapper::getPrimitiveDurationMaxInternal() {
    int32_t delay = 0;
    auto result = getHal()->getPwlePrimitiveDurationMax(&delay);
    return HalResult<milliseconds>::fromStatus(result, milliseconds(delay));
}

HalResult<int32_t> AidlHalWrapper::getCompositionSizeMaxInternal() {
    int32_t size = 0;
    auto result = getHal()->getCompositionSizeMax(&size);
    return HalResult<int32_t>::fromStatus(result, size);
}

HalResult<int32_t> AidlHalWrapper::getPwleSizeMaxInternal() {
    int32_t size = 0;
    auto result = getHal()->getPwleCompositionSizeMax(&size);
    return HalResult<int32_t>::fromStatus(result, size);
}

HalResult<float> AidlHalWrapper::getMinFrequencyInternal() {
HalResult<float> AidlHalWrapper::getMinFrequencyInternal() {
    float minFrequency = 0;
    float minFrequency = 0;
    auto result = getHal()->getFrequencyMinimum(&minFrequency);
    auto result = getHal()->getFrequencyMinimum(&minFrequency);
+35 −3
Original line number Original line Diff line number Diff line
@@ -182,6 +182,10 @@ public:
    const HalResult<std::vector<hardware::vibrator::Braking>> supportedBraking;
    const HalResult<std::vector<hardware::vibrator::Braking>> supportedBraking;
    const HalResult<std::vector<hardware::vibrator::CompositePrimitive>> supportedPrimitives;
    const HalResult<std::vector<hardware::vibrator::CompositePrimitive>> supportedPrimitives;
    const HalResult<std::vector<std::chrono::milliseconds>> primitiveDurations;
    const HalResult<std::vector<std::chrono::milliseconds>> primitiveDurations;
    const HalResult<std::chrono::milliseconds> primitiveDelayMax;
    const HalResult<std::chrono::milliseconds> pwlePrimitiveDurationMax;
    const HalResult<int32_t> compositionSizeMax;
    const HalResult<int32_t> pwleSizeMax;
    const HalResult<float> minFrequency;
    const HalResult<float> minFrequency;
    const HalResult<float> resonantFrequency;
    const HalResult<float> resonantFrequency;
    const HalResult<float> frequencyResolution;
    const HalResult<float> frequencyResolution;
@@ -194,6 +198,10 @@ public:
                supportedBraking.checkAndLogFailure("getSupportedBraking") ||
                supportedBraking.checkAndLogFailure("getSupportedBraking") ||
                supportedPrimitives.checkAndLogFailure("getSupportedPrimitives") ||
                supportedPrimitives.checkAndLogFailure("getSupportedPrimitives") ||
                primitiveDurations.checkAndLogFailure("getPrimitiveDuration") ||
                primitiveDurations.checkAndLogFailure("getPrimitiveDuration") ||
                primitiveDelayMax.checkAndLogFailure("getPrimitiveDelayMax") ||
                pwlePrimitiveDurationMax.checkAndLogFailure("getPwlePrimitiveDurationMax") ||
                compositionSizeMax.checkAndLogFailure("getCompositionSizeMax") ||
                pwleSizeMax.checkAndLogFailure("getPwleSizeMax") ||
                minFrequency.checkAndLogFailure("getMinFrequency") ||
                minFrequency.checkAndLogFailure("getMinFrequency") ||
                resonantFrequency.checkAndLogFailure("getResonantFrequency") ||
                resonantFrequency.checkAndLogFailure("getResonantFrequency") ||
                frequencyResolution.checkAndLogFailure("getFrequencyResolution") ||
                frequencyResolution.checkAndLogFailure("getFrequencyResolution") ||
@@ -205,9 +213,19 @@ public:
class InfoCache {
class InfoCache {
public:
public:
    Info get() {
    Info get() {
        return {mCapabilities,        mSupportedEffects,    mSupportedBraking,
        return {mCapabilities,
                mSupportedPrimitives, mPrimitiveDurations,  mMinFrequency,
                mSupportedEffects,
                mResonantFrequency,   mFrequencyResolution, mQFactor,
                mSupportedBraking,
                mSupportedPrimitives,
                mPrimitiveDurations,
                mPrimitiveDelayMax,
                mPwlePrimitiveDurationMax,
                mCompositionSizeMax,
                mPwleSizeMax,
                mMinFrequency,
                mResonantFrequency,
                mFrequencyResolution,
                mQFactor,
                mMaxAmplitudes};
                mMaxAmplitudes};
    }
    }


@@ -222,6 +240,12 @@ private:
            HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG);
            HalResult<std::vector<hardware::vibrator::CompositePrimitive>>::failed(MSG);
    HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations =
    HalResult<std::vector<std::chrono::milliseconds>> mPrimitiveDurations =
            HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG);
            HalResult<std::vector<std::chrono::milliseconds>>::failed(MSG);
    HalResult<std::chrono::milliseconds> mPrimitiveDelayMax =
            HalResult<std::chrono::milliseconds>::failed(MSG);
    HalResult<std::chrono::milliseconds> mPwlePrimitiveDurationMax =
            HalResult<std::chrono::milliseconds>::failed(MSG);
    HalResult<int32_t> mCompositionSizeMax = HalResult<int>::failed(MSG);
    HalResult<int32_t> mPwleSizeMax = HalResult<int>::failed(MSG);
    HalResult<float> mMinFrequency = HalResult<float>::failed(MSG);
    HalResult<float> mMinFrequency = HalResult<float>::failed(MSG);
    HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG);
    HalResult<float> mResonantFrequency = HalResult<float>::failed(MSG);
    HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG);
    HalResult<float> mFrequencyResolution = HalResult<float>::failed(MSG);
@@ -285,6 +309,10 @@ protected:
    getSupportedPrimitivesInternal();
    getSupportedPrimitivesInternal();
    virtual HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
    virtual HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
            const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives);
            const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives);
    virtual HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal();
    virtual HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal();
    virtual HalResult<int32_t> getCompositionSizeMaxInternal();
    virtual HalResult<int32_t> getPwleSizeMaxInternal();
    virtual HalResult<float> getMinFrequencyInternal();
    virtual HalResult<float> getMinFrequencyInternal();
    virtual HalResult<float> getResonantFrequencyInternal();
    virtual HalResult<float> getResonantFrequencyInternal();
    virtual HalResult<float> getFrequencyResolutionInternal();
    virtual HalResult<float> getFrequencyResolutionInternal();
@@ -347,6 +375,10 @@ protected:
    HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
    HalResult<std::vector<std::chrono::milliseconds>> getPrimitiveDurationsInternal(
            const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives)
            const std::vector<hardware::vibrator::CompositePrimitive>& supportedPrimitives)
            override final;
            override final;
    HalResult<std::chrono::milliseconds> getPrimitiveDelayMaxInternal() override final;
    HalResult<std::chrono::milliseconds> getPrimitiveDurationMaxInternal() override final;
    HalResult<int32_t> getCompositionSizeMaxInternal() override final;
    HalResult<int32_t> getPwleSizeMaxInternal() override final;
    HalResult<float> getMinFrequencyInternal() override final;
    HalResult<float> getMinFrequencyInternal() override final;
    HalResult<float> getResonantFrequencyInternal() override final;
    HalResult<float> getResonantFrequencyInternal() override final;
    HalResult<float> getFrequencyResolutionInternal() override final;
    HalResult<float> getFrequencyResolutionInternal() override final;
+49 −0
Original line number Original line Diff line number Diff line
@@ -301,6 +301,10 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoDoesNotCacheFailedResult) {
    constexpr float F0 = 123.f;
    constexpr float F0 = 123.f;
    constexpr float F_RESOLUTION = 0.5f;
    constexpr float F_RESOLUTION = 0.5f;
    constexpr float Q_FACTOR = 123.f;
    constexpr float Q_FACTOR = 123.f;
    constexpr int32_t COMPOSITION_SIZE_MAX = 10;
    constexpr int32_t PWLE_SIZE_MAX = 20;
    constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
    constexpr int32_t PWLE_DURATION_MAX = 200;
    std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
    std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
    std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK};
    std::vector<CompositePrimitive> supportedPrimitives = {CompositePrimitive::CLICK};
    std::vector<Braking> supportedBraking = {Braking::CLAB};
    std::vector<Braking> supportedBraking = {Braking::CLAB};
@@ -331,6 +335,22 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoDoesNotCacheFailedResult) {
    EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _))
    EXPECT_CALL(*mMockHal.get(), getPrimitiveDuration(Eq(CompositePrimitive::CLICK), _))
            .Times(Exactly(1))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<1>(10), Return(Status())));
            .WillRepeatedly(DoAll(SetArgPointee<1>(10), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
            .Times(Exactly(2))
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
            .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
            .Times(Exactly(2))
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
            .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
            .Times(Exactly(2))
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
            .Times(Exactly(2))
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
    EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
            .Times(Exactly(2))
            .Times(Exactly(2))
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
            .WillOnce(Return(Status::fromExceptionCode(Status::Exception::EX_SECURITY)))
@@ -358,6 +378,10 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoDoesNotCacheFailedResult) {
    ASSERT_TRUE(failed.supportedBraking.isFailed());
    ASSERT_TRUE(failed.supportedBraking.isFailed());
    ASSERT_TRUE(failed.supportedPrimitives.isFailed());
    ASSERT_TRUE(failed.supportedPrimitives.isFailed());
    ASSERT_TRUE(failed.primitiveDurations.isFailed());
    ASSERT_TRUE(failed.primitiveDurations.isFailed());
    ASSERT_TRUE(failed.primitiveDelayMax.isFailed());
    ASSERT_TRUE(failed.pwlePrimitiveDurationMax.isFailed());
    ASSERT_TRUE(failed.compositionSizeMax.isFailed());
    ASSERT_TRUE(failed.pwleSizeMax.isFailed());
    ASSERT_TRUE(failed.minFrequency.isFailed());
    ASSERT_TRUE(failed.minFrequency.isFailed());
    ASSERT_TRUE(failed.resonantFrequency.isFailed());
    ASSERT_TRUE(failed.resonantFrequency.isFailed());
    ASSERT_TRUE(failed.frequencyResolution.isFailed());
    ASSERT_TRUE(failed.frequencyResolution.isFailed());
@@ -370,6 +394,11 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoDoesNotCacheFailedResult) {
    ASSERT_EQ(supportedBraking, successful.supportedBraking.value());
    ASSERT_EQ(supportedBraking, successful.supportedBraking.value());
    ASSERT_EQ(supportedPrimitives, successful.supportedPrimitives.value());
    ASSERT_EQ(supportedPrimitives, successful.supportedPrimitives.value());
    ASSERT_EQ(primitiveDurations, successful.primitiveDurations.value());
    ASSERT_EQ(primitiveDurations, successful.primitiveDurations.value());
    ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), successful.primitiveDelayMax.value());
    ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX),
              successful.pwlePrimitiveDurationMax.value());
    ASSERT_EQ(COMPOSITION_SIZE_MAX, successful.compositionSizeMax.value());
    ASSERT_EQ(PWLE_SIZE_MAX, successful.pwleSizeMax.value());
    ASSERT_EQ(F_MIN, successful.minFrequency.value());
    ASSERT_EQ(F_MIN, successful.minFrequency.value());
    ASSERT_EQ(F0, successful.resonantFrequency.value());
    ASSERT_EQ(F0, successful.resonantFrequency.value());
    ASSERT_EQ(F_RESOLUTION, successful.frequencyResolution.value());
    ASSERT_EQ(F_RESOLUTION, successful.frequencyResolution.value());
@@ -380,6 +409,10 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoDoesNotCacheFailedResult) {
TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
    constexpr float F_MIN = 100.f;
    constexpr float F_MIN = 100.f;
    constexpr float F0 = 123.f;
    constexpr float F0 = 123.f;
    constexpr int32_t COMPOSITION_SIZE_MAX = 10;
    constexpr int32_t PWLE_SIZE_MAX = 20;
    constexpr int32_t PRIMITIVE_DELAY_MAX = 100;
    constexpr int32_t PWLE_DURATION_MAX = 200;
    std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};
    std::vector<Effect> supportedEffects = {Effect::CLICK, Effect::TICK};


    EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
    EXPECT_CALL(*mMockHal.get(), getCapabilities(_))
@@ -395,6 +428,18 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
    EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
    EXPECT_CALL(*mMockHal.get(), getSupportedPrimitives(_))
            .Times(Exactly(1))
            .Times(Exactly(1))
            .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
            .WillRepeatedly(Return(Status::fromStatusT(UNKNOWN_TRANSACTION)));
    EXPECT_CALL(*mMockHal.get(), getCompositionSizeMax(_))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<0>(COMPOSITION_SIZE_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getCompositionDelayMax(_))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<0>(PRIMITIVE_DELAY_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getPwlePrimitiveDurationMax(_))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_DURATION_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getPwleCompositionSizeMax(_))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<0>(PWLE_SIZE_MAX), Return(Status())));
    EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
    EXPECT_CALL(*mMockHal.get(), getFrequencyMinimum(_))
            .Times(Exactly(1))
            .Times(Exactly(1))
            .WillRepeatedly(DoAll(SetArgPointee<0>(F_MIN), Return(Status())));
            .WillRepeatedly(DoAll(SetArgPointee<0>(F_MIN), Return(Status())));
@@ -426,6 +471,10 @@ TEST_F(VibratorHalWrapperAidlTest, TestGetInfoCachesResult) {
    ASSERT_TRUE(info.supportedBraking.isUnsupported());
    ASSERT_TRUE(info.supportedBraking.isUnsupported());
    ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
    ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
    ASSERT_TRUE(info.primitiveDurations.isUnsupported());
    ASSERT_TRUE(info.primitiveDurations.isUnsupported());
    ASSERT_EQ(std::chrono::milliseconds(PRIMITIVE_DELAY_MAX), info.primitiveDelayMax.value());
    ASSERT_EQ(std::chrono::milliseconds(PWLE_DURATION_MAX), info.pwlePrimitiveDurationMax.value());
    ASSERT_EQ(COMPOSITION_SIZE_MAX, info.compositionSizeMax.value());
    ASSERT_EQ(PWLE_SIZE_MAX, info.pwleSizeMax.value());
    ASSERT_EQ(F_MIN, info.minFrequency.value());
    ASSERT_EQ(F_MIN, info.minFrequency.value());
    ASSERT_EQ(F0, info.resonantFrequency.value());
    ASSERT_EQ(F0, info.resonantFrequency.value());
    ASSERT_TRUE(info.frequencyResolution.isUnsupported());
    ASSERT_TRUE(info.frequencyResolution.isUnsupported());
+4 −0
Original line number Original line Diff line number Diff line
@@ -206,6 +206,10 @@ TEST_F(VibratorHalWrapperHidlV1_0Test, TestGetInfoDoesNotCacheFailedResult) {
    ASSERT_TRUE(info.supportedBraking.isUnsupported());
    ASSERT_TRUE(info.supportedBraking.isUnsupported());
    ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
    ASSERT_TRUE(info.supportedPrimitives.isUnsupported());
    ASSERT_TRUE(info.primitiveDurations.isUnsupported());
    ASSERT_TRUE(info.primitiveDurations.isUnsupported());
    ASSERT_TRUE(info.primitiveDelayMax.isUnsupported());
    ASSERT_TRUE(info.pwlePrimitiveDurationMax.isUnsupported());
    ASSERT_TRUE(info.compositionSizeMax.isUnsupported());
    ASSERT_TRUE(info.pwleSizeMax.isUnsupported());
    ASSERT_TRUE(info.minFrequency.isUnsupported());
    ASSERT_TRUE(info.minFrequency.isUnsupported());
    ASSERT_TRUE(info.resonantFrequency.isUnsupported());
    ASSERT_TRUE(info.resonantFrequency.isUnsupported());
    ASSERT_TRUE(info.frequencyResolution.isUnsupported());
    ASSERT_TRUE(info.frequencyResolution.isUnsupported());