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

Commit 362de5c3 authored by Ahmad Khalil's avatar Ahmad Khalil
Browse files

Remove startWaveformEffect APIs

We're removing the `startWaveformEffect` APIs and exposing the `WaveformEnvelopeBuilder` instead. Setting initial frequency is now part of the builder and can be set using `setInitialFrequencyHz`.

Bug: 378969646
Flag: android.os.vibrator.normalized_pwle_effects
Test: atest FrameworksVibratorCoreTests
Change-Id: Icf741057e03f3fd5f2999aa27dcae0b395f8b1ea
parent a7f04eea
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -34731,8 +34731,6 @@ package android.os {
    method public static android.os.VibrationEffect createWaveform(long[], int[], int);
    method public int describeContents();
    method @NonNull public static android.os.VibrationEffect.Composition startComposition();
    method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public static android.os.VibrationEffect.WaveformEnvelopeBuilder startWaveformEnvelope();
    method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public static android.os.VibrationEffect.WaveformEnvelopeBuilder startWaveformEnvelope(@FloatRange(from=0) float);
    field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect> CREATOR;
    field public static final int DEFAULT_AMPLITUDE = -1; // 0xffffffff
    field public static final int EFFECT_CLICK = 0; // 0x0
@@ -34760,8 +34758,10 @@ package android.os {
  }
  @FlaggedApi("android.os.vibrator.normalized_pwle_effects") public static final class VibrationEffect.WaveformEnvelopeBuilder {
    ctor public VibrationEffect.WaveformEnvelopeBuilder();
    method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public android.os.VibrationEffect.WaveformEnvelopeBuilder addControlPoint(@FloatRange(from=0, to=1) float, @FloatRange(from=0) float, int);
    method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public android.os.VibrationEffect build();
    method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public android.os.VibrationEffect.WaveformEnvelopeBuilder setInitialFrequencyHz(@FloatRange(from=0) float);
  }
  public abstract class Vibrator {
+39 −58
Original line number Diff line number Diff line
@@ -1825,52 +1825,6 @@ public abstract class VibrationEffect implements Parcelable {
        }
    }

    /**
     * Start building a waveform vibration.
     *
     * <p>The waveform envelope builder offers more flexibility for creating waveform effects,
     * allowing control over vibration amplitude and frequency via smooth transitions between
     * values. The waveform will start the first transition from the vibrator off state, using
     * the same frequency of the first control point. To provide a different initial vibration
     * frequency, use {@link #startWaveformEnvelope(float)}.
     *
     * <p>Note: To check whether waveform envelope effects are supported, use
     * {@link Vibrator#areEnvelopeEffectsSupported()}.
     *
     * @see VibrationEffect.WaveformEnvelopeBuilder
     */
    @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
    @NonNull
    public static VibrationEffect.WaveformEnvelopeBuilder startWaveformEnvelope() {
        return new WaveformEnvelopeBuilder();
    }

    /**
     * Start building a waveform vibration with an initial frequency.
     *
     * <p>The waveform envelope builder offers more flexibility for creating waveform effects,
     * allowing control over vibration amplitude and frequency via smooth transitions between
     * values.
     *
     * <p>This is the same as {@link #startWaveformEnvelope()}, but the waveform will start
     * vibrating at given frequency, in hertz, while it transitions to the new amplitude and
     * frequency of the first control point.
     *
     * <p>Note: To check whether waveform envelope effects are supported, use
     * {@link Vibrator#areEnvelopeEffectsSupported()}.
     *
     * @param initialFrequencyHz The starting frequency of the vibration, in hertz. Must be greater
     *                           than zero.
     *
     * @see VibrationEffect.WaveformEnvelopeBuilder
     */
    @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
    @NonNull
    public static VibrationEffect.WaveformEnvelopeBuilder startWaveformEnvelope(
            @FloatRange(from = 0) float initialFrequencyHz) {
        return new WaveformEnvelopeBuilder(initialFrequencyHz);
    }

    /**
     * A builder for waveform effects described by its envelope.
     *
@@ -1882,7 +1836,7 @@ public abstract class VibrationEffect implements Parcelable {
     * 100ms, holds that state for 200ms, and then ramps back down over 100ms:
     *
     * <pre>{@code
     * VibrationEffect effect = VibrationEffect.startWaveformEnvelope()
     * VibrationEffect effect = new VibrationEffect.WaveformEnvelopeBuilder()
     *     .addControlPoint(1.0f, 120f, 100)
     *     .addControlPoint(1.0f, 120f, 200)
     *     .addControlPoint(0.0f, 120f, 100)
@@ -1916,20 +1870,48 @@ public abstract class VibrationEffect implements Parcelable {
     * {@link VibratorEnvelopeEffectInfo#getMaxControlPointDurationMillis()}
     * <li>Maximum total effect duration: {@link VibratorEnvelopeEffectInfo#getMaxDurationMillis()}
     * </ul>
     *
     * @see VibrationEffect#startWaveformEnvelope()
     */
    @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
    public static final class WaveformEnvelopeBuilder {

        private ArrayList<PwleSegment> mSegments = new ArrayList<>();
        private float mLastAmplitude = 0f;
        private float mLastFrequencyHz = 0f;
        private float mLastFrequencyHz = Float.NaN;

        private WaveformEnvelopeBuilder() {}
        public WaveformEnvelopeBuilder() {}

        private WaveformEnvelopeBuilder(float initialFrequency) {
            mLastFrequencyHz = initialFrequency;
        /**
         * Sets the initial frequency for the waveform in Hertz.
         *
         * <p>The effect will start vibrating at this frequency when it transitions to the
         * amplitude and frequency defined by the first control point.
         *
         * <p>The frequency must be greater than zero and within the supported range. To determine
         * the supported range, use {@link Vibrator#getFrequencyProfile()}. Creating
         * effects using frequencies outside this range will result in the vibration not playing.
         *
         * @param initialFrequencyHz The starting frequency of the vibration, in Hz. Must be
         *                           greater than zero.
         */
        @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
        @SuppressWarnings("MissingGetterMatchingBuilder")// No getter to initial frequency once set.
        @NonNull
        public WaveformEnvelopeBuilder setInitialFrequencyHz(
                @FloatRange(from = 0) float initialFrequencyHz) {

            if (mSegments.isEmpty()) {
                mLastFrequencyHz = initialFrequencyHz;
            } else {
                PwleSegment firstSegment = mSegments.getFirst();
                mSegments.set(0, new PwleSegment(
                        firstSegment.getStartAmplitude(),
                        firstSegment.getEndAmplitude(),
                        initialFrequencyHz, // Update start frequency
                        firstSegment.getEndFrequencyHz(),
                        (int) firstSegment.getDuration()));
            }

            return this;
        }

        /**
@@ -1940,15 +1922,13 @@ public abstract class VibrationEffect implements Parcelable {
         * perceived intensity. It's determined by the actuator response curve.
         *
         * <p>Frequency must be greater than zero and within the supported range. To determine
         * the supported range, use {@link Vibrator#getFrequencyProfile()}. This method returns a
         * {@link android.os.vibrator.VibratorFrequencyProfile} object, which contains the
         * minimum and maximum frequencies, among other frequency-related information. Creating
         * the supported range, use {@link Vibrator#getFrequencyProfile()}. Creating
         * effects using frequencies outside this range will result in the vibration not playing.
         *
         * <p>Time specifies the duration (in milliseconds) for the vibrator to smoothly transition
         * from the previous control point to this new one. It must be greater than zero. To
         * transition as quickly as possible, use
         * {@link Vibrator#getMinEnvelopeEffectControlPointDurationMillis()}.
         * {@link VibratorEnvelopeEffectInfo#getMinControlPointDurationMillis()}.
         *
         * @param amplitude   The amplitude value between 0 and 1, inclusive. 0 represents the
         *                    vibrator being off, and 1 represents the maximum achievable amplitude
@@ -1963,7 +1943,7 @@ public abstract class VibrationEffect implements Parcelable {
                @FloatRange(from = 0, to = 1) float amplitude,
                @FloatRange(from = 0) float frequencyHz, int timeMillis) {

            if (mLastFrequencyHz == 0) {
            if (Float.isNaN(mLastFrequencyHz)) {
                mLastFrequencyHz = frequencyHz;
            }

@@ -1984,6 +1964,7 @@ public abstract class VibrationEffect implements Parcelable {
         * calling this method again.
         *
         * @return The {@link VibrationEffect} resulting from the list of control points.
         * @throws IllegalStateException if no control points were added to the builder.
         */
        @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
        @NonNull
+2 −2
Original line number Diff line number Diff line
@@ -34,11 +34,11 @@ import java.util.Objects;
 * </ul>
 *
 * <p>This information can be used to help construct waveform envelope effects with
 * {@link VibrationEffect#startWaveformEnvelope()}. When designing these effects, it is also
 * {@link VibrationEffect.WaveformEnvelopeBuilder}. When designing these effects, it is also
 * recommended to check the {@link VibratorFrequencyProfile} for information about the supported
 * frequency range and the vibrator's output response.
 *
 * @see VibrationEffect#startWaveformEnvelope()
 * @see VibrationEffect.WaveformEnvelopeBuilder
 * @see VibratorFrequencyProfile
 */
@FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+38 −23
Original line number Diff line number Diff line
@@ -414,10 +414,10 @@ public class VibrationEffectTest {

    @Test
    @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
    public void computeLegacyPattern_effectsViaStartWaveformEnvelope() {
        // Effects created via startWaveformEnvelope are not expected to be converted to long[]
    public void computeLegacyPattern_effectsViaWaveformEnvelopeBuilder() {
        // Effects created via waveformEnvelopeBuilder are not expected to be converted to long[]
        // patterns, as they are not configured to always play with the default amplitude.
        VibrationEffect effect = VibrationEffect.startWaveformEnvelope()
        VibrationEffect effect = new VibrationEffect.WaveformEnvelopeBuilder()
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 20)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 50)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 80)
@@ -426,7 +426,8 @@ public class VibrationEffectTest {

        assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());

        effect = VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/ 60)
        effect = new VibrationEffect.WaveformEnvelopeBuilder()
                .setInitialFrequencyHz(/*initialFrequencyHz=*/ 60)
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 20)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 50)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 80)
@@ -644,7 +645,7 @@ public class VibrationEffectTest {
    @Test
    @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
    public void testValidateWaveformEnvelopeBuilder() {
        VibrationEffect.startWaveformEnvelope()
        new VibrationEffect.WaveformEnvelopeBuilder()
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 20)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 50)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 80)
@@ -652,7 +653,8 @@ public class VibrationEffectTest {
                .build()
                .validate();

        VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/ 30)
        new VibrationEffect.WaveformEnvelopeBuilder()
                .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 20)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 50)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 80)
