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

Commit f74bfe1f authored by Ahmad Khalil's avatar Ahmad Khalil Committed by Android (Google) Code Review
Browse files

Merge "Add adaptive haptics scaling to external vibrations" into main

parents 1c7ace3d 2cd8035e
Loading
Loading
Loading
Loading
+30 −18
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
#include <vibrator/ExternalVibration.h>
#include <vibrator/ExternalVibrationUtils.h>

#include <android/os/IExternalVibratorService.h>
#include <android/os/ExternalVibrationScale.h>
#include <binder/Parcel.h>
#include <log/log.h>
#include <utils/Errors.h>
@@ -65,24 +65,36 @@ inline bool ExternalVibration::operator==(const ExternalVibration& rhs) const {
    return mToken == rhs.mToken;
}

os::HapticScale ExternalVibration::externalVibrationScaleToHapticScale(int externalVibrationScale) {
    switch (externalVibrationScale) {
        case IExternalVibratorService::SCALE_MUTE:
            return os::HapticScale::MUTE;
        case IExternalVibratorService::SCALE_VERY_LOW:
            return os::HapticScale::VERY_LOW;
        case IExternalVibratorService::SCALE_LOW:
            return os::HapticScale::LOW;
        case IExternalVibratorService::SCALE_NONE:
            return os::HapticScale::NONE;
        case IExternalVibratorService::SCALE_HIGH:
            return os::HapticScale::HIGH;
        case IExternalVibratorService::SCALE_VERY_HIGH:
            return os::HapticScale::VERY_HIGH;
os::HapticScale ExternalVibration::externalVibrationScaleToHapticScale(
        os::ExternalVibrationScale externalVibrationScale) {
    os::HapticLevel scaleLevel = os::HapticLevel::NONE;

    switch (externalVibrationScale.scaleLevel) {
        case os::ExternalVibrationScale::ScaleLevel::SCALE_MUTE:
            scaleLevel = os::HapticLevel::MUTE;
            break;
        case os::ExternalVibrationScale::ScaleLevel::SCALE_VERY_LOW:
            scaleLevel = os::HapticLevel::VERY_LOW;
            break;
        case os::ExternalVibrationScale::ScaleLevel::SCALE_LOW:
            scaleLevel = os::HapticLevel::LOW;
            break;
        case os::ExternalVibrationScale::ScaleLevel::SCALE_NONE:
            scaleLevel = os::HapticLevel::NONE;
            break;
        case os::ExternalVibrationScale::ScaleLevel::SCALE_HIGH:
            scaleLevel = os::HapticLevel::HIGH;
            break;
        case os::ExternalVibrationScale::ScaleLevel::SCALE_VERY_HIGH:
            scaleLevel = os::HapticLevel::VERY_HIGH;
            break;
        default:
          ALOGE("Unknown ExternalVibrationScale %d, not applying scaling", externalVibrationScale);
          return os::HapticScale::NONE;
            ALOGE("Unknown ExternalVibrationScale %d, not applying scaling",
                  externalVibrationScale.scaleLevel);
    }

    return {/*level=*/scaleLevel, /*adaptiveScaleFactor=*/
                      externalVibrationScale.adaptiveHapticsScale};
}

} // namespace os
+36 −27
Original line number Diff line number Diff line
@@ -26,30 +26,30 @@ 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;

float getHapticScaleGamma(HapticScale scale) {
    switch (scale) {
    case HapticScale::VERY_LOW:
float getHapticScaleGamma(HapticLevel level) {
    switch (level) {
    case HapticLevel::VERY_LOW:
        return 2.0f;
    case HapticScale::LOW:
    case HapticLevel::LOW:
        return 1.5f;
    case HapticScale::HIGH:
    case HapticLevel::HIGH:
        return 0.5f;
    case HapticScale::VERY_HIGH:
    case HapticLevel::VERY_HIGH:
        return 0.25f;
    default:
        return 1.0f;
    }
}

float getHapticMaxAmplitudeRatio(HapticScale scale) {
    switch (scale) {
    case HapticScale::VERY_LOW:
float getHapticMaxAmplitudeRatio(HapticLevel level) {
    switch (level) {
    case HapticLevel::VERY_LOW:
        return HAPTIC_SCALE_VERY_LOW_RATIO;
    case HapticScale::LOW:
    case HapticLevel::LOW:
        return HAPTIC_SCALE_LOW_RATIO;
    case HapticScale::NONE:
    case HapticScale::HIGH:
    case HapticScale::VERY_HIGH:
    case HapticLevel::NONE:
    case HapticLevel::HIGH:
    case HapticLevel::VERY_HIGH:
        return 1.0f;
    default:
        return 0.0f;
@@ -57,20 +57,29 @@ float getHapticMaxAmplitudeRatio(HapticScale scale) {
}

void applyHapticScale(float* buffer, size_t length, HapticScale scale) {
    if (scale == HapticScale::MUTE) {
    if (scale.isScaleMute()) {
        memset(buffer, 0, length * sizeof(float));
        return;
    }
    if (scale == HapticScale::NONE) {
    if (scale.isScaleNone()) {
        return;
    }
    float gamma = getHapticScaleGamma(scale);
    float maxAmplitudeRatio = getHapticMaxAmplitudeRatio(scale);
    HapticLevel hapticLevel = scale.getLevel();
    float adaptiveScaleFactor = scale.getAdaptiveScaleFactor();
    float gamma = getHapticScaleGamma(hapticLevel);
    float maxAmplitudeRatio = getHapticMaxAmplitudeRatio(hapticLevel);

    for (size_t i = 0; i < length; i++) {
        if (hapticLevel != HapticLevel::NONE) {
            float sign = buffer[i] >= 0 ? 1.0 : -1.0;
            buffer[i] = powf(fabsf(buffer[i] / HAPTIC_MAX_AMPLITUDE_FLOAT), gamma)
                        * maxAmplitudeRatio * HAPTIC_MAX_AMPLITUDE_FLOAT * sign;
        }

        if (adaptiveScaleFactor != 1.0f) {
            buffer[i] *= adaptiveScaleFactor;
        }
    }
}

void clipHapticData(float* buffer, size_t length, float limit) {
@@ -89,13 +98,13 @@ void clipHapticData(float* buffer, size_t length, float limit) {
} // namespace

bool isValidHapticScale(HapticScale scale) {
    switch (scale) {
    case HapticScale::MUTE:
    case HapticScale::VERY_LOW:
    case HapticScale::LOW:
    case HapticScale::NONE:
    case HapticScale::HIGH:
    case HapticScale::VERY_HIGH:
    switch (scale.getLevel()) {
    case HapticLevel::MUTE:
    case HapticLevel::VERY_LOW:
    case HapticLevel::LOW:
    case HapticLevel::NONE:
    case HapticLevel::HIGH:
    case HapticLevel::VERY_HIGH:
        return true;
    }
    return false;
+4 −2
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <system/audio.h>
#include <utils/RefBase.h>
#include <vibrator/ExternalVibrationUtils.h>
#include <android/os/ExternalVibrationScale.h>

namespace android {
namespace os {
@@ -45,10 +46,11 @@ public :
    audio_attributes_t getAudioAttributes() const { return mAttrs; }
    sp<IExternalVibrationController> getController() { return mController; }

    /* Converts the scale from non-public ExternalVibrationService into the HapticScale
    /* Converts the scale from non-public ExternalVibrationService into the HapticScaleLevel
     * used by the utils.
     */
    static os::HapticScale externalVibrationScaleToHapticScale(int externalVibrationScale);
    static os::HapticScale externalVibrationScaleToHapticScale(
            os::ExternalVibrationScale externalVibrationScale);

private:
    int32_t mUid;
+34 −3
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@

namespace android::os {

enum class HapticScale {
enum class HapticLevel {
    MUTE = -100,
    VERY_LOW = -2,
    LOW = -1,
@@ -28,10 +28,41 @@ enum class HapticScale {
    VERY_HIGH = 2,
};

class HapticScale {
private:
HapticLevel mLevel = HapticLevel::NONE;
float mAdaptiveScaleFactor = 1.0f;

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

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

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

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

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

static HapticScale mute() {
    return {/*level=*/os::HapticLevel::MUTE};
}
};

bool isValidHapticScale(HapticScale scale);

/* Scales the haptic data in given buffer using the selected HapticScale and ensuring no absolute
 * value will be larger than the absolute of given limit.
/* Scales the haptic data in given buffer using the selected HapticScaleLevel and ensuring no
 * absolute value will be larger than the absolute of given limit.
 * The limit will be ignored if it is NaN or zero.
 */
void scaleHapticData(float* buffer, size_t length, HapticScale scale, float limit);