diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 0710781a31556..6586ae044d161 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -1822,9 +1822,9 @@ package android.os { public static final class VibrationEffect.WaveformBuilder { method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int); - method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=-1.0F, to=1.0f) float, @IntRange(from=0) int); + method @NonNull public android.os.VibrationEffect.WaveformBuilder addRamp(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=1.0f) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int); - method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=-1.0F, to=1.0f) float, @IntRange(from=0) int); + method @NonNull public android.os.VibrationEffect.WaveformBuilder addStep(@FloatRange(from=0.0f, to=1.0f) float, @FloatRange(from=1.0f) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect build(); method @NonNull public android.os.VibrationEffect build(int); } @@ -1982,9 +1982,9 @@ package android.os.vibrator { method public int describeContents(); method public long getDuration(); method public float getEndAmplitude(); - method public float getEndFrequency(); + method public float getEndFrequencyHz(); method public float getStartAmplitude(); - method public float getStartFrequency(); + method public float getStartFrequencyHz(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; } @@ -1993,7 +1993,7 @@ package android.os.vibrator { method public int describeContents(); method public float getAmplitude(); method public long getDuration(); - method public float getFrequency(); + method public float getFrequencyHz(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; } diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index 41ab062ee8220..ae37a714e0c8f 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -260,7 +260,7 @@ public abstract class VibrationEffect implements Parcelable { for (int i = 0; i < timings.length; i++) { float parsedAmplitude = amplitudes[i] == DEFAULT_AMPLITUDE ? DEFAULT_AMPLITUDE : (float) amplitudes[i] / MAX_AMPLITUDE; - segments.add(new StepSegment(parsedAmplitude, /* frequency= */ 0, (int) timings[i])); + segments.add(new StepSegment(parsedAmplitude, /* frequencyHz= */ 0, (int) timings[i])); } VibrationEffect effect = new Composed(segments, repeat); effect.validate(); @@ -866,7 +866,7 @@ public abstract class VibrationEffect implements Parcelable { Preconditions.checkArgumentNonnegative(delay); if (delay > 0) { // Created a segment sustaining the zero amplitude to represent the delay. - addSegment(new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, + addSegment(new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ delay)); } return addSegments(effect); @@ -1033,26 +1033,27 @@ public abstract class VibrationEffect implements Parcelable { @NonNull public WaveformBuilder addStep(@FloatRange(from = 0f, to = 1f) float amplitude, @IntRange(from = 0) int duration) { - return addStep(amplitude, getPreviousFrequency(), duration); + mSegments.add(new StepSegment(amplitude, getPreviousFrequencyHz(), duration)); + return this; } /** - * Vibrate with given amplitude for the given duration, in millis, keeping the previous - * vibration frequency the same. + * Vibrate with given amplitude and frequency for the given duration, in millis. * *

If the duration is zero the vibrator will jump to new amplitude. * * @param amplitude The amplitude for this step - * @param frequency The frequency for this step + * @param frequencyHz The frequency for this step, in hertz * @param duration The duration of this step in milliseconds * @return The {@link WaveformBuilder} object to enable adding multiple steps in chain. */ @SuppressLint("MissingGetterMatchingBuilder") @NonNull public WaveformBuilder addStep(@FloatRange(from = 0f, to = 1f) float amplitude, - @FloatRange(from = -1f, to = 1f) float frequency, + @FloatRange(from = 1f) float frequencyHz, @IntRange(from = 0) int duration) { - mSegments.add(new StepSegment(amplitude, frequency, duration)); + Preconditions.checkArgument(frequencyHz >= 1, "Frequency must be >= 1"); + mSegments.add(new StepSegment(amplitude, frequencyHz, duration)); return this; } @@ -1070,7 +1071,9 @@ public abstract class VibrationEffect implements Parcelable { @NonNull public WaveformBuilder addRamp(@FloatRange(from = 0f, to = 1f) float amplitude, @IntRange(from = 0) int duration) { - return addRamp(amplitude, getPreviousFrequency(), duration); + mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude, + getPreviousFrequencyHz(), getPreviousFrequencyHz(), duration)); + return this; } /** @@ -1080,22 +1083,23 @@ public abstract class VibrationEffect implements Parcelable { *

If the duration is zero the vibrator will jump to new amplitude and frequency. * * @param amplitude The final amplitude this ramp should reach - * @param frequency The final frequency this ramp should reach + * @param frequencyHz The final frequency this ramp should reach, in hertz * @param duration The duration of this ramp in milliseconds * @return The {@link WaveformBuilder} object to enable adding multiple steps in chain. */ @SuppressLint("MissingGetterMatchingBuilder") @NonNull public WaveformBuilder addRamp(@FloatRange(from = 0f, to = 1f) float amplitude, - @FloatRange(from = -1f, to = 1f) float frequency, + @FloatRange(from = 1f) float frequencyHz, @IntRange(from = 0) int duration) { - mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude, getPreviousFrequency(), - frequency, duration)); + Preconditions.checkArgument(frequencyHz >= 1, "Frequency must be >= 1"); + mSegments.add(new RampSegment(getPreviousAmplitude(), amplitude, + getPreviousFrequencyHz(), frequencyHz, duration)); return this; } /** - * Compose all of the steps together into a single {@link VibrationEffect}. + * Compose all the steps together into a single {@link VibrationEffect}. * * The {@link WaveformBuilder} object is still valid after this call, so you can * continue adding more primitives to it and generating more {@link VibrationEffect}s by @@ -1109,7 +1113,7 @@ public abstract class VibrationEffect implements Parcelable { } /** - * Compose all of the steps together into a single {@link VibrationEffect}. + * Compose all the steps together into a single {@link VibrationEffect}. * *

To cause the pattern to repeat, pass the index at which to start the repetition * (starting at 0), or -1 to disable repeating. @@ -1131,13 +1135,13 @@ public abstract class VibrationEffect implements Parcelable { return effect; } - private float getPreviousFrequency() { + private float getPreviousFrequencyHz() { if (!mSegments.isEmpty()) { VibrationEffectSegment segment = mSegments.get(mSegments.size() - 1); if (segment instanceof StepSegment) { - return ((StepSegment) segment).getFrequency(); + return ((StepSegment) segment).getFrequencyHz(); } else if (segment instanceof RampSegment) { - return ((RampSegment) segment).getEndFrequency(); + return ((RampSegment) segment).getEndFrequencyHz(); } } return 0; diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java index c67c82e37cd2b..d71ead724f7a3 100644 --- a/core/java/android/os/Vibrator.java +++ b/core/java/android/os/Vibrator.java @@ -17,7 +17,6 @@ package android.os; import android.annotation.CallbackExecutor; -import android.annotation.FloatRange; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -30,7 +29,6 @@ import android.content.Context; import android.hardware.vibrator.IVibrator; import android.media.AudioAttributes; import android.util.Log; -import android.util.Range; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -270,43 +268,6 @@ public abstract class Vibrator { return getInfo().getQFactor(); } - /** - * Return a range of relative frequency values supported by the vibrator. - * - *

These values can be used to create waveforms that controls the vibration frequency via - * {@link VibrationEffect.WaveformBuilder}. - * - * @return A range of relative frequency values supported. The range will always contain the - * value 0, representing the device resonant frequency. Devices without frequency control will - * return the range [0,0]. Devices with frequency control will always return a range containing - * the safe range [-1, 1]. - * @hide - */ - public Range getRelativeFrequencyRange() { - return getInfo().getFrequencyRange(); - } - - /** - * Return the maximum amplitude the vibrator can play at given relative frequency. - * - *

Devices without frequency control will return 1 for the input zero (resonant frequency), - * and 0 to any other input. - * - *

Devices with frequency control will return the supported value, for input in - * {@link #getRelativeFrequencyRange()}, and 0 for any other input. - * - *

These values can be used to create waveforms that plays vibrations outside the resonant - * frequency via {@link VibrationEffect.WaveformBuilder}. - * - * @return a value in [0,1] representing the maximum amplitude the device can play at given - * relative frequency. - * @hide - */ - @FloatRange(from = 0, to = 1) - public float getMaximumAmplitude(float relativeFrequency) { - return getInfo().getMaxAmplitude(relativeFrequency); - } - /** * Return the maximum amplitude the vibrator can play using the audio haptic channels. * diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java index 0a0e3c82f4ad7..5271c4df11ef0 100644 --- a/core/java/android/os/VibratorInfo.java +++ b/core/java/android/os/VibratorInfo.java @@ -21,7 +21,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.hardware.vibrator.Braking; import android.hardware.vibrator.IVibrator; -import android.util.Log; import android.util.MathUtils; import android.util.Range; import android.util.SparseBooleanArray; @@ -345,49 +344,31 @@ public class VibratorInfo implements Parcelable { } /** - * Return a range of relative frequency values supported by the vibrator. + * Return a range of frequency values supported by the vibrator. * - * @return A range of relative frequency values supported. The range will always contain the - * value 0, representing the device resonant frequency. Devices without frequency control will - * return the range [0,0]. Devices with frequency control will always return a range containing - * the safe range [-1, 1]. + * @return A range of frequency values supported, in hertz. The range will always contain the + * device resonant frequency. Devices without frequency control will return null. * @hide */ - public Range getFrequencyRange() { - return mFrequencyMapping.mRelativeFrequencyRange; + @Nullable + public Range getFrequencyRangeHz() { + return mFrequencyMapping.mFrequencyRangeHz; } /** - * Return the maximum amplitude the vibrator can play at given relative frequency. + * Return the maximum amplitude the vibrator can play at given frequency. * + * @param frequencyHz The frequency, in hertz, for query. + * @return a value in [0,1] representing the maximum amplitude the device can play at given - * relative frequency. Devices without frequency control will return 1 for the input zero - * (resonant frequency), and 0 to any other input. Devices with frequency control will return - * the supported value, for input in {@code #getFrequencyRange()}, and 0 for any other input. + * frequency. Devices without frequency control will return 0 to any input. Devices with + * frequency control will return the supported value, for input in + * {@link #getFrequencyRangeHz()}, and 0 for any other input. * @hide */ @FloatRange(from = 0, to = 1) - public float getMaxAmplitude(float relativeFrequency) { - if (mFrequencyMapping.isEmpty()) { - // The vibrator has not provided values for frequency mapping. - // Return the expected behavior for devices without frequency control. - return Float.compare(relativeFrequency, 0) == 0 ? 1 : 0; - } - return mFrequencyMapping.getMaxAmplitude(relativeFrequency); - } - - /** - * Return absolute frequency value for this vibrator, in hertz, that corresponds to given - * relative frequency. - * - * @retur a value in hertz that corresponds to given relative frequency. Input values outside - * {@link #getFrequencyRange()} will return {@link Float#NaN}. Devices without frequency control - * will return {@link Float#NaN} for any input. - * @hide - */ - @FloatRange(from = 0) - public float getAbsoluteFrequency(float relativeFrequency) { - return mFrequencyMapping.toHertz(relativeFrequency); + public float getMaxAmplitude(float frequencyHz) { + return mFrequencyMapping.getMaxAmplitude(frequencyHz); } protected long getCapabilities() { @@ -468,134 +449,96 @@ public class VibratorInfo implements Parcelable { } /** - * Describes how frequency should be mapped to absolute values for a specific {@link Vibrator}. + * Describes the maximum relative output acceleration that can be achieved for each supported + * frequency in a specific vibrator. * *

This mapping is defined by the following parameters: * *

    - *
  1. {@code minFrequency}, {@code resonantFrequency} and {@code frequencyResolution}, in - * hertz, provided by the vibrator. + *
  2. {@code minFrequencyHz}, {@code resonantFrequencyHz} and {@code frequencyResolutionHz} + * provided by the vibrator in hertz. *
  3. {@code maxAmplitudes} a list of values in [0,1] provided by the vibrator, where * {@code maxAmplitudes[i]} represents max supported amplitude at frequency - * {@code minFrequency + frequencyResolution * i}. - *
  4. {@code maxFrequency = minFrequency + frequencyResolution * (maxAmplitudes.length-1)} - *
  5. {@code suggestedSafeRangeHz} is the suggested frequency range in hertz that should be - * mapped to relative values -1 and 1, where 0 maps to {@code resonantFrequency}. - *
- * - *

The mapping is defined linearly by the following points: - * - *

    - *
  1. {@code toHertz(relativeMinFrequency) = minFrequency} - *
  2. {@code toHertz(-1) = resonantFrequency - safeRange / 2} - *
  3. {@code toHertz(0) = resonantFrequency} - *
  4. {@code toHertz(1) = resonantFrequency + safeRange / 2} - *
  5. {@code toHertz(relativeMaxFrequency) = maxFrequency} + * {@code minFrequencyHz + frequencyResolutionHz * i}. + *
  6. {@code maxFrequencyHz = minFrequencyHz + * + frequencyResolutionHz * (maxAmplitudes.length-1)} *
* * @hide */ public static final class FrequencyMapping implements Parcelable { + @Nullable + private final Range mFrequencyRangeHz; private final float mMinFrequencyHz; private final float mResonantFrequencyHz; private final float mFrequencyResolutionHz; - private final float mSuggestedSafeRangeHz; private final float[] mMaxAmplitudes; - // Relative fields calculated from input values: - private final Range mRelativeFrequencyRange; - FrequencyMapping(Parcel in) { - this(in.readFloat(), in.readFloat(), in.readFloat(), in.readFloat(), - in.createFloatArray()); + this(in.readFloat(), in.readFloat(), in.readFloat(), in.createFloatArray()); } /** * Default constructor. * - * @param minFrequencyHz Minimum supported frequency, in hertz. * @param resonantFrequencyHz The vibrator resonant frequency, in hertz. + * @param minFrequencyHz Minimum supported frequency, in hertz. * @param frequencyResolutionHz The frequency resolution, in hertz, used by the max * amplitudes mapping. - * @param suggestedSafeRangeHz The suggested range, in hertz, for the safe relative - * frequency range represented by [-1, 1]. * @param maxAmplitudes The max amplitude supported by each supported frequency, * starting at minimum frequency with jumps of frequency * resolution. * @hide */ - public FrequencyMapping(float minFrequencyHz, float resonantFrequencyHz, - float frequencyResolutionHz, float suggestedSafeRangeHz, float[] maxAmplitudes) { + public FrequencyMapping(float resonantFrequencyHz, float minFrequencyHz, + float frequencyResolutionHz, float[] maxAmplitudes) { mMinFrequencyHz = minFrequencyHz; mResonantFrequencyHz = resonantFrequencyHz; mFrequencyResolutionHz = frequencyResolutionHz; - mSuggestedSafeRangeHz = suggestedSafeRangeHz; mMaxAmplitudes = new float[maxAmplitudes == null ? 0 : maxAmplitudes.length]; if (maxAmplitudes != null) { System.arraycopy(maxAmplitudes, 0, mMaxAmplitudes, 0, maxAmplitudes.length); } - float maxFrequencyHz = - minFrequencyHz + frequencyResolutionHz * (mMaxAmplitudes.length - 1); - if (Float.isNaN(resonantFrequencyHz) || Float.isNaN(minFrequencyHz) - || Float.isNaN(frequencyResolutionHz) || Float.isNaN(suggestedSafeRangeHz) - || resonantFrequencyHz < minFrequencyHz - || resonantFrequencyHz > maxFrequencyHz) { - // Some required fields are undefined or have bad values. - // Leave this mapping empty. - mRelativeFrequencyRange = Range.create(0f, 0f); - return; - } + // If any required field is undefined then leave this mapping empty. + boolean isValid = !Float.isNaN(resonantFrequencyHz) + && !Float.isNaN(minFrequencyHz) + && !Float.isNaN(frequencyResolutionHz) + && (mMaxAmplitudes.length > 0); - // Calculate actual safe range, limiting the suggested one by the device supported range - float safeDelta = MathUtils.min( - suggestedSafeRangeHz / 2, - resonantFrequencyHz - minFrequencyHz, - maxFrequencyHz - resonantFrequencyHz); - mRelativeFrequencyRange = Range.create( - (minFrequencyHz - resonantFrequencyHz) / safeDelta, - (maxFrequencyHz - resonantFrequencyHz) / safeDelta); + float maxFrequencyHz = isValid + ? minFrequencyHz + frequencyResolutionHz * (mMaxAmplitudes.length - 1) + : Float.NaN; + + // If the non-empty mapping does not have min < resonant < max frequency respected + // then leave this mapping empty. + isValid &= !Float.isNaN(maxFrequencyHz) + && (resonantFrequencyHz >= minFrequencyHz) + && (resonantFrequencyHz <= maxFrequencyHz) + && (minFrequencyHz < maxFrequencyHz); + + mFrequencyRangeHz = isValid ? Range.create(minFrequencyHz, maxFrequencyHz) : null; } /** - * Returns true if this frequency mapping is empty, i.e. the only supported relative - * frequency is 0 (resonant frequency). + * Returns true if this frequency mapping is empty, i.e. the only supported is the resonant + * frequency. */ public boolean isEmpty() { - return Float.compare(mRelativeFrequencyRange.getLower(), - mRelativeFrequencyRange.getUpper()) == 0; + return mFrequencyRangeHz == null; } /** - * Returns the frequency value in hertz that is mapped to the given relative frequency. + * Returns the maximum relative amplitude the vibrator can reach while playing at the + * given frequency. * - * @return The mapped frequency, in hertz, or {@link Float#NaN} is value outside the device - * supported range. + * @param frequencyHz frequency, in hertz, for query. + * @return A value in [0,1] representing the max relative amplitude supported at the given + * frequency. This will return 0 if the frequency is outside the supported range, or if the + * mapping is empty. */ - public float toHertz(float relativeFrequency) { - if (!mRelativeFrequencyRange.contains(relativeFrequency)) { - return Float.NaN; - } - float relativeMinFrequency = mRelativeFrequencyRange.getLower(); - if (Float.compare(relativeMinFrequency, 0) == 0) { - // relative supported range is [0,0], so toHertz(0) should be the resonant frequency - return mResonantFrequencyHz; - } - float shift = (mMinFrequencyHz - mResonantFrequencyHz) / relativeMinFrequency; - return mResonantFrequencyHz + relativeFrequency * shift; - } - - /** - * Returns the maximum amplitude the vibrator can reach while playing at given relative - * frequency. - * - * @return A value in [0,1] representing the max amplitude supported at given relative - * frequency. This will return 0 if frequency is outside supported range, or if max - * amplitude mapping is empty. - */ - public float getMaxAmplitude(float relativeFrequency) { - float frequencyHz = toHertz(relativeFrequency); - if (Float.isNaN(frequencyHz)) { + public float getMaxAmplitude(float frequencyHz) { + if (isEmpty() || Float.isNaN(frequencyHz)) { // Unsupported frequency requested, vibrator cannot play at this frequency. return 0; } @@ -603,13 +546,6 @@ public class VibratorInfo implements Parcelable { int floorIndex = (int) Math.floor(position); int ceilIndex = (int) Math.ceil(position); if (floorIndex < 0 || floorIndex >= mMaxAmplitudes.length) { - if (mMaxAmplitudes.length > 0) { - // This should never happen if the setup of relative frequencies was correct. - Log.w(TAG, "Max amplitudes has " + mMaxAmplitudes.length - + " entries and was expected to cover the frequency " + frequencyHz - + " Hz when starting at min frequency of " + mMinFrequencyHz - + " Hz with resolution of " + mFrequencyResolutionHz + " Hz."); - } return 0; } if (floorIndex != ceilIndex && ceilIndex < mMaxAmplitudes.length) { @@ -621,10 +557,9 @@ public class VibratorInfo implements Parcelable { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeFloat(mMinFrequencyHz); dest.writeFloat(mResonantFrequencyHz); + dest.writeFloat(mMinFrequencyHz); dest.writeFloat(mFrequencyResolutionHz); - dest.writeFloat(mSuggestedSafeRangeHz); dest.writeFloatArray(mMaxAmplitudes); } @@ -645,14 +580,13 @@ public class VibratorInfo implements Parcelable { return Float.compare(mMinFrequencyHz, that.mMinFrequencyHz) == 0 && Float.compare(mResonantFrequencyHz, that.mResonantFrequencyHz) == 0 && Float.compare(mFrequencyResolutionHz, that.mFrequencyResolutionHz) == 0 - && Float.compare(mSuggestedSafeRangeHz, that.mSuggestedSafeRangeHz) == 0 && Arrays.equals(mMaxAmplitudes, that.mMaxAmplitudes); } @Override public int hashCode() { int hashCode = Objects.hash(mMinFrequencyHz, mFrequencyResolutionHz, - mFrequencyResolutionHz, mSuggestedSafeRangeHz); + mFrequencyResolutionHz); hashCode = 31 * hashCode + Arrays.hashCode(mMaxAmplitudes); return hashCode; } @@ -660,13 +594,10 @@ public class VibratorInfo implements Parcelable { @Override public String toString() { return "FrequencyMapping{" - + "mRelativeFrequencyRange=" + mRelativeFrequencyRange + + "mFrequencyRange=" + mFrequencyRangeHz + ", mMinFrequency=" + mMinFrequencyHz + ", mResonantFrequency=" + mResonantFrequencyHz - + ", mMaxFrequency=" - + (mMinFrequencyHz + mFrequencyResolutionHz * (mMaxAmplitudes.length - 1)) + ", mFrequencyResolution=" + mFrequencyResolutionHz - + ", mSuggestedSafeRange=" + mSuggestedSafeRangeHz + ", mMaxAmplitudes count=" + mMaxAmplitudes.length + '}'; } @@ -699,7 +630,7 @@ public class VibratorInfo implements Parcelable { private int mPwleSizeMax; private float mQFactor = Float.NaN; private FrequencyMapping mFrequencyMapping = - new FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null); + new FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, null); /** A builder class for a {@link VibratorInfo}. */ public Builder(int id) { diff --git a/core/java/android/os/vibrator/RampSegment.java b/core/java/android/os/vibrator/RampSegment.java index 3ec56366d9215..9e1f6360b0909 100644 --- a/core/java/android/os/vibrator/RampSegment.java +++ b/core/java/android/os/vibrator/RampSegment.java @@ -29,14 +29,20 @@ import java.util.Objects; * Representation of {@link VibrationEffectSegment} that ramps vibration amplitude and/or frequency * for a specified duration. * + *

The amplitudes are expressed by float values in the range [0, 1], representing the relative + * output acceleration for the vibrator. The frequencies are expressed in hertz by positive finite + * float values. The special value zero is used here for an unspecified frequency, and will be + * automatically mapped to the device's default vibration frequency (usually the resonant + * frequency). + * * @hide */ @TestApi public final class RampSegment extends VibrationEffectSegment { private final float mStartAmplitude; - private final float mStartFrequency; + private final float mStartFrequencyHz; private final float mEndAmplitude; - private final float mEndFrequency; + private final float mEndFrequencyHz; private final int mDuration; RampSegment(@NonNull Parcel in) { @@ -44,12 +50,12 @@ public final class RampSegment extends VibrationEffectSegment { } /** @hide */ - public RampSegment(float startAmplitude, float endAmplitude, float startFrequency, - float endFrequency, int duration) { + public RampSegment(float startAmplitude, float endAmplitude, float startFrequencyHz, + float endFrequencyHz, int duration) { mStartAmplitude = startAmplitude; mEndAmplitude = endAmplitude; - mStartFrequency = startFrequency; - mEndFrequency = endFrequency; + mStartFrequencyHz = startFrequencyHz; + mEndFrequencyHz = endFrequencyHz; mDuration = duration; } @@ -61,8 +67,8 @@ public final class RampSegment extends VibrationEffectSegment { RampSegment other = (RampSegment) o; return Float.compare(mStartAmplitude, other.mStartAmplitude) == 0 && Float.compare(mEndAmplitude, other.mEndAmplitude) == 0 - && Float.compare(mStartFrequency, other.mStartFrequency) == 0 - && Float.compare(mEndFrequency, other.mEndFrequency) == 0 + && Float.compare(mStartFrequencyHz, other.mStartFrequencyHz) == 0 + && Float.compare(mEndFrequencyHz, other.mEndFrequencyHz) == 0 && mDuration == other.mDuration; } @@ -74,12 +80,12 @@ public final class RampSegment extends VibrationEffectSegment { return mEndAmplitude; } - public float getStartFrequency() { - return mStartFrequency; + public float getStartFrequencyHz() { + return mStartFrequencyHz; } - public float getEndFrequency() { - return mEndFrequency; + public float getEndFrequencyHz() { + return mEndFrequencyHz; } @Override @@ -102,6 +108,12 @@ public final class RampSegment extends VibrationEffectSegment { /** @hide */ @Override public void validate() { + Preconditions.checkArgumentNonNegative(mStartFrequencyHz, + "Frequencies must all be >= 0, got start frequency of " + mStartFrequencyHz); + Preconditions.checkArgumentFinite(mStartFrequencyHz, "startFrequencyHz"); + Preconditions.checkArgumentNonNegative(mEndFrequencyHz, + "Frequencies must all be >= 0, got end frequency of " + mEndFrequencyHz); + Preconditions.checkArgumentFinite(mEndFrequencyHz, "endFrequencyHz"); Preconditions.checkArgumentNonnegative(mDuration, "Durations must all be >= 0, got " + mDuration); Preconditions.checkArgumentInRange(mStartAmplitude, 0f, 1f, "startAmplitude"); @@ -126,7 +138,8 @@ public final class RampSegment extends VibrationEffectSegment { && Float.compare(mEndAmplitude, newEndAmplitude) == 0) { return this; } - return new RampSegment(newStartAmplitude, newEndAmplitude, mStartFrequency, mEndFrequency, + return new RampSegment(newStartAmplitude, newEndAmplitude, mStartFrequencyHz, + mEndFrequencyHz, mDuration); } @@ -139,7 +152,7 @@ public final class RampSegment extends VibrationEffectSegment { @Override public int hashCode() { - return Objects.hash(mStartAmplitude, mEndAmplitude, mStartFrequency, mEndFrequency, + return Objects.hash(mStartAmplitude, mEndAmplitude, mStartFrequencyHz, mEndFrequencyHz, mDuration); } @@ -147,8 +160,8 @@ public final class RampSegment extends VibrationEffectSegment { public String toString() { return "Ramp{startAmplitude=" + mStartAmplitude + ", endAmplitude=" + mEndAmplitude - + ", startFrequency=" + mStartFrequency - + ", endFrequency=" + mEndFrequency + + ", startFrequencyHz=" + mStartFrequencyHz + + ", endFrequencyHz=" + mEndFrequencyHz + ", duration=" + mDuration + "}"; } @@ -163,8 +176,8 @@ public final class RampSegment extends VibrationEffectSegment { out.writeInt(PARCEL_TOKEN_RAMP); out.writeFloat(mStartAmplitude); out.writeFloat(mEndAmplitude); - out.writeFloat(mStartFrequency); - out.writeFloat(mEndFrequency); + out.writeFloat(mStartFrequencyHz); + out.writeFloat(mEndFrequencyHz); out.writeInt(mDuration); } diff --git a/core/java/android/os/vibrator/StepSegment.java b/core/java/android/os/vibrator/StepSegment.java index 69a381f5c558d..c6795111d4961 100644 --- a/core/java/android/os/vibrator/StepSegment.java +++ b/core/java/android/os/vibrator/StepSegment.java @@ -30,12 +30,18 @@ import java.util.Objects; * Representation of {@link VibrationEffectSegment} that holds a fixed vibration amplitude and * frequency for a specified duration. * + *

The amplitude is expressed by a float value in the range [0, 1], representing the relative + * output acceleration for the vibrator. The frequency is expressed in hertz by a positive finite + * float value. The special value zero is used here for an unspecified frequency, and will be + * automatically mapped to the device's default vibration frequency (usually the resonant + * frequency). + * * @hide */ @TestApi public final class StepSegment extends VibrationEffectSegment { private final float mAmplitude; - private final float mFrequency; + private final float mFrequencyHz; private final int mDuration; StepSegment(@NonNull Parcel in) { @@ -43,9 +49,9 @@ public final class StepSegment extends VibrationEffectSegment { } /** @hide */ - public StepSegment(float amplitude, float frequency, int duration) { + public StepSegment(float amplitude, float frequencyHz, int duration) { mAmplitude = amplitude; - mFrequency = frequency; + mFrequencyHz = frequencyHz; mDuration = duration; } @@ -56,7 +62,7 @@ public final class StepSegment extends VibrationEffectSegment { } StepSegment other = (StepSegment) o; return Float.compare(mAmplitude, other.mAmplitude) == 0 - && Float.compare(mFrequency, other.mFrequency) == 0 + && Float.compare(mFrequencyHz, other.mFrequencyHz) == 0 && mDuration == other.mDuration; } @@ -64,8 +70,8 @@ public final class StepSegment extends VibrationEffectSegment { return mAmplitude; } - public float getFrequency() { - return mFrequency; + public float getFrequencyHz() { + return mFrequencyHz; } @Override @@ -89,6 +95,9 @@ public final class StepSegment extends VibrationEffectSegment { /** @hide */ @Override public void validate() { + Preconditions.checkArgumentNonNegative(mFrequencyHz, + "Frequencies must all be >= 0, got " + mFrequencyHz); + Preconditions.checkArgumentFinite(mFrequencyHz, "frequencyHz"); Preconditions.checkArgumentNonnegative(mDuration, "Durations must all be >= 0, got " + mDuration); if (Float.compare(mAmplitude, VibrationEffect.DEFAULT_AMPLITUDE) != 0) { @@ -108,7 +117,8 @@ public final class StepSegment extends VibrationEffectSegment { if (Float.compare(mAmplitude, VibrationEffect.DEFAULT_AMPLITUDE) != 0) { return this; } - return new StepSegment((float) defaultAmplitude / VibrationEffect.MAX_AMPLITUDE, mFrequency, + return new StepSegment((float) defaultAmplitude / VibrationEffect.MAX_AMPLITUDE, + mFrequencyHz, mDuration); } @@ -119,7 +129,7 @@ public final class StepSegment extends VibrationEffectSegment { if (Float.compare(mAmplitude, VibrationEffect.DEFAULT_AMPLITUDE) == 0) { return this; } - return new StepSegment(VibrationEffect.scale(mAmplitude, scaleFactor), mFrequency, + return new StepSegment(VibrationEffect.scale(mAmplitude, scaleFactor), mFrequencyHz, mDuration); } @@ -132,13 +142,13 @@ public final class StepSegment extends VibrationEffectSegment { @Override public int hashCode() { - return Objects.hash(mAmplitude, mFrequency, mDuration); + return Objects.hash(mAmplitude, mFrequencyHz, mDuration); } @Override public String toString() { return "Step{amplitude=" + mAmplitude - + ", frequency=" + mFrequency + + ", frequencyHz=" + mFrequencyHz + ", duration=" + mDuration + "}"; } @@ -152,7 +162,7 @@ public final class StepSegment extends VibrationEffectSegment { public void writeToParcel(@NonNull Parcel out, int flags) { out.writeInt(PARCEL_TOKEN_STEP); out.writeFloat(mAmplitude); - out.writeFloat(mFrequency); + out.writeFloat(mFrequencyHz); out.writeInt(mDuration); } diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java index 781564b7be35e..10cec8243b8e5 100644 --- a/core/tests/coretests/src/android/os/VibrationEffectTest.java +++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java @@ -125,8 +125,8 @@ public class VibrationEffectTest { VibrationEffect.startWaveform() .addStep(/* amplitude= */ 1, /* duration= */ 10) .addRamp(/* amplitude= */ 0, /* duration= */ 20) - .addStep(/* amplitude= */ 1, /* frequency*/ 1, /* duration= */ 100) - .addRamp(/* amplitude= */ 0.5f, /* frequency*/ -1, /* duration= */ 50) + .addStep(/* amplitude= */ 1, /* frequencyHz= */ 1, /* duration= */ 100) + .addRamp(/* amplitude= */ 0.5f, /* frequencyHz= */ 100, /* duration= */ 50) .build() .validate(); @@ -148,12 +148,24 @@ public class VibrationEffectTest { assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startWaveform() .addStep(/* amplitude= */ -2, 10).build().validate()); + assertThrows(IllegalArgumentException.class, + () -> VibrationEffect.startWaveform() + .addStep(1, /* frequencyHz= */ -1f, 10).build().validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startWaveform() .addStep(1, /* duration= */ -1).build().validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startWaveform() - .addStep(1, 0, /* duration= */ -1).build().validate()); + .addStep(1, 100f, /* duration= */ -1).build().validate()); + assertThrows(IllegalArgumentException.class, + () -> VibrationEffect.startWaveform() + .addRamp(/* amplitude= */ -3, 10).build().validate()); + assertThrows(IllegalArgumentException.class, + () -> VibrationEffect.startWaveform() + .addRamp(1, /* frequencyHz= */ 0, 10).build().validate()); + assertThrows(IllegalArgumentException.class, + () -> VibrationEffect.startWaveform() + .addRamp(1, 10f, /* duration= */ -3).build().validate()); } @Test diff --git a/core/tests/coretests/src/android/os/VibratorInfoTest.java b/core/tests/coretests/src/android/os/VibratorInfoTest.java index 6e07fa264c1cc..d0e03a24427e1 100644 --- a/core/tests/coretests/src/android/os/VibratorInfoTest.java +++ b/core/tests/coretests/src/android/os/VibratorInfoTest.java @@ -19,6 +19,7 @@ package android.os; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.hardware.vibrator.Braking; @@ -43,19 +44,17 @@ public class VibratorInfoTest { /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; private static final VibratorInfo.FrequencyMapping EMPTY_FREQUENCY_MAPPING = - new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null); + new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, null); private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING = - new VibratorInfo.FrequencyMapping(TEST_MIN_FREQUENCY, - TEST_RESONANT_FREQUENCY, TEST_FREQUENCY_RESOLUTION, - /* suggestedSafeRangeHz= */ 50, TEST_AMPLITUDE_MAP); + new VibratorInfo.FrequencyMapping(TEST_RESONANT_FREQUENCY, TEST_MIN_FREQUENCY, + TEST_FREQUENCY_RESOLUTION, TEST_AMPLITUDE_MAP); @Test public void testHasAmplitudeControl() { VibratorInfo noCapabilities = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); assertFalse(noCapabilities.hasAmplitudeControl()); VibratorInfo composeAndAmplitudeControl = new VibratorInfo.Builder(TEST_VIBRATOR_ID) - .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS - | IVibrator.CAP_AMPLITUDE_CONTROL) + .setCapabilities(IVibrator.CAP_COMPOSE_EFFECTS | IVibrator.CAP_AMPLITUDE_CONTROL) .build(); assertTrue(composeAndAmplitudeControl.hasAmplitudeControl()); } @@ -143,138 +142,95 @@ public class VibratorInfoTest { } @Test - public void testGetFrequencyRange_invalidFrequencyMappingReturnsEmptyRange() { + public void testGetFrequencyRangeHz_invalidFrequencyMappingReturnsNull() { // Invalid, contains NaN values or empty array. - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder( - TEST_VIBRATOR_ID).build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) + assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID).build().getFrequencyRangeHz()); + assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - Float.NaN, 150, 25, 50, TEST_AMPLITUDE_MAP)) - .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) + Float.NaN, 50, 25, TEST_AMPLITUDE_MAP)) + .build().getFrequencyRangeHz()); + assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - 50, Float.NaN, 25, 50, TEST_AMPLITUDE_MAP)) - .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) + 150, Float.NaN, 25, TEST_AMPLITUDE_MAP)) + .build().getFrequencyRangeHz()); + assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - 50, 150, Float.NaN, 50, TEST_AMPLITUDE_MAP)) - .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) - .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - 50, 150, 25, Float.NaN, TEST_AMPLITUDE_MAP)) - .build().getFrequencyRange()); - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) - .setFrequencyMapping(new VibratorInfo.FrequencyMapping(50, 150, 25, 50, null)) - .build().getFrequencyRange()); + 150, 50, Float.NaN, TEST_AMPLITUDE_MAP)) + .build().getFrequencyRangeHz()); + assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID) + .setFrequencyMapping(new VibratorInfo.FrequencyMapping(150, 50, 25, null)) + .build().getFrequencyRangeHz()); // Invalid, minFrequency > resonantFrequency - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) + assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - /* minFrequencyHz= */ 250, /* resonantFrequency= */ 150, 25, 50, null)) - .build().getFrequencyRange()); + /* resonantFrequencyHz= */ 150, /* minFrequencyHz= */ 250, 25, null)) + .build().getFrequencyRangeHz()); // Invalid, maxFrequency < resonantFrequency by changing resolution. - assertEquals(Range.create(0f, 0f), new VibratorInfo.Builder(TEST_VIBRATOR_ID) + assertNull(new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - 50, 150, /* frequencyResolutionHz= */10, 50, null)) - .build().getFrequencyRange()); + 150, 50, /* frequencyResolutionHz= */ 10, null)) + .build().getFrequencyRangeHz()); } @Test - public void testGetFrequencyRange_safeRangeLimitedByMaxFrequency() { + public void testGetFrequencyRangeHz_resultRangeDerivedFromHalMapping() { VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150, - /* frequencyResolutionHz= */ 25, /* suggestedSafeRangeHz= */ 200, - TEST_AMPLITUDE_MAP)) + /* resonantFrequencyHz= */ 150, + /* minFrequencyHz= */ 50, + /* frequencyResolutionHz= */ 25, + new float[]{ + /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, + /* 200Hz= */ 0.8f})) .build(); - // Mapping should range from 50Hz = -2 to 200Hz = 1 - // Safe range [-1, 1] = [100Hz, 200Hz] defined by max - resonant = 50Hz - assertEquals(Range.create(-2f, 1f), info.getFrequencyRange()); + assertEquals(Range.create(50f, 200f), info.getFrequencyRangeHz()); } @Test - public void testGetFrequencyRange_safeRangeLimitedByMinFrequency() { - VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) - .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150, - /* frequencyResolutionHz= */ 50, /* suggestedSafeRangeHz= */ 200, - TEST_AMPLITUDE_MAP)) - .build(); - - // Mapping should range from 50Hz = -1 to 350Hz = 2 - // Safe range [-1, 1] = [50Hz, 250Hz] defined by resonant - min = 100Hz - assertEquals(Range.create(-1f, 2f), info.getFrequencyRange()); - } - - @Test - public void testGetFrequencyRange_validMappingReturnsFullRelativeRange() { - VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) - .setFrequencyMapping(new VibratorInfo.FrequencyMapping( - /* minFrequencyHz= */ 50, /* resonantFrequencyHz= */ 150, - /* frequencyResolutionHz= */ 50, /* suggestedSafeRangeHz= */ 100, - TEST_AMPLITUDE_MAP)) - .build(); - - // Mapping should range from 50Hz = -2 to 350Hz = 4 - // Safe range [-1, 1] = [100Hz, 200Hz] defined by suggested safe range 100Hz - assertEquals(Range.create(-2f, 4f), info.getFrequencyRange()); - } - - @Test - public void testAbsoluteFrequency_emptyMappingReturnsNaN() { + public void testGetMaxAmplitude_emptyMappingReturnsAlwaysZero() { VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); - assertTrue(Float.isNaN(info.getAbsoluteFrequency(-1))); - assertTrue(Float.isNaN(info.getAbsoluteFrequency(0))); - assertTrue(Float.isNaN(info.getAbsoluteFrequency(1))); - } + assertEquals(0f, info.getMaxAmplitude(Float.NaN), TEST_TOLERANCE); + assertEquals(0f, info.getMaxAmplitude(100f), TEST_TOLERANCE); + assertEquals(0f, info.getMaxAmplitude(200f), TEST_TOLERANCE); - @Test - public void testAbsoluteFrequency_validRangeReturnsOriginalValue() { - VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).setFrequencyMapping( - TEST_FREQUENCY_MAPPING).build(); - assertEquals(TEST_RESONANT_FREQUENCY, info.getAbsoluteFrequency(0), TEST_TOLERANCE); + info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) + .setFrequencyMapping(new VibratorInfo.FrequencyMapping( + /* resonantFrequencyHz= */ 150, + /* minFrequencyHz= */ Float.NaN, + /* frequencyResolutionHz= */ Float.NaN, + null)) + .build(); - // Safe range [-1, 1] = [125Hz, 175Hz] defined by suggested safe range 100Hz - assertEquals(125, info.getAbsoluteFrequency(-1), TEST_TOLERANCE); - assertEquals(175, info.getAbsoluteFrequency(1), TEST_TOLERANCE); - assertEquals(155, info.getAbsoluteFrequency(0.2f), TEST_TOLERANCE); - assertEquals(140, info.getAbsoluteFrequency(-0.4f), TEST_TOLERANCE); - - // Full range [-4, 2] = [50Hz, 200Hz] defined by min frequency and amplitude mapping size - assertEquals(50, info.getAbsoluteFrequency(info.getFrequencyRange().getLower()), - TEST_TOLERANCE); - assertEquals(200, info.getAbsoluteFrequency(info.getFrequencyRange().getUpper()), - TEST_TOLERANCE); - } - - @Test - public void testGetMaxAmplitude_emptyMappingReturnsOnlyResonantFrequency() { - VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build(); - assertEquals(1f, info.getMaxAmplitude(0), TEST_TOLERANCE); - assertEquals(0f, info.getMaxAmplitude(0.1f), TEST_TOLERANCE); - assertEquals(0f, info.getMaxAmplitude(-1), TEST_TOLERANCE); + assertEquals(0f, info.getMaxAmplitude(Float.NaN), TEST_TOLERANCE); + assertEquals(0f, info.getMaxAmplitude(100f), TEST_TOLERANCE); + assertEquals(0f, info.getMaxAmplitude(150f), TEST_TOLERANCE); } @Test public void testGetMaxAmplitude_validMappingReturnsMappedValues() { VibratorInfo info = new VibratorInfo.Builder(TEST_VIBRATOR_ID) - .setFrequencyMapping(new VibratorInfo.FrequencyMapping(/* minFrequencyHz= */ 50, - /* resonantFrequencyHz= */ 150, /* frequencyResolutionHz= */ 25, - /* suggestedSafeRangeHz= */ 50, TEST_AMPLITUDE_MAP)) + .setFrequencyMapping(new VibratorInfo.FrequencyMapping( + /* resonantFrequencyHz= */ 150, + /* minFrequencyHz= */ 50, + /* frequencyResolutionHz= */ 25, + new float[]{ + /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, + /* 200Hz= */ 0.8f})) .build(); - assertEquals(1f, info.getMaxAmplitude(0), TEST_TOLERANCE); // 150Hz - assertEquals(0.9f, info.getMaxAmplitude(1), TEST_TOLERANCE); // 175Hz - assertEquals(0.8f, info.getMaxAmplitude(-1), TEST_TOLERANCE); // 125Hz - assertEquals(0.8f, info.getMaxAmplitude(info.getFrequencyRange().getUpper()), + assertEquals(1f, info.getMaxAmplitude(150f), TEST_TOLERANCE); + assertEquals(0.9f, info.getMaxAmplitude(175f), TEST_TOLERANCE); + assertEquals(0.8f, info.getMaxAmplitude(125f), TEST_TOLERANCE); + assertEquals(0.8f, info.getMaxAmplitude(info.getFrequencyRangeHz().getUpper()), TEST_TOLERANCE); // 200Hz - assertEquals(0.1f, info.getMaxAmplitude(info.getFrequencyRange().getLower()), + assertEquals(0.1f, info.getMaxAmplitude(info.getFrequencyRangeHz().getLower()), TEST_TOLERANCE); // 50Hz - // Rounds 145Hz to the max amplitude for 125Hz, which is lower. - assertEquals(0.8f, info.getMaxAmplitude(-0.1f), TEST_TOLERANCE); // 145Hz - // Rounds 185Hz to the max amplitude for 200Hz, which is lower. - assertEquals(0.8f, info.getMaxAmplitude(1.2f), TEST_TOLERANCE); // 185Hz + // 145Hz maps to the max amplitude for 125Hz, which is lower. + assertEquals(0.8f, info.getMaxAmplitude(145f), TEST_TOLERANCE); // 145Hz + // 185Hz maps to the max amplitude for 200Hz, which is lower. + assertEquals(0.8f, info.getMaxAmplitude(185f), TEST_TOLERANCE); // 185Hz } @Test @@ -317,9 +273,11 @@ public class VibratorInfoTest { assertNotEquals(complete, completeWithDifferentPrimitiveDuration); VibratorInfo completeWithDifferentFrequencyMapping = completeBuilder - .setFrequencyMapping(new VibratorInfo.FrequencyMapping(TEST_MIN_FREQUENCY + 10, - TEST_RESONANT_FREQUENCY + 20, TEST_FREQUENCY_RESOLUTION + 5, - /* suggestedSafeRangeHz= */ 100, TEST_AMPLITUDE_MAP)) + .setFrequencyMapping(new VibratorInfo.FrequencyMapping( + TEST_RESONANT_FREQUENCY + 20, + TEST_MIN_FREQUENCY + 10, + TEST_FREQUENCY_RESOLUTION + 5, + TEST_AMPLITUDE_MAP)) .build(); assertNotEquals(complete, completeWithDifferentFrequencyMapping); diff --git a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java index 5f80d2a105153..3291b2d8edd9d 100644 --- a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java +++ b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java @@ -39,19 +39,19 @@ public class RampSegmentTest { @Test public void testCreation() { RampSegment ramp = new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, - /* StartFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 100); + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 200, /* duration= */ 100); assertEquals(100L, ramp.getDuration()); assertTrue(ramp.hasNonZeroAmplitude()); assertEquals(1f, ramp.getStartAmplitude()); assertEquals(0f, ramp.getEndAmplitude()); - assertEquals(-1f, ramp.getStartFrequency()); - assertEquals(1f, ramp.getEndFrequency()); + assertEquals(100f, ramp.getStartFrequencyHz()); + assertEquals(200f, ramp.getEndFrequencyHz()); } @Test public void testSerialization() { - RampSegment original = new RampSegment(0, 1, 0, 0.5f, 10); + RampSegment original = new RampSegment(0, 1, 10, 20.5f, 10); Parcel parcel = Parcel.obtain(); original.writeToParcel(parcel, 0); parcel.setDataPosition(0); @@ -61,7 +61,9 @@ public class RampSegmentTest { @Test public void testValidate() { new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, - /* StartFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 100).validate(); + /* startFrequencyHz= */ 2, /* endFrequencyHz= */ 1, /* duration= */ 100).validate(); + // Zero frequency is still used internally for unset frequency. + new RampSegment(0, 0, 0, 0, 0).validate(); assertThrows(IllegalArgumentException.class, () -> new RampSegment(VibrationEffect.DEFAULT_AMPLITUDE, 0, 0, 0, 0).validate()); @@ -69,8 +71,16 @@ public class RampSegmentTest { () -> new RampSegment(/* startAmplitude= */ -2, 0, 0, 0, 0).validate()); assertThrows(IllegalArgumentException.class, () -> new RampSegment(0, /* endAmplitude= */ 2, 0, 0, 0).validate()); + assertThrows(IllegalArgumentException.class, + () -> new RampSegment(0, 0, /* startFrequencyHz= */ -1, 0, 0).validate()); + assertThrows(IllegalArgumentException.class, + () -> new RampSegment(0, 0, 0, /* endFrequencyHz= */ -3, 0).validate()); assertThrows(IllegalArgumentException.class, () -> new RampSegment(0, 0, 0, 0, /* duration= */ -1).validate()); + assertThrows(IllegalArgumentException.class, + () -> new RampSegment(/* startAmplitude= */ Float.NaN, 0, 0, 0, 0).validate()); + assertThrows(IllegalArgumentException.class, + () -> new RampSegment(0, 0, /* startFrequencyHz= */ Float.NaN, 0, 0).validate()); } @Test diff --git a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java index fdce86a27ac47..44241273d9e35 100644 --- a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java +++ b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java @@ -38,13 +38,13 @@ public class StepSegmentTest { @Test public void testCreation() { - StepSegment step = new StepSegment(/* amplitude= */ 1f, /* frequency= */ -1f, + StepSegment step = new StepSegment(/* amplitude= */ 1f, /* frequencyHz= */ 1f, /* duration= */ 100); assertEquals(100, step.getDuration()); assertTrue(step.hasNonZeroAmplitude()); assertEquals(1f, step.getAmplitude()); - assertEquals(-1f, step.getFrequency()); + assertEquals(1f, step.getFrequencyHz()); } @Test @@ -58,14 +58,22 @@ public class StepSegmentTest { @Test public void testValidate() { - new StepSegment(/* amplitude= */ 0f, /* frequency= */ -1f, /* duration= */ 100).validate(); + new StepSegment(/* amplitude= */ 0f, /* frequencyHz= */ 10f, /* duration= */ 10).validate(); + // Zero frequency is still used internally for unset frequency. + new StepSegment(0, 0, 0).validate(); assertThrows(IllegalArgumentException.class, () -> new StepSegment(/* amplitude= */ -2, 1f, 10).validate()); assertThrows(IllegalArgumentException.class, () -> new StepSegment(/* amplitude= */ 2, 1f, 10).validate()); + assertThrows(IllegalArgumentException.class, + () -> new StepSegment(1, /* frequencyHz*/ -1f, 10).validate()); assertThrows(IllegalArgumentException.class, () -> new StepSegment(2, 1f, /* duration= */ -1).validate()); + assertThrows(IllegalArgumentException.class, + () -> new StepSegment(/* amplitude= */ Float.NaN, 1f, 10).validate()); + assertThrows(IllegalArgumentException.class, + () -> new StepSegment(1, /* frequencyHz*/ Float.NaN, 10).validate()); } @Test diff --git a/services/core/java/com/android/server/notification/VibratorHelper.java b/services/core/java/com/android/server/notification/VibratorHelper.java index be5f2194997a3..8acc8572453b5 100644 --- a/services/core/java/com/android/server/notification/VibratorHelper.java +++ b/services/core/java/com/android/server/notification/VibratorHelper.java @@ -125,10 +125,10 @@ public final class VibratorHelper { private static VibrationEffect createChirpVibration(int rampDuration, boolean insistent) { VibrationEffect.WaveformBuilder waveformBuilder = VibrationEffect.startWaveform() - .addStep(/* amplitude= */ 0, /* frequency= */ -0.85f, /* duration= */ 0) - .addRamp(/* amplitude= */ 1, /* frequency= */ -0.25f, rampDuration) - .addStep(/* amplitude= */ 1, /* frequency= */ -0.25f, CHIRP_LEVEL_DURATION_MILLIS) - .addRamp(/* amplitude= */ 0, /* frequency= */ -0.85f, rampDuration); + .addStep(/* amplitude= */ 0, /* frequencyHz= */ 60f, /* duration= */ 0) + .addRamp(/* amplitude= */ 1, /* frequencyHz= */ 120f, rampDuration) + .addStep(/* amplitude= */ 1, /* frequencyHz= */ 120f, CHIRP_LEVEL_DURATION_MILLIS) + .addRamp(/* amplitude= */ 0, /* frequencyHz= */ 60f, rampDuration); if (insistent) { return waveformBuilder diff --git a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java index 0690d3be3db17..8189e74f922ca 100644 --- a/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java +++ b/services/core/java/com/android/server/vibrator/ClippingAmplitudeAndFrequencyAdapter.java @@ -21,18 +21,16 @@ import android.os.vibrator.RampSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationEffectSegment; import android.util.MathUtils; +import android.util.Range; import java.util.List; /** - * Adapter that clips frequency values to {@link VibratorInfo#getFrequencyRange()} and + * Adapter that clips frequency values to {@link VibratorInfo#getFrequencyRangeHz()} and * amplitude values to respective {@link VibratorInfo#getMaxAmplitude}. * - *

Devices with no frequency control will collapse all frequencies to zero and leave - * amplitudes unchanged. - * - *

The frequency value returned in segments will be absolute, converted with - * {@link VibratorInfo#getAbsoluteFrequency(float)}. + *

Devices with no frequency control will collapse all frequencies to the resonant frequency and + * leave amplitudes unchanged. */ final class ClippingAmplitudeAndFrequencyAdapter implements VibrationEffectAdapters.SegmentsAdapter { @@ -52,29 +50,39 @@ final class ClippingAmplitudeAndFrequencyAdapter } private StepSegment apply(StepSegment segment, VibratorInfo info) { - float clampedFrequency = clampFrequency(info, segment.getFrequency()); + float clampedFrequency = clampFrequency(info, segment.getFrequencyHz()); return new StepSegment( clampAmplitude(info, clampedFrequency, segment.getAmplitude()), - info.getAbsoluteFrequency(clampedFrequency), + clampedFrequency, (int) segment.getDuration()); } private RampSegment apply(RampSegment segment, VibratorInfo info) { - float clampedStartFrequency = clampFrequency(info, segment.getStartFrequency()); - float clampedEndFrequency = clampFrequency(info, segment.getEndFrequency()); + float clampedStartFrequency = clampFrequency(info, segment.getStartFrequencyHz()); + float clampedEndFrequency = clampFrequency(info, segment.getEndFrequencyHz()); return new RampSegment( clampAmplitude(info, clampedStartFrequency, segment.getStartAmplitude()), clampAmplitude(info, clampedEndFrequency, segment.getEndAmplitude()), - info.getAbsoluteFrequency(clampedStartFrequency), - info.getAbsoluteFrequency(clampedEndFrequency), + clampedStartFrequency, + clampedEndFrequency, (int) segment.getDuration()); } - private float clampFrequency(VibratorInfo info, float frequency) { - return info.getFrequencyRange().clamp(frequency); + private float clampFrequency(VibratorInfo info, float frequencyHz) { + Range frequencyRangeHz = info.getFrequencyRangeHz(); + if (frequencyHz == 0 || frequencyRangeHz == null) { + return info.getResonantFrequency(); + } + return frequencyRangeHz.clamp(frequencyHz); } - private float clampAmplitude(VibratorInfo info, float frequency, float amplitude) { - return MathUtils.min(amplitude, info.getMaxAmplitude(frequency)); + private float clampAmplitude(VibratorInfo info, float frequencyHz, float amplitude) { + Range frequencyRangeHz = info.getFrequencyRangeHz(); + if (frequencyRangeHz == null) { + // No frequency range was specified, leave amplitude unchanged, the frequency will be + // clamped to the device's resonant frequency. + return amplitude; + } + return MathUtils.min(amplitude, info.getMaxAmplitude(frequencyHz)); } } diff --git a/services/core/java/com/android/server/vibrator/RampDownAdapter.java b/services/core/java/com/android/server/vibrator/RampDownAdapter.java index e97ed4ce6e7c2..8fec162bb5878 100644 --- a/services/core/java/com/android/server/vibrator/RampDownAdapter.java +++ b/services/core/java/com/android/server/vibrator/RampDownAdapter.java @@ -90,13 +90,13 @@ final class RampDownAdapter implements VibrationEffectAdapters.SegmentsAdapter steps = apply((RampSegment) segment); + List steps = apply(info, (RampSegment) segment); segments.remove(i); segments.addAll(i, steps); int addedSegments = steps.size() - 1; @@ -65,11 +66,12 @@ final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter return repeatIndex; } - private List apply(RampSegment ramp) { + private List apply(VibratorInfo info, RampSegment ramp) { if (Float.compare(ramp.getStartAmplitude(), ramp.getEndAmplitude()) == 0) { // Amplitude is the same, so return a single step to simulate this ramp. return Arrays.asList( - new StepSegment(ramp.getStartAmplitude(), ramp.getStartFrequency(), + new StepSegment(ramp.getStartAmplitude(), + fillEmptyFrequency(info, ramp.getStartFrequencyHz()), (int) ramp.getDuration())); } @@ -77,17 +79,21 @@ final class RampToStepAdapter implements VibrationEffectAdapters.SegmentsAdapter int stepCount = (int) (ramp.getDuration() + mStepDuration - 1) / mStepDuration; for (int i = 0; i < stepCount - 1; i++) { float pos = (float) i / stepCount; + // Fill zero frequency values with the device resonant frequency before interpolating. + float startFrequencyHz = fillEmptyFrequency(info, ramp.getStartFrequencyHz()); + float endFrequencyHz = fillEmptyFrequency(info, ramp.getEndFrequencyHz()); steps.add(new StepSegment( - interpolate(ramp.getStartAmplitude(), ramp.getEndAmplitude(), pos), - interpolate(ramp.getStartFrequency(), ramp.getEndFrequency(), pos), + MathUtils.lerp(ramp.getStartAmplitude(), ramp.getEndAmplitude(), pos), + MathUtils.lerp(startFrequencyHz, endFrequencyHz, pos), mStepDuration)); } int duration = (int) ramp.getDuration() - mStepDuration * (stepCount - 1); - steps.add(new StepSegment(ramp.getEndAmplitude(), ramp.getEndFrequency(), duration)); + float endFrequencyHz = fillEmptyFrequency(info, ramp.getEndFrequencyHz()); + steps.add(new StepSegment(ramp.getEndAmplitude(), endFrequencyHz, duration)); return steps; } - private static float interpolate(float start, float end, float position) { - return start + position * (end - start); + private static float fillEmptyFrequency(VibratorInfo info, float frequencyHz) { + return frequencyHz == 0 ? info.getResonantFrequency() : frequencyHz; } } diff --git a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java index 6f5adac33ae6e..5ace3896f387c 100644 --- a/services/core/java/com/android/server/vibrator/StepToRampAdapter.java +++ b/services/core/java/com/android/server/vibrator/StepToRampAdapter.java @@ -21,6 +21,7 @@ import android.os.VibratorInfo; import android.os.vibrator.RampSegment; import android.os.vibrator.StepSegment; import android.os.vibrator.VibrationEffectSegment; +import android.util.MathUtils; import java.util.ArrayList; import java.util.List; @@ -41,18 +42,18 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter // The vibrator does not have PWLE capability, so keep the segments unchanged. return repeatIndex; } - convertStepsToRamps(segments); + convertStepsToRamps(info, segments); repeatIndex = splitLongRampSegments(info, segments, repeatIndex); return repeatIndex; } - private void convertStepsToRamps(List segments) { + private void convertStepsToRamps(VibratorInfo info, List segments) { int segmentCount = segments.size(); // Convert steps that require frequency control to ramps. for (int i = 0; i < segmentCount; i++) { VibrationEffectSegment segment = segments.get(i); - if (isStep(segment) && ((StepSegment) segment).getFrequency() != 0) { - segments.set(i, convertStepToRamp((StepSegment) segment)); + if (isStep(segment) && ((StepSegment) segment).getFrequencyHz() != 0) { + segments.set(i, convertStepToRamp(info, (StepSegment) segment)); } } // Convert steps that are next to ramps to also become ramps, so they can be composed @@ -60,10 +61,10 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter for (int i = 0; i < segmentCount; i++) { if (segments.get(i) instanceof RampSegment) { for (int j = i - 1; j >= 0 && isStep(segments.get(j)); j--) { - segments.set(j, convertStepToRamp((StepSegment) segments.get(j))); + segments.set(j, convertStepToRamp(info, (StepSegment) segments.get(j))); } for (int j = i + 1; j < segmentCount && isStep(segments.get(j)); j++) { - segments.set(j, convertStepToRamp((StepSegment) segments.get(j))); + segments.set(j, convertStepToRamp(info, (StepSegment) segments.get(j))); } } } @@ -92,7 +93,7 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter continue; } segments.remove(i); - segments.addAll(i, splitRampSegment(ramp, splits)); + segments.addAll(i, splitRampSegment(info, ramp, splits)); int addedSegments = splits - 1; if (repeatIndex > i) { repeatIndex += addedSegments; @@ -104,31 +105,40 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter return repeatIndex; } - private static RampSegment convertStepToRamp(StepSegment segment) { + private static RampSegment convertStepToRamp(VibratorInfo info, StepSegment segment) { + float frequencyHz = fillEmptyFrequency(info, segment.getFrequencyHz()); return new RampSegment(segment.getAmplitude(), segment.getAmplitude(), - segment.getFrequency(), segment.getFrequency(), (int) segment.getDuration()); + frequencyHz, frequencyHz, (int) segment.getDuration()); } - private static List splitRampSegment(RampSegment ramp, int splits) { + private static List splitRampSegment(VibratorInfo info, RampSegment ramp, + int splits) { List ramps = new ArrayList<>(splits); + float startFrequencyHz = fillEmptyFrequency(info, ramp.getStartFrequencyHz()); + float endFrequencyHz = fillEmptyFrequency(info, ramp.getEndFrequencyHz()); long splitDuration = ramp.getDuration() / splits; float previousAmplitude = ramp.getStartAmplitude(); - float previousFrequency = ramp.getStartFrequency(); + float previousFrequency = startFrequencyHz; long accumulatedDuration = 0; for (int i = 1; i < splits; i++) { accumulatedDuration += splitDuration; + float durationRatio = (float) accumulatedDuration / ramp.getDuration(); + float interpolatedFrequency = + MathUtils.lerp(startFrequencyHz, endFrequencyHz, durationRatio); + float interpolatedAmplitude = + MathUtils.lerp(ramp.getStartAmplitude(), ramp.getEndAmplitude(), durationRatio); RampSegment rampSplit = new RampSegment( - previousAmplitude, interpolateAmplitude(ramp, accumulatedDuration), - previousFrequency, interpolateFrequency(ramp, accumulatedDuration), + previousAmplitude, interpolatedAmplitude, + previousFrequency, interpolatedFrequency, (int) splitDuration); ramps.add(rampSplit); previousAmplitude = rampSplit.getEndAmplitude(); - previousFrequency = rampSplit.getEndFrequency(); + previousFrequency = rampSplit.getEndFrequencyHz(); } ramps.add(new RampSegment(previousAmplitude, ramp.getEndAmplitude(), previousFrequency, - ramp.getEndFrequency(), (int) (ramp.getDuration() - accumulatedDuration))); + endFrequencyHz, (int) (ramp.getDuration() - accumulatedDuration))); return ramps; } @@ -137,18 +147,7 @@ final class StepToRampAdapter implements VibrationEffectAdapters.SegmentsAdapter return segment instanceof StepSegment; } - private static float interpolateAmplitude(RampSegment ramp, long duration) { - return interpolate(ramp.getStartAmplitude(), ramp.getEndAmplitude(), duration, - ramp.getDuration()); - } - - private static float interpolateFrequency(RampSegment ramp, long duration) { - return interpolate(ramp.getStartFrequency(), ramp.getEndFrequency(), duration, - ramp.getDuration()); - } - - private static float interpolate(float start, float end, long duration, long totalDuration) { - float position = (float) duration / totalDuration; - return start + position * (end - start); + private static float fillEmptyFrequency(VibratorInfo info, float frequencyHz) { + return frequencyHz == 0 ? info.getResonantFrequency() : frequencyHz; } } diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java index 1d6e1585872dc..0c15ee723dd31 100644 --- a/services/core/java/com/android/server/vibrator/Vibration.java +++ b/services/core/java/com/android/server/vibrator/Vibration.java @@ -373,7 +373,7 @@ final class Vibration { final long token = proto.start(fieldId); proto.write(StepSegmentProto.DURATION, segment.getDuration()); proto.write(StepSegmentProto.AMPLITUDE, segment.getAmplitude()); - proto.write(StepSegmentProto.FREQUENCY, segment.getFrequency()); + proto.write(StepSegmentProto.FREQUENCY, segment.getFrequencyHz()); proto.end(token); } @@ -382,8 +382,8 @@ final class Vibration { proto.write(RampSegmentProto.DURATION, segment.getDuration()); proto.write(RampSegmentProto.START_AMPLITUDE, segment.getStartAmplitude()); proto.write(RampSegmentProto.END_AMPLITUDE, segment.getEndAmplitude()); - proto.write(RampSegmentProto.START_FREQUENCY, segment.getStartFrequency()); - proto.write(RampSegmentProto.END_FREQUENCY, segment.getEndFrequency()); + proto.write(RampSegmentProto.START_FREQUENCY, segment.getStartFrequencyHz()); + proto.write(RampSegmentProto.END_FREQUENCY, segment.getEndFrequencyHz()); proto.end(token); } diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java index 4a1b95bd4596e..47b3e1a2294cb 100644 --- a/services/core/java/com/android/server/vibrator/VibratorController.java +++ b/services/core/java/com/android/server/vibrator/VibratorController.java @@ -36,8 +36,6 @@ import libcore.util.NativeAllocationRegistry; /** Controls a single vibrator. */ final class VibratorController { private static final String TAG = "VibratorController"; - // TODO(b/167947076): load suggested range from config - private static final int SUGGESTED_FREQUENCY_SAFE_RANGE = 200; private final Object mLock = new Object(); @@ -74,8 +72,7 @@ final class VibratorController { mNativeWrapper = nativeWrapper; mNativeWrapper.init(vibratorId, listener); VibratorInfo.Builder vibratorInfoBuilder = new VibratorInfo.Builder(vibratorId); - mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(SUGGESTED_FREQUENCY_SAFE_RANGE, - vibratorInfoBuilder); + mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(vibratorInfoBuilder); mVibratorInfo = vibratorInfoBuilder.build(); if (!mVibratorInfoLoadSuccessful) { @@ -126,8 +123,7 @@ final class VibratorController { } int vibratorId = mVibratorInfo.getId(); VibratorInfo.Builder vibratorInfoBuilder = new VibratorInfo.Builder(vibratorId); - mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(SUGGESTED_FREQUENCY_SAFE_RANGE, - vibratorInfoBuilder); + mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(vibratorInfoBuilder); mVibratorInfo = vibratorInfoBuilder.build(); if (!mVibratorInfoLoadSuccessful) { Slog.e(TAG, "Failed retry of HAL getInfo for vibrator " + vibratorId); @@ -419,8 +415,7 @@ final class VibratorController { private static native void alwaysOnDisable(long nativePtr, long id); - private static native boolean getInfo(long nativePtr, float suggestedFrequencyRange, - VibratorInfo.Builder infoBuilder); + private static native boolean getInfo(long nativePtr, VibratorInfo.Builder infoBuilder); private long mNativePtr = 0; @@ -490,8 +485,8 @@ final class VibratorController { /** * Loads device vibrator metadata and returns true if all metadata was loaded successfully. */ - public boolean getInfo(float suggestedFrequencyRange, VibratorInfo.Builder infoBuilder) { - return getInfo(mNativePtr, suggestedFrequencyRange, infoBuilder); + public boolean getInfo(VibratorInfo.Builder infoBuilder) { + return getInfo(mNativePtr, infoBuilder); } } } diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java index 478e86e5f7107..27566b301a6ed 100644 --- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java +++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java @@ -1756,17 +1756,23 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { } if (hasFrequencies) { frequencies.add(Float.parseFloat(getNextArgRequired())); - } else { - frequencies.add(0f); } } VibrationEffect.WaveformBuilder waveform = VibrationEffect.startWaveform(); for (int i = 0; i < durations.size(); i++) { if (isContinuous) { - waveform.addRamp(amplitudes.get(i), frequencies.get(i), durations.get(i)); + if (hasFrequencies) { + waveform.addRamp(amplitudes.get(i), frequencies.get(i), durations.get(i)); + } else { + waveform.addRamp(amplitudes.get(i), durations.get(i)); + } } else { - waveform.addStep(amplitudes.get(i), frequencies.get(i), durations.get(i)); + if (hasFrequencies) { + waveform.addStep(amplitudes.get(i), frequencies.get(i), durations.get(i)); + } else { + waveform.addStep(amplitudes.get(i), durations.get(i)); + } } } composition.addEffect(waveform.build(repeat), delay); @@ -1865,7 +1871,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub { pw.println(" If -c is provided, the waveform is continuous and will ramp"); pw.println(" between values; otherwise each entry is a fixed step."); pw.println(" Duration is in milliseconds; amplitude is a scale of 1-255;"); - pw.println(" frequency is a relative value around resonant frequency 0;"); + pw.println(" frequency is an absolute value in hertz;"); pw.println(" prebaked [-w delay] [-b] "); pw.println(" Vibrates with prebaked effect; ignored when device is on DND "); pw.println(" (Do Not Disturb) mode; touch feedback strength user setting "); diff --git a/services/core/jni/com_android_server_vibrator_VibratorController.cpp b/services/core/jni/com_android_server_vibrator_VibratorController.cpp index 546b075ea0be1..b484796af6e24 100644 --- a/services/core/jni/com_android_server_vibrator_VibratorController.cpp +++ b/services/core/jni/com_android_server_vibrator_VibratorController.cpp @@ -61,8 +61,8 @@ static struct { static struct { jfieldID startAmplitude; jfieldID endAmplitude; - jfieldID startFrequency; - jfieldID endFrequency; + jfieldID startFrequencyHz; + jfieldID endFrequencyHz; jfieldID duration; } sRampClassInfo; @@ -157,8 +157,8 @@ static aidl::ActivePwle activePwleFromJavaPrimitive(JNIEnv* env, jobject ramp) { static_cast(env->GetFloatField(ramp, sRampClassInfo.startAmplitude)); pwle.endAmplitude = static_cast(env->GetFloatField(ramp, sRampClassInfo.endAmplitude)); pwle.startFrequency = - static_cast(env->GetFloatField(ramp, sRampClassInfo.startFrequency)); - pwle.endFrequency = static_cast(env->GetFloatField(ramp, sRampClassInfo.endFrequency)); + static_cast(env->GetFloatField(ramp, sRampClassInfo.startFrequencyHz)); + pwle.endFrequency = static_cast(env->GetFloatField(ramp, sRampClassInfo.endFrequencyHz)); pwle.duration = static_cast(env->GetIntField(ramp, sRampClassInfo.duration)); return pwle; } @@ -363,7 +363,7 @@ static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr, } static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr, - jfloat suggestedSafeRange, jobject vibratorInfoBuilder) { + jobject vibratorInfoBuilder) { VibratorControllerWrapper* wrapper = reinterpret_cast(ptr); if (wrapper == nullptr) { ALOGE("vibratorGetInfo failed because native wrapper was not initialized"); @@ -437,9 +437,9 @@ static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr, env->SetFloatArrayRegion(maxAmplitudes, 0, amplitudes.size(), reinterpret_cast(amplitudes.data())); } - jobject frequencyMapping = env->NewObject(sFrequencyMappingClass, sFrequencyMappingCtor, - minFrequency, resonantFrequency, frequencyResolution, - suggestedSafeRange, maxAmplitudes); + jobject frequencyMapping = + env->NewObject(sFrequencyMappingClass, sFrequencyMappingCtor, resonantFrequency, + minFrequency, frequencyResolution, maxAmplitudes); env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setFrequencyMapping, frequencyMapping); @@ -463,7 +463,7 @@ static const JNINativeMethod method_table[] = { {"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl}, {"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable}, {"alwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable}, - {"getInfo", "(JFLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo}, + {"getInfo", "(JLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo}, }; int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) { @@ -481,13 +481,13 @@ int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env jclass rampClass = FindClassOrDie(env, "android/os/vibrator/RampSegment"); sRampClassInfo.startAmplitude = GetFieldIDOrDie(env, rampClass, "mStartAmplitude", "F"); sRampClassInfo.endAmplitude = GetFieldIDOrDie(env, rampClass, "mEndAmplitude", "F"); - sRampClassInfo.startFrequency = GetFieldIDOrDie(env, rampClass, "mStartFrequency", "F"); - sRampClassInfo.endFrequency = GetFieldIDOrDie(env, rampClass, "mEndFrequency", "F"); + sRampClassInfo.startFrequencyHz = GetFieldIDOrDie(env, rampClass, "mStartFrequencyHz", "F"); + sRampClassInfo.endFrequencyHz = GetFieldIDOrDie(env, rampClass, "mEndFrequencyHz", "F"); sRampClassInfo.duration = GetFieldIDOrDie(env, rampClass, "mDuration", "I"); jclass frequencyMappingClass = FindClassOrDie(env, "android/os/VibratorInfo$FrequencyMapping"); sFrequencyMappingClass = static_cast(env->NewGlobalRef(frequencyMappingClass)); - sFrequencyMappingCtor = GetMethodIDOrDie(env, sFrequencyMappingClass, "", "(FFFF[F)V"); + sFrequencyMappingCtor = GetMethodIDOrDie(env, sFrequencyMappingClass, "", "(FFF[F)V"); jclass vibratorInfoBuilderClass = FindClassOrDie(env, "android/os/VibratorInfo$Builder"); sVibratorInfoBuilderClassInfo.setCapabilities = diff --git a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java index b934ecb805641..739b3b179de77 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/DeviceVibrationEffectAdapterTest.java @@ -54,11 +54,10 @@ public class DeviceVibrationEffectAdapterTest { /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; private static final VibratorInfo.FrequencyMapping EMPTY_FREQUENCY_MAPPING = - new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, Float.NaN, null); + new VibratorInfo.FrequencyMapping(Float.NaN, Float.NaN, Float.NaN, null); private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING = - new VibratorInfo.FrequencyMapping(TEST_MIN_FREQUENCY, - TEST_RESONANT_FREQUENCY, TEST_FREQUENCY_RESOLUTION, - /* suggestedSafeRangeHz= */ 50, TEST_AMPLITUDE_MAP); + new VibratorInfo.FrequencyMapping(TEST_RESONANT_FREQUENCY, TEST_MIN_FREQUENCY, + TEST_FREQUENCY_RESOLUTION, TEST_AMPLITUDE_MAP); private DeviceVibrationEffectAdapter mAdapter; @@ -87,14 +86,14 @@ public class DeviceVibrationEffectAdapterTest { @Test public void testStepAndRampSegments_withoutPwleCapability_convertsRampsToSteps() { VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10), + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 300, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 100), + /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f, - /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 1000)), + /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 1, /* duration= */ 1000)), /* repeatIndex= */ 3); VibrationEffect.Composed adaptedEffect = (VibrationEffect.Composed) mAdapter.apply(effect, @@ -110,23 +109,23 @@ public class DeviceVibrationEffectAdapterTest { @Test public void testStepAndRampSegments_withPwleCapability_convertsStepsToRamps() { VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 175, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 60), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)), + /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)), /* repeatIndex= */ 2); VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList( new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 175, /* endFrequency= */ 175, /* duration= */ 10), + /* startFrequencyHz= */ 175, /* endFrequencyHz= */ 175, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ 150, /* endFrequency= */ 150, /* duration= */ 100), + /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 60), new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f, - /* startFrequency= */ 50, /* endFrequency= */ 200, /* duration= */ 50), + /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f, - /* startFrequency= */ 200, /* endFrequency= */ 50, /* duration= */ 20)), + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 50, /* duration= */ 20)), /* repeatIndex= */ 2); VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_MAPPING, @@ -135,28 +134,28 @@ public class DeviceVibrationEffectAdapterTest { } @Test - public void testStepAndRampSegments_withEmptyFreqMapping_returnsSameAmplitudesAndZeroFreq() { + public void testStepAndRampSegments_withEmptyFreqMapping_returnsAmplitudesWithResonantFreq() { VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 175, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 1, - /* startFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 50), + /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.7f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)), + /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)), /* repeatIndex= */ 2); VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList( new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN, + /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN, + /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 1, - /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN, + /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.7f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ Float.NaN, /* endFrequency= */ Float.NaN, + /* startFrequencyHz= */ Float.NaN, /* endFrequencyHz= */ Float.NaN, /* duration= */ 20)), /* repeatIndex= */ 2); @@ -168,25 +167,25 @@ public class DeviceVibrationEffectAdapterTest { @Test public void testStepAndRampSegments_withValidFreqMapping_returnsClippedValues() { VibrationEffect.Composed effect = new VibrationEffect.Composed(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 1, /* frequency= */ -1, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 125, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20)), + /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20)), /* repeatIndex= */ 2); VibrationEffect.Composed expected = new VibrationEffect.Composed(Arrays.asList( new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ 150, /* endFrequency= */ 150, + /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f, - /* startFrequency= */ 125, /* endFrequency= */ 125, + /* startFrequencyHz= */ 125, /* endFrequencyHz= */ 125, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.1f, /* endAmplitude= */ 0.8f, - /* startFrequency= */ 50, /* endFrequency= */ 200, /* duration= */ 50), + /* startFrequencyHz= */ 50, /* endFrequencyHz= */ 200, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.1f, - /* startFrequency= */ 200, /* endFrequency= */ 50, /* duration= */ 20)), + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 50, /* duration= */ 20)), /* repeatIndex= */ 2); VibratorInfo info = createVibratorInfo(TEST_FREQUENCY_MAPPING, diff --git a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java index 777e3f4e4a010..2ad0e93dd1fb1 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibratorControllerProvider.java @@ -87,7 +87,7 @@ final class FakeVibratorControllerProvider { @Override public long on(long milliseconds, long vibrationId) { mEffectSegments.add(new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE, - /* frequency= */ 0, (int) milliseconds)); + /* frequencyHz= */ 0, (int) milliseconds)); applyLatency(); scheduleListener(milliseconds, vibrationId); return milliseconds; @@ -158,7 +158,7 @@ final class FakeVibratorControllerProvider { } @Override - public boolean getInfo(float suggestedFrequencyRange, VibratorInfo.Builder infoBuilder) { + public boolean getInfo(VibratorInfo.Builder infoBuilder) { infoBuilder.setCapabilities(mCapabilities); infoBuilder.setSupportedBraking(mSupportedBraking); infoBuilder.setPwleSizeMax(mPwleSizeMax); @@ -170,9 +170,8 @@ final class FakeVibratorControllerProvider { } infoBuilder.setCompositionSizeMax(mCompositionSizeMax); infoBuilder.setQFactor(mQFactor); - infoBuilder.setFrequencyMapping(new VibratorInfo.FrequencyMapping(mMinFrequency, - mResonantFrequency, mFrequencyResolution, suggestedFrequencyRange, - mMaxAmplitudes)); + infoBuilder.setFrequencyMapping(new VibratorInfo.FrequencyMapping( + mResonantFrequency, mMinFrequency, mFrequencyResolution, mMaxAmplitudes)); return mIsInfoLoadSuccessful; } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java index 4c3312c415500..a3edf2345a228 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/RampDownAdapterTest.java @@ -70,9 +70,9 @@ public class RampDownAdapterTest { @Test public void testRampAndStepSegments_withNoOffSegment_keepsListUnchanged() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20))); List originalSegments = new ArrayList<>(segments); assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO)); @@ -86,12 +86,12 @@ public class RampDownAdapterTest { mAdapter = new RampDownAdapter(/* rampDownDuration= */ 0, TEST_STEP_DURATION); List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20), + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 50))); + /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 50))); List originalSegments = new ArrayList<>(segments); assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO)); @@ -102,12 +102,12 @@ public class RampDownAdapterTest { @Test public void testStepSegments_withShortZeroSegment_replaceWithStepsDown() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10))); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 10))); List expectedSegments = Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5)); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5)); assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO)); assertEquals(expectedSegments, segments); @@ -116,17 +116,17 @@ public class RampDownAdapterTest { @Test public void testStepSegments_withLongZeroSegment_replaceWithStepsDownWithRemainingOffSegment() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 50), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100))); + /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 0, /* duration= */ 50), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100))); List expectedSegments = Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100)); assertEquals(-1, mAdapter.apply(segments, -1, TEST_VIBRATOR_INFO)); assertEquals(expectedSegments, segments); @@ -135,16 +135,16 @@ public class RampDownAdapterTest { @Test public void testStepSegments_withZeroSegmentBeforeRepeat_fixesRepeat() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 50), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100))); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 50), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100))); List expectedSegments = Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100)); // Repeat index fixed after intermediate steps added assertEquals(5, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); @@ -154,14 +154,14 @@ public class RampDownAdapterTest { @Test public void testStepSegments_withZeroSegmentAfterRepeat_preservesRepeat() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100))); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100))); List expectedSegments = Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 100)); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 100)); assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); assertEquals(expectedSegments, segments); @@ -170,22 +170,22 @@ public class RampDownAdapterTest { @Test public void testStepSegments_withZeroSegmentAtRepeat_fixesRepeatAndAppendOriginalToListEnd() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 50), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 100))); + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 50), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 100))); List expectedSegments = Arrays.asList( - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 100), // Original zero segment appended to the end of new looping vibration, // then converted to ramp down as well. - new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 35)); + new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 35)); // Repeat index fixed after intermediate steps added assertEquals(5, mAdapter.apply(segments, 1, TEST_VIBRATOR_INFO)); @@ -195,8 +195,8 @@ public class RampDownAdapterTest { @Test public void testStepSegments_withRepeatToNonZeroSegment_keepsOriginalSteps() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100))); + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100))); List originalSegments = new ArrayList<>(segments); assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); @@ -208,14 +208,14 @@ public class RampDownAdapterTest { public void testStepSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() { List segments = new ArrayList<>(Arrays.asList( new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30))); + /* startfrequencyHz= */ 0, /* endfrequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30))); List expectedSegments = Arrays.asList( new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5)); + /* startfrequencyHz= */ 0, /* endfrequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5)); // Shift repeat index to the right to use append instead of zero segment. assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); @@ -226,17 +226,17 @@ public class RampDownAdapterTest { @Test public void testStepSegments_withRepeatToLongZeroSegment_splitAndAppendRampDown() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 120), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30))); + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 120), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30))); List expectedSegments = Arrays.asList( // Split long zero segment to skip part of it. - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 20), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 100), - new StepSegment(/* amplitude= */ 1, /* frequency= */ 0, /* duration= */ 30), - new StepSegment(/* amplitude= */ 0.75f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.25f, /* frequency= */ 0, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 5)); + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 20), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 0, /* duration= */ 30), + new StepSegment(/* amplitude= */ 0.75f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.25f, /* frequencyHz= */ 0, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 5)); // Shift repeat index to the right to use append with part of the zero segment. assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); @@ -248,18 +248,20 @@ public class RampDownAdapterTest { public void testRampSegments_withShortZeroSegment_replaceWithRampDown() { List segments = new ArrayList<>(Arrays.asList( new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200, + /* duration= */ 30))); List expectedSegments = Arrays.asList( new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200, + /* duration= */ 30)); assertEquals(2, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); @@ -269,20 +271,23 @@ public class RampDownAdapterTest { @Test public void testRampSegments_withLongZeroSegment_splitAndAddRampDown() { List segments = new ArrayList<>(Arrays.asList( - new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 150), + new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 150, /* duration= */ 150), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200, + /* duration= */ 30))); List expectedSegments = Arrays.asList( new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 20), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 130), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, + /* duration= */ 130), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30)); + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200, + /* duration= */ 30)); // Repeat index fixed after intermediate steps added assertEquals(3, mAdapter.apply(segments, 2, TEST_VIBRATOR_INFO)); @@ -294,9 +299,10 @@ public class RampDownAdapterTest { public void testRampSegments_withRepeatToNonZeroSegment_keepsOriginalSteps() { List segments = new ArrayList<>(Arrays.asList( new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200, + /* duration= */ 30))); List originalSegments = new ArrayList<>(segments); assertEquals(0, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); @@ -307,15 +313,15 @@ public class RampDownAdapterTest { @Test public void testRampSegments_withRepeatToShortZeroSegment_skipAndAppendRampDown() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 1, - /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 20))); + /* startFrequencyHz= */ 40, /* endFrequencyHz= */ 80, /* duration= */ 20))); List expectedSegments = Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 20), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, - /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 20), + /* startFrequencyHz= */ 40, /* endFrequencyHz= */ 80, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20)); + /* startFrequencyHz= */ 80, /* endFrequencyHz= */ 80, /* duration= */ 20)); // Shift repeat index to the right to use append instead of zero segment. assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); @@ -327,19 +333,19 @@ public class RampDownAdapterTest { public void testRampSegments_withRepeatToLongZeroSegment_splitAndAppendRampDown() { List segments = new ArrayList<>(Arrays.asList( new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 70), + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 70), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30))); + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 30))); List expectedSegments = Arrays.asList( // Split long zero segment to skip part of it. new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20), + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 50), + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 30), + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 30), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 20)); + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 1, /* duration= */ 20)); // Shift repeat index to the right to use append with part of the zero segment. assertEquals(1, mAdapter.apply(segments, 0, TEST_VIBRATOR_INFO)); diff --git a/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java index 95c3bd93e69b5..22db917367560 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/RampToStepAdapterTest.java @@ -45,6 +45,12 @@ import java.util.stream.IntStream; @Presubmit public class RampToStepAdapterTest { private static final int TEST_STEP_DURATION = 5; + private static final float[] TEST_AMPLITUDE_MAP = new float[]{ + /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; + private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING = + new VibratorInfo.FrequencyMapping( + /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f, + /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP); private RampToStepAdapter mAdapter; @@ -56,7 +62,7 @@ public class RampToStepAdapterTest { @Test public void testStepAndPrebakedAndPrimitiveSegments_keepsListUnchanged() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10), new PrebakedSegment( VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT), new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10))); @@ -71,9 +77,9 @@ public class RampToStepAdapterTest { @Test public void testRampSegments_withPwleCapability_keepsListUnchanged() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 1, /* duration= */ 20))); List originalSegments = new ArrayList<>(segments); VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); @@ -86,27 +92,28 @@ public class RampToStepAdapterTest { @Test public void testRampSegments_withoutPwleCapability_convertsRampsToSteps() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 10, /* duration= */ 100), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10), + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 0, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ -3, /* endFrequency= */ 0, /* duration= */ 11), + /* startFrequencyHz= */ 30, /* endFrequencyHz= */ 60, /* duration= */ 11), new RampSegment(/* startAmplitude= */ 0.65f, /* endAmplitude= */ 0.65f, - /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 200))); + /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 1, /* duration= */ 200))); List expectedSegments = Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 10, /* duration= */ 100), // 10ms ramp becomes 2 steps - new StepSegment(/* amplitude= */ 1, /* frequency= */ -4, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.2f, /* frequency= */ 2, /* duration= */ 5), + new StepSegment(/* amplitude= */ 1, /* frequencyHz= */ 10, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.2f, /* frequencyHz= */ 150, /* duration= */ 5), // 11ms ramp becomes 3 steps - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ -3, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.6f, /* frequency= */ -2, /* duration= */ 5), - new StepSegment(/* amplitude= */ 0.2f, /* frequency= */ 0, /* duration= */ 1), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 30, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.6f, /* frequencyHz= */ 40, /* duration= */ 5), + new StepSegment(/* amplitude= */ 0.2f, /* frequencyHz= */ 60, /* duration= */ 1), // 200ms ramp with same amplitude becomes a single step - new StepSegment(/* amplitude= */ 0.65f, /* frequency= */ 0, /* duration= */ 200)); + new StepSegment(/* amplitude= */ 0.65f, /* frequencyHz= */ 150, + /* duration= */ 200)); // Repeat index fixed after intermediate steps added assertEquals(4, mAdapter.apply(segments, 3, createVibratorInfo())); @@ -117,6 +124,7 @@ public class RampToStepAdapterTest { private static VibratorInfo createVibratorInfo(int... capabilities) { return new VibratorInfo.Builder(0) .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) + .setFrequencyMapping(TEST_FREQUENCY_MAPPING) .build(); } } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java index 128cd2f9e0a1e..18ff953446a23 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/StepToRampAdapterTest.java @@ -44,6 +44,13 @@ import java.util.stream.IntStream; */ @Presubmit public class StepToRampAdapterTest { + private static final float[] TEST_AMPLITUDE_MAP = new float[]{ + /* 50Hz= */ 0.1f, 0.2f, 0.4f, 0.8f, /* 150Hz= */ 1f, 0.9f, /* 200Hz= */ 0.8f}; + private static final VibratorInfo.FrequencyMapping TEST_FREQUENCY_MAPPING = + new VibratorInfo.FrequencyMapping( + /* resonantFrequencyHz= */ 150f, /* minFrequencyHz= */ 50f, + /* frequencyResolutionHz= */ 25f, TEST_AMPLITUDE_MAP); + private StepToRampAdapter mAdapter; @Before @@ -55,7 +62,7 @@ public class StepToRampAdapterTest { public void testRampAndPrebakedAndPrimitiveSegments_returnsOriginalSegments() { List segments = new ArrayList<>(Arrays.asList( new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 0.2f, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 10), + /* startFrequencyHz= */ 40f, /* endFrequencyHz= */ 20f, /* duration= */ 10), new PrebakedSegment( VibrationEffect.EFFECT_CLICK, false, VibrationEffect.EFFECT_STRENGTH_LIGHT), new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10))); @@ -71,27 +78,28 @@ public class StepToRampAdapterTest { public void testRampSegments_withPwleDurationLimit_splitsLongRamps() { List segments = new ArrayList<>(Arrays.asList( new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 10, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, - /* startFrequency= */ 0, /* endFrequency= */ -1, /* duration= */ 25), + /* startFrequencyHz= */ 0, /* endFrequencyHz= */ 50, /* duration= */ 25), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude*/ 1, - /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 5))); + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 20, /* duration= */ 5))); List expectedSegments = Arrays.asList( new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude*/ 0.5f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 10, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 0.32f, - /* startFrequency= */ 0, /* endFrequency= */ -0.32f, /* duration= */ 8), + /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 118f, /* duration= */ 8), new RampSegment(/* startAmplitude= */ 0.32f, /* endAmplitude= */ 0.64f, - /* startFrequency= */ -0.32f, /* endFrequency= */ -0.64f, + /* startFrequencyHz= */ 118f, /* endFrequencyHz= */ 86f, /* duration= */ 8), new RampSegment(/* startAmplitude= */ 0.64f, /* endAmplitude= */ 1, - /* startFrequency= */ -0.64f, /* endFrequency= */ -1, /* duration= */ 9), + /* startFrequencyHz= */ 86f, /* endFrequencyHz= */ 50f, /* duration= */ 9), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude*/ 1, - /* startFrequency= */ 0, /* endFrequency= */ 1, /* duration= */ 5)); + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 20, /* duration= */ 5)); VibratorInfo vibratorInfo = new VibratorInfo.Builder(0) .setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS) .setPwlePrimitiveDurationMax(10) + .setFrequencyMapping(TEST_FREQUENCY_MAPPING) .build(); // Update repeat index to skip the ramp splits. @@ -102,9 +110,9 @@ public class StepToRampAdapterTest { @Test public void testStepAndRampSegments_withoutPwleCapability_keepsListUnchanged() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 1, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 50, /* duration= */ 20))); List originalSegments = new ArrayList<>(segments); assertEquals(-1, mAdapter.apply(segments, -1, createVibratorInfo())); @@ -116,13 +124,13 @@ public class StepToRampAdapterTest { @Test public void testStepAndRampSegments_withPwleCapabilityAndNoFrequency_keepsOriginalSteps() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 0, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 0, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 100), new PrimitiveSegment(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + /* startFrequencyHz= */ 40, /* endFrequencyHz= */ 200, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20))); + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 1, /* duration= */ 20))); List originalSegments = new ArrayList<>(segments); VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); @@ -135,25 +143,25 @@ public class StepToRampAdapterTest { @Test public void testStepAndRampSegments_withPwleCapabilityAndStepNextToRamp_convertsStepsToRamps() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ 1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 0, /* duration= */ 100), + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 200, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 150, /* duration= */ 60), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 300, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20), - new StepSegment(/* amplitude= */ 0.8f, /* frequency= */ -1, /* duration= */ 60))); + /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20), + new StepSegment(/* amplitude= */ 0.8f, /* frequencyHz= */ 10, /* duration= */ 60))); List expectedSegments = Arrays.asList( new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 10), + /* startFrequencyHz= */ 200, /* endFrequencyHz= */ 200, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ 0, /* endFrequency= */ 0, /* duration= */ 100), + /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 60), new RampSegment(/* startAmplitude= */ 1, /* endAmplitude= */ 1, - /* startFrequency= */ -4, /* endFrequency= */ 2, /* duration= */ 50), + /* startFrequencyHz= */ 1, /* endFrequencyHz= */ 300, /* duration= */ 50), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.2f, - /* startFrequency= */ 10, /* endFrequency= */ -5, /* duration= */ 20), + /* startFrequencyHz= */ 1000, /* endFrequencyHz= */ 1, /* duration= */ 20), new RampSegment(/* startAmplitude= */ 0.8f, /* endAmplitude= */ 0.8f, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 60)); + /* startFrequencyHz= */ 10, /* endFrequencyHz= */ 10, /* duration= */ 60)); VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); @@ -165,13 +173,13 @@ public class StepToRampAdapterTest { @Test public void testStepSegments_withPwleCapabilityAndFrequency_convertsStepsToRamps() { List segments = new ArrayList<>(Arrays.asList( - new StepSegment(/* amplitude= */ 0, /* frequency= */ -1, /* duration= */ 10), - new StepSegment(/* amplitude= */ 0.5f, /* frequency= */ 1, /* duration= */ 100))); + new StepSegment(/* amplitude= */ 0, /* frequencyHz= */ 100, /* duration= */ 10), + new StepSegment(/* amplitude= */ 0.5f, /* frequencyHz= */ 0, /* duration= */ 6))); List expectedSegments = Arrays.asList( new RampSegment(/* startAmplitude= */ 0, /* endAmplitude*/ 0, - /* startFrequency= */ -1, /* endFrequency= */ -1, /* duration= */ 10), + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 100, /* duration= */ 10), new RampSegment(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ 1, /* endFrequency= */ 1, /* duration= */ 100)); + /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 6)); VibratorInfo vibratorInfo = createVibratorInfo(IVibrator.CAP_COMPOSE_PWLE_EFFECTS); assertEquals(-1, mAdapter.apply(segments, -1, vibratorInfo)); @@ -183,6 +191,7 @@ public class StepToRampAdapterTest { private static VibratorInfo createVibratorInfo(int... capabilities) { return new VibratorInfo.Builder(0) .setCapabilities(IntStream.of(capabilities).reduce((a, b) -> a | b).orElse(0)) + .setFrequencyMapping(TEST_FREQUENCY_MAPPING) .build(); } } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java index 4cc4d55f228da..bfceb9abba2e8 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationThreadTest.java @@ -553,8 +553,8 @@ public class VibrationThreadTest { VibrationEffect effect = VibrationEffect.startWaveform() .addStep(1, 10) .addRamp(0, 20) - .addStep(0.8f, 1, 30) - .addRamp(0.6f, -1, 40) + .addStep(0.8f, 100, 30) + .addRamp(0.6f, 200, 40) .build(); VibrationThread thread = startThreadAndDispatcher(vibrationId, effect); waitForCompletion(thread); @@ -565,12 +565,13 @@ public class VibrationThreadTest { verifyCallbacksTriggered(vibrationId, Vibration.Status.FINISHED); assertFalse(thread.getVibrators().get(VIBRATOR_ID).isVibrating()); assertEquals(Arrays.asList( - expectedRamp(/* amplitude= */ 1, /* frequency= */ 150, /* duration= */ 10), - expectedRamp(/* StartAmplitude= */ 1, /* endAmplitude= */ 0, - /* startFrequency= */ 150, /* endFrequency= */ 150, /* duration= */ 20), - expectedRamp(/* amplitude= */ 0.6f, /* frequency= */ 200, /* duration= */ 30), - expectedRamp(/* StartAmplitude= */ 0.6f, /* endAmplitude= */ 0.5f, - /* startFrequency= */ 200, /* endFrequency= */ 100, /* duration= */ 40)), + expectedRamp(/* amplitude= */ 1, /* frequencyHz= */ 150, /* duration= */ 10), + expectedRamp(/* startAmplitude= */ 1, /* endAmplitude= */ 0, + /* startFrequencyHz= */ 150, /* endFrequencyHz= */ 150, /* duration= */ 20), + expectedRamp(/* amplitude= */ 0.5f, /* frequencyHz= */ 100, /* duration= */ 30), + expectedRamp(/* startAmplitude= */ 0.5f, /* endAmplitude= */ 0.6f, + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 200, + /* duration= */ 40)), fakeVibrator.getEffectSegments()); assertEquals(Arrays.asList(Braking.CLAB), fakeVibrator.getBraking()); } @@ -589,8 +590,8 @@ public class VibrationThreadTest { VibrationEffect effect = VibrationEffect.startWaveform() .addStep(1, 10) .addRamp(0, 20) - .addStep(0.8f, 1, 30) - .addRamp(0.6f, -1, 40) + .addStep(0.8f, 10, 30) + .addRamp(0.6f, 100, 40) .build(); VibrationThread thread = startThreadAndDispatcher(vibrationId, effect); waitForCompletion(thread); @@ -1345,7 +1346,8 @@ public class VibrationThreadTest { } private VibrationEffectSegment expectedOneShot(long millis) { - return new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE, /* frequency= */ 0, (int) millis); + return new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE, + /* frequencyHz= */ 0, (int) millis); } private VibrationEffectSegment expectedPrebaked(int effectId) { @@ -1356,13 +1358,13 @@ public class VibrationThreadTest { return new PrimitiveSegment(primitiveId, scale, delay); } - private VibrationEffectSegment expectedRamp(float amplitude, float frequency, int duration) { - return expectedRamp(amplitude, amplitude, frequency, frequency, duration); + private VibrationEffectSegment expectedRamp(float amplitude, float frequencyHz, int duration) { + return expectedRamp(amplitude, amplitude, frequencyHz, frequencyHz, duration); } private VibrationEffectSegment expectedRamp(float startAmplitude, float endAmplitude, - float startFrequency, float endFrequency, int duration) { - return new RampSegment(startAmplitude, endAmplitude, startFrequency, endFrequency, + float startFrequencyHz, float endFrequencyHz, int duration) { + return new RampSegment(startAmplitude, endAmplitude, startFrequencyHz, endFrequencyHz, duration); } diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java index 9fb8b38a706e5..cb4982be40c30 100644 --- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorControllerTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyFloat; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; @@ -236,7 +235,7 @@ public class VibratorControllerTest { RampSegment[] primitives = new RampSegment[]{ new RampSegment(/* startAmplitude= */ 0, /* endAmplitude= */ 1, - /* startFrequency= */ -1, /* endFrequency= */ 1, /* duration= */ 10) + /* startFrequencyHz= */ 100, /* endFrequencyHz= */ 200, /* duration= */ 10) }; assertEquals(15L, controller.on(primitives, 12)); assertTrue(controller.isVibrating()); @@ -312,10 +311,10 @@ public class VibratorControllerTest { private void mockVibratorCapabilities(int capabilities) { VibratorInfo.FrequencyMapping frequencyMapping = new VibratorInfo.FrequencyMapping( - Float.NaN, Float.NaN, Float.NaN, Float.NaN, null); - when(mNativeWrapperMock.getInfo(anyFloat(), any(VibratorInfo.Builder.class))) + Float.NaN, Float.NaN, Float.NaN, null); + when(mNativeWrapperMock.getInfo(any(VibratorInfo.Builder.class))) .then(invocation -> { - ((VibratorInfo.Builder) invocation.getArgument(1)) + ((VibratorInfo.Builder) invocation.getArgument(0)) .setCapabilities(capabilities) .setFrequencyMapping(frequencyMapping); return true;