@@ -661,13 +663,13 @@ public class VibrationEffectTest {
                .validate();

        VibrationEffect.createRepeatingEffect(
                /*preamble=*/ VibrationEffect.startWaveformEnvelope()
                /*preamble=*/ new VibrationEffect.WaveformEnvelopeBuilder()
                        .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f,
                                /*timeMillis=*/ 20)
                        .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f,
                                /*timeMillis=*/ 50)
                        .build(),
                /*repeatingEffect=*/ VibrationEffect.startWaveformEnvelope()
                /*repeatingEffect=*/ new VibrationEffect.WaveformEnvelopeBuilder()
                        .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f,
                                /*timeMillis=*/ 20)
                        .addControlPoint(/*amplitude=*/ 0.5f, /*frequencyHz=*/ 150f,
@@ -676,7 +678,7 @@ public class VibrationEffectTest {
        ).validate();

        VibrationEffect.createRepeatingEffect(
                /*effect=*/ VibrationEffect.startWaveformEnvelope()
                /*effect=*/ new VibrationEffect.WaveformEnvelopeBuilder()
                        .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f,
                                /*timeMillis=*/ 20)
                        .addControlPoint(/*amplitude=*/ 0.5f, /*frequencyHz=*/ 150f,
@@ -685,59 +687,70 @@ public class VibrationEffectTest {
        ).validate();

        assertThrows(IllegalStateException.class,
                () -> VibrationEffect.startWaveformEnvelope().build().validate());
                () -> new VibrationEffect.WaveformEnvelopeBuilder().build().validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope()
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .addControlPoint(/*amplitude=*/ -1.0f, /*frequencyHz=*/ 60f,
                                /*timeMillis=*/ 20)
                        .build()
                        .validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope()
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .addControlPoint(/*amplitude=*/ 1.1f, /*frequencyHz=*/ 60f,
                                /*timeMillis=*/ 20)
                        .build()
                        .validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope()
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .addControlPoint(/*amplitude=*/ 0.8f, /*frequencyHz=*/ 0f,
                                /*timeMillis=*/ 20)
                        .build()
                        .validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope()
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .addControlPoint(/*amplitude=*/ 0.8f, /*frequencyHz=*/ 100f,
                                /*timeMillis=*/ 0)
                        .build()
                        .validate());

        assertThrows(IllegalStateException.class,
                () -> VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/30)
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                        .build().validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/30)
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                        .addControlPoint(/*amplitude=*/ -1.0f, /*frequencyHz=*/ 60f,
                                /*timeMillis=*/ 20)
                        .build()
                        .validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/30)
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                        .addControlPoint(/*amplitude=*/ 1.1f, /*frequencyHz=*/ 60f,
                                /*timeMillis=*/ 20)
                        .build()
                        .validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/30)
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                        .addControlPoint(/*amplitude=*/ 0.8f, /*frequencyHz=*/ 0f,
                                /*timeMillis=*/ 20)
                        .build()
                        .validate());
        assertThrows(IllegalArgumentException.class,
                () -> VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/30)
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                        .addControlPoint(/*amplitude=*/ 0.8f, /*frequencyHz=*/ 100f,
                                /*timeMillis=*/ 0)
                        .build()
                        .validate());
        assertThrows(IllegalArgumentException.class,
                () -> new VibrationEffect.WaveformEnvelopeBuilder()
                        .setInitialFrequencyHz(/*initialFrequencyHz=*/ 0)
                        .addControlPoint(/*amplitude=*/ 0.8f, /*frequencyHz=*/ 100f,
                                /*timeMillis=*/ 20)
                        .build().validate());
    }

    @Test
