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

Commit fa6eac33 authored by Ahmad Khalil's avatar Ahmad Khalil
Browse files

Adding the ability to pull vibration params before playing vibration

Vibrations that don't have strong latency requirements, e.g. ringtone and notification, will request vibration params before they get played.
The received params will be cached in the VibrationScaler and used to scale these vibrations. If the request times out, any previously cached vibration params will be used for scaling.

Bug: 305939448
Bug: 305961303
Test: atest FrameworksVibratorServicesTests
Change-Id: I085d8b238dbde4ff2f068d5e15eeb08b7a5381d3
parent 03823b64
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.os.Vibrator.VibrationIntensity;
import android.util.IndentingPrintWriter;

import java.io.PrintWriter;
import java.util.Arrays;

/**
 * List of device-specific internal vibration configuration loaded from platform config.xml.
@@ -51,6 +52,8 @@ public class VibrationConfig {
    private final float mHapticChannelMaxVibrationAmplitude;
    private final int mRampStepDurationMs;
    private final int mRampDownDurationMs;
    private final int mRequestVibrationParamsTimeoutMs;
    private final int[] mRequestVibrationParamsForUsages;

    private final boolean mIgnoreVibrationsOnWirelessCharger;

@@ -75,6 +78,10 @@ public class VibrationConfig {
                com.android.internal.R.integer.config_vibrationWaveformRampDownDuration, 0);
        mRampStepDurationMs = loadInteger(resources,
                com.android.internal.R.integer.config_vibrationWaveformRampStepDuration, 0);
        mRequestVibrationParamsTimeoutMs = loadInteger(resources,
                com.android.internal.R.integer.config_requestVibrationParamsTimeout, 0);
        mRequestVibrationParamsForUsages = loadIntArray(resources,
                com.android.internal.R.array.config_requestVibrationParamsForUsages);

        mIgnoreVibrationsOnWirelessCharger = loadBoolean(resources,
                com.android.internal.R.bool.config_ignoreVibrationsOnWirelessCharger, false);
@@ -115,6 +122,10 @@ public class VibrationConfig {
        return res != null ? res.getBoolean(resId) : defaultValue;
    }

    private static int[] loadIntArray(@Nullable Resources res, int resId) {
        return res != null ? res.getIntArray(resId) : new int[0];
    }

    /**
     * Return the maximum amplitude the vibrator can play using the audio haptic channels.
     *
@@ -139,6 +150,23 @@ public class VibrationConfig {
        return mRampDownDurationMs;
    }

    /**
     * The duration, in milliseconds, that the vibrator control service will wait for new
     * vibration params.
     */
    public int getRequestVibrationParamsTimeoutMs() {
        return Math.max(mRequestVibrationParamsTimeoutMs, 0);
    }

    /**
     * The list of usages that should request vibration params before they are played. These
     * usages don't have strong latency requirements, e.g. ringtone and notification, and can be
     * slightly delayed.
     */
    public int[] getRequestVibrationParamsForUsages() {
        return mRequestVibrationParamsForUsages;
    }

    /**
     * The duration, in milliseconds, that should be applied to convert vibration effect's
     * {@link android.os.vibrator.RampSegment} to a {@link android.os.vibrator.StepSegment} on
@@ -204,6 +232,9 @@ public class VibrationConfig {
                + ", mDefaultMediaIntensity=" + mDefaultMediaVibrationIntensity
                + ", mDefaultNotificationIntensity=" + mDefaultNotificationVibrationIntensity
                + ", mDefaultRingIntensity=" + mDefaultRingVibrationIntensity
                + ", mRequestVibrationParamsTimeoutMs=" + mRequestVibrationParamsTimeoutMs
                + ", mRequestVibrationParamsForUsages=" + Arrays.toString(
                getRequestVibrationParamsForUsagesNames())
                + "}";
    }

@@ -220,4 +251,14 @@ public class VibrationConfig {
        pw.println("rampDownDurationMs = " + mRampDownDurationMs);
        pw.decreaseIndent();
    }

    private String[] getRequestVibrationParamsForUsagesNames() {
        int usagesCount = mRequestVibrationParamsForUsages.length;
        String[] names = new String[usagesCount];
        for (int i = 0; i < usagesCount; i++) {
            names[i] = VibrationAttributes.usageToString(mRequestVibrationParamsForUsages[i]);
        }

        return names;
    }
}
+14 −0
Original line number Diff line number Diff line
@@ -281,6 +281,20 @@
         when there's no network connection. If the scan doesn't timeout, use zero -->
    <integer name="config_radioScanningTimeout">0</integer>

    <!-- The duration (in milliseconds) that the vibrator control service will wait for new
         vibration params. -->
    <integer name="config_requestVibrationParamsTimeout">50</integer>

    <!-- Array containing the usages that should request vibration params before they are played.
         These usages don't have strong latency requirements, e.g. ringtone and notification, and
         can be slightly delayed. -->
    <integer-array name="config_requestVibrationParamsForUsages">
        <item>17</item> <!-- USAGE_ALARM -->
        <item>33</item> <!-- USAGE_RINGTONE -->
        <item>49</item> <!-- USAGE_NOTIFICATION -->
        <item>65</item> <!-- USAGE_COMMUNICATION_REQUEST -->
    </integer-array>

    <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
         Please don't copy them, copy anything else. -->

+2 −0
Original line number Diff line number Diff line
@@ -2080,6 +2080,8 @@
  <java-symbol type="bool" name="config_ignoreVibrationsOnWirelessCharger" />
  <java-symbol type="integer" name="config_vibrationWaveformRampDownDuration" />
  <java-symbol type="integer" name="config_radioScanningTimeout" />
  <java-symbol type="integer" name="config_requestVibrationParamsTimeout" />
  <java-symbol type="array" name="config_requestVibrationParamsForUsages" />
  <java-symbol type="integer" name="config_screenBrightnessSettingMinimum" />
  <java-symbol type="integer" name="config_screenBrightnessSettingMaximum" />
  <java-symbol type="integer" name="config_screenBrightnessSettingDefault" />
+29 −8
Original line number Diff line number Diff line
@@ -17,10 +17,10 @@
package com.android.server.vibrator;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.vibrator.V1_0.EffectStrength;
import android.os.IExternalVibratorService;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.os.vibrator.Flags;
@@ -57,8 +57,7 @@ final class VibrationScaler {
    private final SparseArray<ScaleLevel> mScaleLevels;
    private final VibrationSettings mSettingsController;
    private final int mDefaultVibrationAmplitude;

    private SparseArray<Float> mAdaptiveHapticsScales;
    private final SparseArray<Float> mAdaptiveHapticsScales = new SparseArray<>();

    VibrationScaler(Context context, VibrationSettings settingsController) {
        mSettingsController = settingsController;
@@ -147,7 +146,7 @@ final class VibrationScaler {

            // If adaptive haptics scaling is available for this usage, apply it to the segment.
            if (Flags.adaptiveHapticsEnabled()
                    && mAdaptiveHapticsScales != null && mAdaptiveHapticsScales.size() > 0
                    && mAdaptiveHapticsScales.size() > 0
                    && mAdaptiveHapticsScales.contains(usageHint)) {
                float adaptiveScale = mAdaptiveHapticsScales.get(usageHint);
                segment = segment.scale(adaptiveScale);
@@ -187,13 +186,35 @@ final class VibrationScaler {
    }

    /**
     * Updates the adaptive haptics scales.
     * @param scales the new vibration scales to apply.
     * Updates the adaptive haptics scales list by adding or modifying the scale for this usage.
     *
     * @param usageHint one of VibrationAttributes.USAGE_*.
     * @param scale The scaling factor that should be applied to vibrations of this usage.
     *
     * @hide
     */
    public void updateAdaptiveHapticsScale(@VibrationAttributes.Usage int usageHint, float scale) {
        mAdaptiveHapticsScales.put(usageHint, scale);
    }

    /**
     * Removes the usage from the cached adaptive haptics scales list.
     *
     * @param usageHint one of VibrationAttributes.USAGE_*.
     *
     * @hide
     */
    public void removeAdaptiveHapticsScale(@VibrationAttributes.Usage int usageHint) {
        mAdaptiveHapticsScales.remove(usageHint);
    }

    /**
     * Removes all cached adaptive haptics scales.
     *
     * @hide
     */
    public void updateAdaptiveHapticsScales(@Nullable SparseArray<Float> scales) {
        mAdaptiveHapticsScales = scales;
    public void clearAdaptiveHapticsScales() {
        mAdaptiveHapticsScales.clear();
    }

    /** Mapping of Vibrator.VIBRATION_INTENSITY_* values to {@link EffectStrength}. */
+19 −0
Original line number Diff line number Diff line
@@ -375,6 +375,25 @@ final class VibrationSettings {
        }
    }

    /**
     * Returns the duration, in milliseconds, that the vibrator control service will wait for new
     * vibration params.
     * @return The request vibration params timeout in milliseconds.
     * @hide
     */
    public int getRequestVibrationParamsTimeoutMs() {
        return mVibrationConfig.getRequestVibrationParamsTimeoutMs();
    }

    /**
     * The list of usages that should request vibration params before they are played. These
     * usages don't have strong latency requirements, e.g. ringtone and notification, and can be
     * slightly delayed.
     */
    public int[] getRequestVibrationParamsForUsages() {
        return mVibrationConfig.getRequestVibrationParamsForUsages();
    }

    /**
     * Return a {@link VibrationEffect} that should be played if the device do not support given
     * {@code effectId}.
Loading