Merge "Remove startWaveformEffect APIs" into main
diff --git a/core/api/current.txt b/core/api/current.txt
index f660158..19a32c1 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -34737,8 +34737,6 @@
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
@@ -34766,8 +34764,10 @@
}
@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 {
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 70cbc73..f6bc389 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -1826,52 +1826,6 @@
}
/**
- * 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.
*
* <p>Waveform effect envelopes are defined by one or more control points describing a target
@@ -1882,7 +1836,7 @@
* 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 @@
* {@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 @@
* 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 @@
@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 @@
* 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
diff --git a/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java b/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java
index f2ad7a4..afaab55 100644
--- a/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java
+++ b/core/java/android/os/vibrator/VibratorEnvelopeEffectInfo.java
@@ -34,11 +34,11 @@
* </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)
diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
index 1cd1190..ccc5108 100644
--- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java
+++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
@@ -414,10 +414,10 @@
@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 @@
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 @@
@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 @@
.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 @@
.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 @@
).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 @@
).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 @@
@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 @@
@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)
diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
index b9fab61..eb44daa 100644
--- a/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
+++ b/services/tests/vibrator/src/com/android/server/vibrator/VibrationThreadTest.java
@@ -904,7 +904,7 @@
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)
@@ -939,12 +939,14 @@
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();