@@ -1381,14 +1394,15 @@ public class VibrationEffectTest {
    @Test
    @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
    public void testIsHapticFeedbackCandidate_longEnvelopeEffects_notCandidates() {
        assertFalse(VibrationEffect.startWaveformEnvelope()
        assertFalse(new VibrationEffect.WaveformEnvelopeBuilder()
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 200)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 500)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 800)
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 400)
                .build()
                .isHapticFeedbackCandidate());
        assertFalse(VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/ 40)
        assertFalse(new VibrationEffect.WaveformEnvelopeBuilder()
                .setInitialFrequencyHz(/*initialFrequencyHz=*/ 40)
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 200)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 500)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 800)
@@ -1413,13 +1427,14 @@ public class VibrationEffectTest {
    @Test
    @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
    public void testIsHapticFeedbackCandidate_shortEnvelopeEffects_areCandidates() {
        assertTrue(VibrationEffect.startWaveformEnvelope()
        assertTrue(new VibrationEffect.WaveformEnvelopeBuilder()
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 500)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 400)
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 100)
                .build()
                .isHapticFeedbackCandidate());
        assertTrue(VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/ 30)
        assertTrue(new VibrationEffect.WaveformEnvelopeBuilder()
                .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 500)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 400)
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 100)
+4 −2
Original line number Diff line number Diff line
@@ -887,7 +887,7 @@ public class VibrationThreadTest {
        fakeVibrator.setMaxEnvelopeEffectSize(10);
        fakeVibrator.setMinEnvelopeEffectControlPointDurationMillis(20);

        VibrationEffect effect = VibrationEffect.startWaveformEnvelope()
        VibrationEffect effect = new VibrationEffect.WaveformEnvelopeBuilder()
                .addControlPoint(/*amplitude=*/ 0.1f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 20)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 30)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 20)
@@ -922,12 +922,14 @@ public class VibrationThreadTest {
        fakeVibrator.setMaxEnvelopeEffectSize(10);
        fakeVibrator.setMinEnvelopeEffectControlPointDurationMillis(20);

        VibrationEffect effect = VibrationEffect.startWaveformEnvelope(/*initialFrequency=*/ 30)
        VibrationEffect effect = new VibrationEffect.WaveformEnvelopeBuilder()
                .setInitialFrequencyHz(/*initialFrequencyHz=*/ 30)
                .addControlPoint(/*amplitude=*/ 0.1f, /*frequencyHz=*/ 60f, /*timeMillis=*/ 20)
                .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f, /*timeMillis=*/ 30)
                .addControlPoint(/*amplitude=*/ 0.4f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 20)
                .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 120f, /*timeMillis=*/ 30)
                .build();

        HalVibration vibration = startThreadAndDispatcher(effect);
        waitForCompletion();