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

Commit 03373895 authored by Lais Andrade's avatar Lais Andrade
Browse files

Introduce device config for vibration scales

Add two new keys to core/res/config.xml to allow device configurable
scale factors to be used for each vibration intensity setting value.

The configurations must provide a scale value to be used directly for
each user intensity setting value: LOW, MEDIUM and HIGH.

The framework logic around device default setting vs user setting will
be ignored on devices that provide this direct scale value config, so
the user setting will translate directly into a scale factor to be used
as a direct multiplier for the input values.

There is also a separate config key for external vibrations (a.k.a
audio-coupled haptics), which can be used to configure their scaling
separately. If no config is provided, the vibration config will still be
applied to external vibrations for consistency with vibration effects.

Fix: 427503922
Flag: android.os.vibrator.vibration_scale_device_config_enabled
Test: FrameworksVibratorServicesTests
Change-Id: Ic5d67f6a45865d054f96bb04e692578624a69a44
parent fcb00bc1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ package android.os;
 * @hide
 */
parcelable ExternalVibrationScale {
    // TODO(b/345186129): remove this once we finish migrating to scale factor.
    @Backing(type="int")
    enum ScaleLevel {
        SCALE_MUTE = -100,
+27 −0
Original line number Diff line number Diff line
@@ -644,6 +644,19 @@ public abstract class VibrationEffect implements Parcelable {
     *                    scale down the intensity, values larger than 1 will scale up
     * @return this if there is no scaling to be done, or a copy of this effect with scaled
     *         vibration intensity otherwise
     *
     * @hide
     */
    @NonNull
    public abstract VibrationEffect scaleLinearly(float scaleFactor);

    /**
     * Applies given scale factor as adaptive scale.
     *
     * @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
     *                    scale down the intensity, values larger than 1 will scale up
     * @return this if there is no scaling to be done, or a copy of this effect with scaled
     *         vibration intensity otherwise
     * @hide
     */
    @NonNull
@@ -1003,6 +1016,13 @@ public abstract class VibrationEffect implements Parcelable {
            return applyToSegments(VibrationEffectSegment::scale, scaleFactor);
        }

        /** @hide */
        @NonNull
        @Override
        public Composed scaleLinearly(float scaleFactor) {
            return applyToSegments(VibrationEffectSegment::scaleLinearly, scaleFactor);
        }

        /** @hide */
        @NonNull
        @Override
@@ -1265,6 +1285,13 @@ public abstract class VibrationEffect implements Parcelable {
            return updated;
        }

        /** @hide */
        @NonNull
        @Override
        public VibrationEffect scaleLinearly(float scaleFactor) {
            return scale(scaleFactor);
        }

        /** @hide */
        @NonNull
        @Override
+81 −2
Original line number Diff line number Diff line
@@ -63,13 +63,14 @@ public class VibrationConfig {
     */
    private static final int DEFAULT_AMPLITUDE = 255;

    // TODO(b/191150049): move these to vibrator static config file
    private final float mHapticChannelMaxVibrationAmplitude;
    private final int mDefaultVibrationAmplitude;
    private final int mRampStepDurationMs;
    private final int mRampDownDurationMs;
    private final int mRequestVibrationParamsTimeoutMs;
    private final int[] mRequestVibrationParamsForUsages;
    private final float[] mVibrationScaleFactors;
    private final float[] mExternalVibrationScaleFactors;

    private final boolean mIgnoreVibrationsOnWirelessCharger;

@@ -123,6 +124,11 @@ public class VibrationConfig {
                com.android.internal.R.integer.config_defaultRingVibrationIntensity);
        mDefaultKeyboardVibrationIntensity = loadDefaultIntensity(resources,
                com.android.internal.R.integer.config_defaultKeyboardVibrationIntensity);

        mVibrationScaleFactors = loadIntensityScaleFactors(resources,
                com.android.internal.R.array.config_vibrationIntensityScaleFactors);
        mExternalVibrationScaleFactors = loadIntensityScaleFactors(resources,
                com.android.internal.R.array.config_externalVibrationIntensityScaleFactors);
    }

    @VibrationIntensity
@@ -135,6 +141,22 @@ public class VibrationConfig {
        return value;
    }

    @Nullable
    private static float[] loadIntensityScaleFactors(@Nullable Resources res, int resId) {
        float[] scales = loadFloatArray(res, resId);
        if (scales == null || scales.length != Vibrator.VIBRATION_INTENSITY_HIGH) {
            // Missing or bad config, ignore it.
            return null;
        }
        for (float scale : scales) {
            if (scale <= 0) {
                // Bad scale value, ignore config.
                return null;
            }
        }
        return scales;
    }

    private static float loadFloat(@Nullable Resources res, int resId) {
        return res != null ? res.getFloat(resId) : 0f;
    }
@@ -151,6 +173,22 @@ public class VibrationConfig {
        return res != null ? res.getIntArray(resId) : new int[0];
    }

    private static float[] loadFloatArray(@Nullable Resources res, int resId) {
        String[] values = res != null ? res.getStringArray(resId) : null;
        if (values == null) {
            return null;
        }
        float[] parsedValues = new float[values.length];
        for (int i = 0; i < values.length; i++) {
            try {
                parsedValues[i] = Float.parseFloat(values[i]);
            } catch (Exception e) {
                return null;
            }
        }
        return parsedValues;
    }

    /**
     * Return the maximum amplitude the vibrator can play using the audio haptic channels.
     *
@@ -180,10 +218,45 @@ public class VibrationConfig {
     * for each level.
     */
    public float getDefaultVibrationScaleLevelGain() {
        // TODO(b/356407380): add device config for this
        return DEFAULT_SCALE_LEVEL_GAIN;
    }

    /** Return true if device has vibration scale factors config. */
    public boolean hasVibrationScaleFactors() {
        return mVibrationScaleFactors != null;
    }

    /**
     * Return the scale factor configured for given intensity, or the default value if no
     * configuration is in place.
     */
    public float getVibrationScaleFactor(@VibrationIntensity int intensity, float defaultValue) {
        if (mVibrationScaleFactors == null || mVibrationScaleFactors.length < intensity) {
            return defaultValue;
        }
        return mVibrationScaleFactors[intensity - 1];
    }

    /** Return true if device has vibration scale factors config. */
    public boolean hasExternalVibrationScaleFactors() {
        return mExternalVibrationScaleFactors != null;
    }

    /**
     * Return the scale factor configured for given intensity for external vibrations.
     *
     * <p>This will return {@link #getVibrationScaleFactor} if no configuration is in place
     * specifically for external vibrations.
     */
    public float getExternalVibrationScaleFactor(@VibrationIntensity int intensity,
            float defaultValue) {
        if (mExternalVibrationScaleFactors == null
                || mExternalVibrationScaleFactors.length < intensity) {
            return getVibrationScaleFactor(intensity, defaultValue);
        }
        return mExternalVibrationScaleFactors[intensity - 1];
    }

    /**
     * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator
     * when a vibration is cancelled or finished at non-zero amplitude.
@@ -305,6 +378,9 @@ public class VibrationConfig {
                + ", mDefaultRingIntensity=" + mDefaultRingVibrationIntensity
                + ", mDefaultKeyboardIntensity=" + mDefaultKeyboardVibrationIntensity
                + ", mKeyboardVibrationSettingsSupported=" + mKeyboardVibrationSettingsSupported
                + ", mVibrationScaleFactors=" + Arrays.toString(mVibrationScaleFactors)
                + ", mExternalVibrationScaleFactors="
                + Arrays.toString(mExternalVibrationScaleFactors)
                + "}";
    }

@@ -319,6 +395,9 @@ public class VibrationConfig {
        pw.println("ignoreVibrationsOnWirelessCharger = " + mIgnoreVibrationsOnWirelessCharger);
        pw.println("defaultVibrationAmplitude = " + mDefaultVibrationAmplitude);
        pw.println("hapticChannelMaxAmplitude = " + mHapticChannelMaxVibrationAmplitude);
        pw.println("vibrationScaleFactors = " + Arrays.toString(mVibrationScaleFactors));
        pw.println("externalVibrationScaleFactors = "
                + Arrays.toString(mExternalVibrationScaleFactors));
        pw.println("rampStepDurationMs = " + mRampStepDurationMs);
        pw.println("rampDownDurationMs = " + mRampDownDurationMs);
        pw.println("requestVibrationParamsForUsages = "
+10 −0
Original line number Diff line number Diff line
@@ -146,3 +146,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "haptics"
    name: "vibration_scale_device_config_enabled"
    description: "Enables device-configurable vibration scale factors"
    bug: "427503922"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+25 −0
Original line number Diff line number Diff line
@@ -4390,6 +4390,31 @@
    <!-- The default vibration strength, must be between 1 and 255 inclusive. -->
    <integer name="config_defaultVibrationAmplitude">255</integer>

    <!-- The scale factor to be applied at each vibration intensity level supported by the device,
     defined by a positive float value.
     The default framework scaling will be applied if this is not set, based on the user and the
     default scales for each usage.
     The number of entries here must be the device supported scale levels for LOW/MEDIUM/HIGH.
     Example:
     <string-array name="config_vibrationIntensityScaleFactors" translatable="false">
       <item>0.5</item> -> Vibrator.VIBRATION_INTENSITY_LOW
       <item>0.7</item> -> Vibrator.VIBRATION_INTENSITY_MEDIUM
       <item>1.0</item> -> Vibrator.VIBRATION_INTENSITY_HIGH
     </string-array> -->
    <string-array name="config_vibrationIntensityScaleFactors" translatable="false" />

    <!-- The scale factor to be applied for external vibrations only (i.e. audio-coupled haptics),
         defined by a positive float value.
         The values from config_vibrationIntensityScaleFactors will be used if this is not set.
         The number of entries here must be the device supported scale levels for LOW/MEDIUM/HIGH.
         Example:
         <string-array name="config_externalVibrationIntensityScaleFactors" translatable="false">
           <item>0.3</item> -> Vibrator.VIBRATION_INTENSITY_LOW
           <item>0.5</item> -> Vibrator.VIBRATION_INTENSITY_MEDIUM
           <item>1.0</item> -> Vibrator.VIBRATION_INTENSITY_HIGH
         </string-array> -->
    <string-array name="config_externalVibrationIntensityScaleFactors" translatable="false" />

    <!-- The max vibration strength allowed in audio haptic channels, must be positive or zero if
         limit is unknown. -->
    <item name="config_hapticChannelMaxVibrationAmplitude" format="float" type="dimen">0</item>
Loading