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

Commit 1556dcda authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add scale factor field to HapticScale" into main

parents 2c5a7c4f 045376e4
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -93,8 +93,8 @@ os::HapticScale ExternalVibration::externalVibrationScaleToHapticScale(
                  externalVibrationScale.scaleLevel);
    }

    return {/*level=*/scaleLevel, /*adaptiveScaleFactor=*/
                      externalVibrationScale.adaptiveHapticsScale};
    return os::HapticScale(scaleLevel, externalVibrationScale.scaleFactor,
                           externalVibrationScale.adaptiveHapticsScale);
}

} // namespace os
+43 −5
Original line number Diff line number Diff line
@@ -13,6 +13,8 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#define LOG_TAG "ExternalVibrationUtils"

#include <cstring>

#include <android_os_vibrator.h>
@@ -20,6 +22,7 @@
#include <algorithm>
#include <math.h>

#include <log/log.h>
#include <vibrator/ExternalVibrationUtils.h>

namespace android::os {
@@ -29,6 +32,7 @@ static constexpr float HAPTIC_SCALE_VERY_LOW_RATIO = 2.0f / 3.0f;
static constexpr float HAPTIC_SCALE_LOW_RATIO = 3.0f / 4.0f;
static constexpr float HAPTIC_MAX_AMPLITUDE_FLOAT = 1.0f;
static constexpr float SCALE_GAMMA = 0.65f; // Same as VibrationEffect.SCALE_GAMMA
static constexpr float SCALE_LEVEL_GAIN = 1.4f; // Same as VibrationConfig.DEFAULT_SCALE_LEVEL_GAIN

float getOldHapticScaleGamma(HapticLevel level) {
    switch (level) {
@@ -60,9 +64,34 @@ float getOldHapticMaxAmplitudeRatio(HapticLevel level) {
    }
}

/* Same as VibrationScaler.SCALE_LEVEL_* */
float getHapticScaleFactor(HapticLevel level) {
/* Same as VibrationScaler.getScaleFactor */
float getHapticScaleFactor(HapticScale scale) {
    if (android_os_vibrator_haptics_scale_v2_enabled()) {
        if (scale.getScaleFactor() >= 0) {
            // ExternalVibratorService provided the scale factor, use it.
            return scale.getScaleFactor();
        }

        HapticLevel level = scale.getLevel();
        switch (level) {
            case HapticLevel::MUTE:
                return 0.0f;
            case HapticLevel::NONE:
                return 1.0f;
            default:
                float scaleFactor = powf(SCALE_LEVEL_GAIN, static_cast<int32_t>(level));
                if (scaleFactor <= 0) {
                    ALOGE("Invalid scale factor %.2f for level %d, using fallback to 1.0",
                          scaleFactor, static_cast<int32_t>(level));
                    scaleFactor = 1.0f;
                }
                return scaleFactor;
        }
    }
    // Same as VibrationScaler.SCALE_FACTOR_*
    switch (scale.getLevel()) {
        case HapticLevel::MUTE:
            return 0.0f;
        case HapticLevel::VERY_LOW:
            return 0.6f;
        case HapticLevel::LOW:
@@ -83,6 +112,14 @@ float applyOldHapticScale(float value, float gamma, float maxAmplitudeRatio) {
}

float applyNewHapticScale(float value, float scaleFactor) {
    if (android_os_vibrator_haptics_scale_v2_enabled()) {
        if (scaleFactor <= 1 || value == 0) {
            return value * scaleFactor;
        } else {
            // Using S * x / (1 + (S - 1) * x^2) as the scale up function to converge to 1.0.
            return (value * scaleFactor) / (1 + (scaleFactor - 1) * value * value);
        }
    }
    float scale = powf(scaleFactor, 1.0f / SCALE_GAMMA);
    if (scaleFactor <= 1) {
        // Scale down is simply a gamma corrected application of scaleFactor to the intensity.
@@ -115,14 +152,15 @@ void applyHapticScale(float* buffer, size_t length, HapticScale scale) {
        return;
    }
    HapticLevel hapticLevel = scale.getLevel();
    float scaleFactor = getHapticScaleFactor(hapticLevel);
    float scaleFactor = getHapticScaleFactor(scale);
    float adaptiveScaleFactor = scale.getAdaptiveScaleFactor();
    float oldGamma = getOldHapticScaleGamma(hapticLevel);
    float oldMaxAmplitudeRatio = getOldHapticMaxAmplitudeRatio(hapticLevel);

    for (size_t i = 0; i < length; i++) {
        if (hapticLevel != HapticLevel::NONE) {
            if (android_os_vibrator_fix_audio_coupled_haptics_scaling()) {
            if (android_os_vibrator_fix_audio_coupled_haptics_scaling() ||
                android_os_vibrator_haptics_scale_v2_enabled()) {
                buffer[i] = applyNewHapticScale(buffer[i], scaleFactor);
            } else {
                buffer[i] = applyOldHapticScale(buffer[i], oldGamma, oldMaxAmplitudeRatio);
+30 −16
Original line number Diff line number Diff line
@@ -17,9 +17,13 @@
#ifndef ANDROID_EXTERNAL_VIBRATION_UTILS_H
#define ANDROID_EXTERNAL_VIBRATION_UTILS_H

#include <cstring>
#include <sstream>
#include <string>

namespace android::os {

enum class HapticLevel {
enum class HapticLevel : int32_t {
    MUTE = -100,
    VERY_LOW = -2,
    LOW = -1,
@@ -31,32 +35,42 @@ enum class HapticLevel {
class HapticScale {
private:
HapticLevel mLevel = HapticLevel::NONE;
float mScaleFactor = -1.0f; // undefined, use haptic level to define scale factor
float mAdaptiveScaleFactor = 1.0f;

public:
constexpr HapticScale(HapticLevel level, float adaptiveScaleFactor)
    : mLevel(level), mAdaptiveScaleFactor(adaptiveScaleFactor) {}
constexpr HapticScale(HapticLevel level) : mLevel(level) {}
    explicit HapticScale(HapticLevel level, float scaleFactor, float adaptiveScaleFactor)
          : mLevel(level), mScaleFactor(scaleFactor), mAdaptiveScaleFactor(adaptiveScaleFactor) {}
    explicit HapticScale(HapticLevel level) : mLevel(level) {}
    constexpr HapticScale() {}

    HapticLevel getLevel() const { return mLevel; }
    float getScaleFactor() const { return mScaleFactor; }
    float getAdaptiveScaleFactor() const { return mAdaptiveScaleFactor; }

    bool operator==(const HapticScale& other) const {
    return mLevel == other.mLevel && mAdaptiveScaleFactor == other.mAdaptiveScaleFactor;
        return mLevel == other.mLevel && mScaleFactor == other.mScaleFactor &&
                mAdaptiveScaleFactor == other.mAdaptiveScaleFactor;
    }

bool isScaleNone() const {
    return mLevel == HapticLevel::NONE && mAdaptiveScaleFactor == 1.0f;
    return (mLevel == HapticLevel::NONE || mScaleFactor == 1.0f) && mAdaptiveScaleFactor == 1.0f;
}

bool isScaleMute() const {
    return mLevel == HapticLevel::MUTE;
}
bool isScaleMute() const { return mLevel == HapticLevel::MUTE || mScaleFactor == 0; }

static HapticScale mute() {
    return {/*level=*/os::HapticLevel::MUTE};
std::string toString() const {
    std::ostringstream os;
    os << "HapticScale { level: " << static_cast<int>(mLevel);
    os << ", scaleFactor: " << mScaleFactor;
    os << ", adaptiveScaleFactor: " << mAdaptiveScaleFactor;
    os << "}";
    return os.str();
}

static HapticScale mute() { return os::HapticScale(os::HapticLevel::MUTE); }

static HapticScale none() { return os::HapticScale(os::HapticLevel::NONE); }
};

bool isValidHapticScale(HapticScale scale);
+13 −1
Original line number Diff line number Diff line
@@ -57,11 +57,14 @@ TEST_F(ExternalVibrationTest, TestReadAndWriteToParcel) {
    originalAttrs.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
    originalAttrs.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
    originalAttrs.flags = AUDIO_FLAG_BYPASS_MUTE;

    sp<TestVibrationController> vibrationController = new TestVibrationController();
    ASSERT_NE(vibrationController, nullptr);

    sp<os::ExternalVibration> original =
            new os::ExternalVibration(uid, pkg, originalAttrs, vibrationController);
    ASSERT_NE(original, nullptr);

    EXPECT_EQ(original->getUid(), uid);
    EXPECT_EQ(original->getPackage(), pkg);
    EXPECT_EQ(original->getAudioAttributes().content_type, originalAttrs.content_type);
@@ -69,18 +72,22 @@ TEST_F(ExternalVibrationTest, TestReadAndWriteToParcel) {
    EXPECT_EQ(original->getAudioAttributes().source, originalAttrs.source);
    EXPECT_EQ(original->getAudioAttributes().flags, originalAttrs.flags);
    EXPECT_EQ(original->getController(), vibrationController);

    audio_attributes_t defaultAttrs;
    defaultAttrs.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
    defaultAttrs.usage = AUDIO_USAGE_UNKNOWN;
    defaultAttrs.source = AUDIO_SOURCE_DEFAULT;
    defaultAttrs.flags = AUDIO_FLAG_NONE;

    sp<os::ExternalVibration> parceled =
            new os::ExternalVibration(0, std::string(""), defaultAttrs, nullptr);
    ASSERT_NE(parceled, nullptr);

    Parcel parcel;
    original->writeToParcel(&parcel);
    parcel.setDataPosition(0);
    parceled->readFromParcel(&parcel);

    EXPECT_EQ(parceled->getUid(), uid);
    EXPECT_EQ(parceled->getPackage(), pkg);
    EXPECT_EQ(parceled->getAudioAttributes().content_type, originalAttrs.content_type);
@@ -93,12 +100,17 @@ TEST_F(ExternalVibrationTest, TestReadAndWriteToParcel) {
TEST_F(ExternalVibrationTest, TestExternalVibrationScaleToHapticScale) {
    os::ExternalVibrationScale externalVibrationScale;
    externalVibrationScale.scaleLevel = ScaleLevel::SCALE_HIGH;
    externalVibrationScale.scaleFactor = 0.5f;
    externalVibrationScale.adaptiveHapticsScale = 0.8f;

    os::HapticScale hapticScale =
            os::ExternalVibration::externalVibrationScaleToHapticScale(externalVibrationScale);
    // Check scale factor is forwarded.

    // Check scale factors are forwarded.
    EXPECT_EQ(hapticScale.getLevel(), HapticLevel::HIGH);
    EXPECT_EQ(hapticScale.getScaleFactor(), 0.5f);
    EXPECT_EQ(hapticScale.getAdaptiveScaleFactor(), 0.8f);

    // Check conversion for all levels.
    EXPECT_EQ(toHapticLevel(ScaleLevel::SCALE_MUTE), HapticLevel::MUTE);
    EXPECT_EQ(toHapticLevel(ScaleLevel::SCALE_VERY_LOW), HapticLevel::VERY_LOW);
+138 −48
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ public:

protected:
    void scaleBuffer(HapticLevel hapticLevel) {
        scaleBuffer(HapticScale(hapticLevel), 0 /* limit */);
        scaleBuffer(HapticScale(hapticLevel));
    }

    void scaleBuffer(HapticLevel hapticLevel, float adaptiveScaleFactor) {
@@ -49,7 +49,11 @@ protected:
    }

    void scaleBuffer(HapticLevel hapticLevel, float adaptiveScaleFactor, float limit) {
        scaleBuffer(HapticScale(hapticLevel, adaptiveScaleFactor), limit);
        scaleBuffer(HapticScale(hapticLevel, -1 /* scaleFactor */, adaptiveScaleFactor), limit);
    }

    void scaleBuffer(HapticScale hapticScale) {
        scaleBuffer(hapticScale, 0 /* limit */);
    }

    void scaleBuffer(HapticScale hapticScale, float limit) {
@@ -60,11 +64,9 @@ protected:
    float mBuffer[TEST_BUFFER_LENGTH];
};

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestLegacyScaleMute,
        REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestLegacyScaleMute,
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling),
                                          ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expected[TEST_BUFFER_LENGTH];
    std::fill(std::begin(expected), std::end(expected), 0);

@@ -72,11 +74,9 @@ TEST_F_WITH_FLAGS(
    EXPECT_FLOATS_NEARLY_EQ(expected, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestFixedScaleMute,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestFixedScaleMute,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling)),
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expected[TEST_BUFFER_LENGTH];
    std::fill(std::begin(expected), std::end(expected), 0);

@@ -85,10 +85,19 @@ TEST_F_WITH_FLAGS(
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestLegacyScaleNone,
        REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
        ExternalVibrationUtilsTest, TestScaleV2Mute,
        // Value of fix_audio_coupled_haptics_scaling is not important, should work with either
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expected[TEST_BUFFER_LENGTH];
    std::fill(std::begin(expected), std::end(expected), 0);

    scaleBuffer(HapticLevel::MUTE);
    EXPECT_FLOATS_NEARLY_EQ(expected, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestLegacyScaleNone,
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling),
                                          ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expected[TEST_BUFFER_LENGTH];
    std::copy(std::begin(TEST_BUFFER), std::end(TEST_BUFFER), std::begin(expected));

@@ -96,11 +105,9 @@ TEST_F_WITH_FLAGS(
    EXPECT_FLOATS_NEARLY_EQ(expected, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestFixedScaleNone,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestFixedScaleNone,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling)),
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expected[TEST_BUFFER_LENGTH];
    std::copy(std::begin(TEST_BUFFER), std::end(TEST_BUFFER), std::begin(expected));

@@ -109,10 +116,19 @@ TEST_F_WITH_FLAGS(
}

TEST_F_WITH_FLAGS(
    ExternalVibrationUtilsTest,
    TestLegacyScaleToHapticLevel,
    REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
        ExternalVibrationUtilsTest, TestScaleV2None,
        // Value of fix_audio_coupled_haptics_scaling is not important, should work with either
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expected[TEST_BUFFER_LENGTH];
    std::copy(std::begin(TEST_BUFFER), std::end(TEST_BUFFER), std::begin(expected));

    scaleBuffer(HapticLevel::NONE);
    EXPECT_FLOATS_NEARLY_EQ(expected, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestLegacyScaleToHapticLevel,
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling),
                                          ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expectedVeryHigh[TEST_BUFFER_LENGTH] = { 1, -1, 0.84f, -0.66f };
    scaleBuffer(HapticLevel::VERY_HIGH);
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
@@ -130,11 +146,9 @@ TEST_F_WITH_FLAGS(
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestFixedScaleToHapticLevel,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestFixedScaleToHapticLevel,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling)),
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expectedVeryHigh[TEST_BUFFER_LENGTH] = { 1, -1, 0.79f, -0.39f };
    scaleBuffer(HapticLevel::VERY_HIGH);
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
@@ -153,10 +167,52 @@ TEST_F_WITH_FLAGS(
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestAdaptiveScaleFactorAppliedAfterLegacyScale,
        REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
        ExternalVibrationUtilsTest, TestScaleV2ToHapticLevel,
        // Value of fix_audio_coupled_haptics_scaling is not important, should work with either
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    float expectedVeryHigh[TEST_BUFFER_LENGTH] = { 1, -1, 0.8f, -0.38f };
    scaleBuffer(HapticLevel::VERY_HIGH);
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    float expectedHigh[TEST_BUFFER_LENGTH] = { 1, -1, 0.63f, -0.27f };
    scaleBuffer(HapticLevel::HIGH);
    EXPECT_FLOATS_NEARLY_EQ(expectedHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    float expectedLow[TEST_BUFFER_LENGTH] = { 0.71f, -0.71f, 0.35f, -0.14f };
    scaleBuffer(HapticLevel::LOW);
    EXPECT_FLOATS_NEARLY_EQ(expectedLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    float expectedVeryLow[TEST_BUFFER_LENGTH] = { 0.51f, -0.51f, 0.25f, -0.1f };
    scaleBuffer(HapticLevel::VERY_LOW);
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest, TestScaleV2ToScaleFactorIgnoresLevel,
    // Value of fix_audio_coupled_haptics_scaling is not important, should work with either
    REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    constexpr float adaptiveScaleNone = 1.0f;

    float expectedVeryHigh[TEST_BUFFER_LENGTH] = { 1, -1, 1, -0.55f };
    scaleBuffer(HapticScale(HapticLevel::LOW, 3.0f /* scaleFactor */, adaptiveScaleNone));
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    float expectedHigh[TEST_BUFFER_LENGTH] = { 1, -1, 0.66f, -0.29f };
    scaleBuffer(HapticScale(HapticLevel::LOW, 1.5f /* scaleFactor */, adaptiveScaleNone));
    EXPECT_FLOATS_NEARLY_EQ(expectedHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    float expectedLow[TEST_BUFFER_LENGTH] = { 0.8f, -0.8f, 0.4f, -0.16f };
    scaleBuffer(HapticScale(HapticLevel::HIGH, 0.8f /* scaleFactor */, adaptiveScaleNone));
    EXPECT_FLOATS_NEARLY_EQ(expectedLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    float expectedVeryLow[TEST_BUFFER_LENGTH] = { 0.4f, -0.4f, 0.2f, -0.08f };
    scaleBuffer(HapticScale(HapticLevel::HIGH, 0.4f /* scaleFactor */, adaptiveScaleNone));
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestAdaptiveScaleFactorAppliedAfterLegacyScale,
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling),
                                          ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    // Haptic level scale up then adaptive scale down
    float expectedVeryHigh[TEST_BUFFER_LENGTH] = { 0.2, -0.2, 0.16f, -0.13f };
    scaleBuffer(HapticLevel::VERY_HIGH, 0.2f /* adaptiveScaleFactor */);
@@ -178,11 +234,9 @@ TEST_F_WITH_FLAGS(
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestAdaptiveScaleFactorAppliedAfterFixedScale,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestAdaptiveScaleFactorAppliedAfterFixedScale,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling)),
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    // Haptic level scale up then adaptive scale down
    float expectedVeryHigh[TEST_BUFFER_LENGTH] = { 0.2, -0.2, 0.16f, -0.07f };
    scaleBuffer(HapticLevel::VERY_HIGH, 0.2f /* adaptiveScaleFactor */);
@@ -205,10 +259,33 @@ TEST_F_WITH_FLAGS(
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestLimitAppliedAfterLegacyScale,
        REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
        ExternalVibrationUtilsTest, TestAdaptiveScaleFactorAppliedAfterScaleV2,
        // Value of fix_audio_coupled_haptics_scaling is not important, should work with either
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    // Haptic level scale up then adaptive scale down
    float expectedVeryHigh[TEST_BUFFER_LENGTH] = { 0.2, -0.2, 0.15f, -0.07f };
    scaleBuffer(HapticLevel::VERY_HIGH, 0.2f /* adaptiveScaleFactor */);
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    // Haptic level scale up then adaptive scale up
    float expectedHigh[TEST_BUFFER_LENGTH] = { 1.5f, -1.5f, 0.95f, -0.41f };
    scaleBuffer(HapticLevel::HIGH, 1.5f /* adaptiveScaleFactor */);
    EXPECT_FLOATS_NEARLY_EQ(expectedHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    // Haptic level scale down then adaptive scale down
    float expectedLow[TEST_BUFFER_LENGTH] = { 0.42f, -0.42f, 0.21f, -0.08f };
    scaleBuffer(HapticLevel::LOW, 0.6f /* adaptiveScaleFactor */);
    EXPECT_FLOATS_NEARLY_EQ(expectedLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    // Haptic level scale down then adaptive scale up
    float expectedVeryLow[TEST_BUFFER_LENGTH] = { 1.02f, -1.02f, 0.51f, -0.2f };
    scaleBuffer(HapticLevel::VERY_LOW, 2 /* adaptiveScaleFactor */);
    EXPECT_FLOATS_NEARLY_EQ(expectedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestLimitAppliedAfterLegacyScale,
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling),
                                          ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    // Scaled = { 0.2, -0.2, 0.16f, -0.13f };
    float expectedClippedVeryHigh[TEST_BUFFER_LENGTH] = { 0.15f, -0.15f, 0.15f, -0.13f };
    scaleBuffer(HapticLevel::VERY_HIGH, 0.2f /* adaptiveScaleFactor */, 0.15f /* limit */);
@@ -220,11 +297,9 @@ TEST_F_WITH_FLAGS(
    EXPECT_FLOATS_NEARLY_EQ(expectedClippedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest,
        TestLimitAppliedAfterFixedScale,
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling))
) {
TEST_F_WITH_FLAGS(ExternalVibrationUtilsTest, TestLimitAppliedAfterFixedScale,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, fix_audio_coupled_haptics_scaling)),
                  REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    // Scaled = { 0.2, -0.2, 0.16f, -0.13f };
    float expectedClippedVeryHigh[TEST_BUFFER_LENGTH] = { 0.15f, -0.15f, 0.15f, -0.07f };
    scaleBuffer(HapticLevel::VERY_HIGH, 0.2f /* adaptiveScaleFactor */, 0.15f /* limit */);
@@ -235,3 +310,18 @@ TEST_F_WITH_FLAGS(
    scaleBuffer(HapticLevel::VERY_LOW, 2 /* adaptiveScaleFactor */, 0.7f /* limit */);
    EXPECT_FLOATS_NEARLY_EQ(expectedClippedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}

TEST_F_WITH_FLAGS(
        ExternalVibrationUtilsTest, TestLimitAppliedAfterScaleV2,
        // Value of fix_audio_coupled_haptics_scaling is not important, should work with either
        REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(FLAG_NS, haptics_scale_v2_enabled))) {
    // Scaled = { 0.2, -0.2, 0.15f, -0.07f };
    float expectedClippedVeryHigh[TEST_BUFFER_LENGTH] = { 0.15f, -0.15f, 0.15f, -0.07f };
    scaleBuffer(HapticLevel::VERY_HIGH, 0.2f /* adaptiveScaleFactor */, 0.15f /* limit */);
    EXPECT_FLOATS_NEARLY_EQ(expectedClippedVeryHigh, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);

    // Scaled = { 1.02f, -1.02f, 0.51f, -0.2f }
    float expectedClippedVeryLow[TEST_BUFFER_LENGTH] = { 0.7f, -0.7f, 0.51f, -0.2f };
    scaleBuffer(HapticLevel::VERY_LOW, 2 /* adaptiveScaleFactor */, 0.7f /* limit */);
    EXPECT_FLOATS_NEARLY_EQ(expectedClippedVeryLow, mBuffer, TEST_BUFFER_LENGTH, TEST_TOLERANCE);
}