summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/os/VibrationEffect.java43
-rw-r--r--core/tests/vibrator/src/android/os/VibrationEffectTest.java86
3 files changed, 131 insertions, 0 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 4cb791a9db1f..69728d37ccef 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -34373,6 +34373,8 @@ package android.os {
public abstract class VibrationEffect implements android.os.Parcelable {
method public static android.os.VibrationEffect createOneShot(long, int);
method @NonNull public static android.os.VibrationEffect createPredefined(int);
+ method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public static android.os.VibrationEffect createRepeatingEffect(@NonNull android.os.VibrationEffect);
+ method @FlaggedApi("android.os.vibrator.normalized_pwle_effects") @NonNull public static android.os.VibrationEffect createRepeatingEffect(@NonNull android.os.VibrationEffect, @NonNull android.os.VibrationEffect);
method public static android.os.VibrationEffect createWaveform(long[], int);
method public static android.os.VibrationEffect createWaveform(long[], int[], int);
method public int describeContents();
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index d8094ab0f748..a3844e244edb 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -1404,6 +1404,49 @@ public abstract class VibrationEffect implements Parcelable {
}
/**
+ * Creates a new {@link VibrationEffect} that repeats the given effect indefinitely.
+ *
+ * <p>The input vibration must not be a repeating vibration. If it is, an
+ * {@link IllegalArgumentException} will be thrown.
+ *
+ * @param effect The {@link VibrationEffect} that will be repeated.
+ * @return A {@link VibrationEffect} that repeats the effect indefinitely.
+ * @throws IllegalArgumentException if the effect is already a repeating vibration.
+ */
+ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @NonNull
+ public static VibrationEffect createRepeatingEffect(@NonNull VibrationEffect effect) {
+ return VibrationEffect.startComposition()
+ .repeatEffectIndefinitely(effect)
+ .compose();
+ }
+
+ /**
+ * Creates a new {@link VibrationEffect} by merging the preamble and repeating vibration effect.
+ *
+ * <p>Neither input vibration may already be repeating. An {@link IllegalArgumentException} will
+ * be thrown if either input vibration is set to repeat indefinitely.
+ *
+ * @param preamble The starting vibration effect, which must be finite.
+ * @param repeatingEffect The vibration effect to be repeated indefinitely after the preamble.
+ * @return A {@link VibrationEffect} that plays the preamble once followed by the
+ * `repeatingEffect` indefinitely.
+ * @throws IllegalArgumentException if either preamble or repeatingEffect is already a repeating
+ * vibration.
+ */
+ @FlaggedApi(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ @NonNull
+ public static VibrationEffect createRepeatingEffect(@NonNull VibrationEffect preamble,
+ @NonNull VibrationEffect repeatingEffect) {
+ Preconditions.checkArgument(preamble.getDuration() < Long.MAX_VALUE,
+ "Can't repeat an indefinitely repeating effect.");
+ return VibrationEffect.startComposition()
+ .addEffect(preamble)
+ .repeatEffectIndefinitely(repeatingEffect)
+ .compose();
+ }
+
+ /**
* A composition of haptic elements that are combined to be playable as a single
* {@link VibrationEffect}.
*
diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
index 8a250bdd5459..beb69858a85c 100644
--- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java
+++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
@@ -403,6 +403,17 @@ public class VibrationEffectTest {
@Test
@EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ public void computeLegacyPattern_repeatingEffect() {
+ VibrationEffect repeatingEffect = VibrationEffect.createRepeatingEffect(TEST_ONE_SHOT,
+ TEST_WAVEFORM);
+ assertNull(repeatingEffect.computeCreateWaveformOffOnTimingsOrNull());
+
+ repeatingEffect = VibrationEffect.createRepeatingEffect(TEST_WAVEFORM);
+ assertNull(repeatingEffect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
public void computeLegacyPattern_effectsViaStartWaveformEnvelope() {
// Effects created via startWaveformEnvelope are not expected to be converted to long[]
// patterns, as they are not configured to always play with the default amplitude.
@@ -526,6 +537,17 @@ public class VibrationEffectTest {
}
@Test
+ @EnableFlags(Flags.FLAG_NORMALIZED_PWLE_EFFECTS)
+ public void cropToLength_repeatingEffect() {
+ VibrationEffect repeatingEffect = VibrationEffect.createRepeatingEffect(TEST_ONE_SHOT,
+ TEST_WAVEFORM);
+ assertThat(repeatingEffect.cropToLengthOrNull(1)).isNull();
+
+ repeatingEffect = VibrationEffect.createRepeatingEffect(TEST_WAVEFORM);
+ assertThat(repeatingEffect.cropToLengthOrNull(1)).isNull();
+ }
+
+ @Test
public void getRingtones_noPrebakedRingtones() {
Resources r = mockRingtoneResources(new String[0]);
Context context = mockContext(r);
@@ -621,6 +643,30 @@ public class VibrationEffectTest {
.build()
.validate();
+ VibrationEffect.createRepeatingEffect(
+ /*preamble=*/ VibrationEffect.startWaveformEnvelope()
+ .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f,
+ /*timeMillis=*/ 20)
+ .addControlPoint(/*amplitude=*/ 0.3f, /*frequencyHz=*/ 100f,
+ /*timeMillis=*/ 50)
+ .build(),
+ /*repeatingEffect=*/ VibrationEffect.startWaveformEnvelope()
+ .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f,
+ /*timeMillis=*/ 20)
+ .addControlPoint(/*amplitude=*/ 0.5f, /*frequencyHz=*/ 150f,
+ /*timeMillis=*/ 100)
+ .build()
+ ).validate();
+
+ VibrationEffect.createRepeatingEffect(
+ /*effect=*/ VibrationEffect.startWaveformEnvelope()
+ .addControlPoint(/*amplitude=*/ 0.0f, /*frequencyHz=*/ 60f,
+ /*timeMillis=*/ 20)
+ .addControlPoint(/*amplitude=*/ 0.5f, /*frequencyHz=*/ 150f,
+ /*timeMillis=*/ 100)
+ .build()
+ ).validate();
+
assertThrows(IllegalStateException.class,
() -> VibrationEffect.startWaveformEnvelope().build().validate());
assertThrows(IllegalArgumentException.class,
@@ -725,6 +771,21 @@ public class VibrationEffectTest {
.repeatEffectIndefinitely(TEST_ONE_SHOT)
.compose()
.validate();
+ VibrationEffect.startComposition()
+ .addEffect(TEST_ONE_SHOT)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK)
+ .addEffect(VibrationEffect.createRepeatingEffect(
+ /*preamble=*/ VibrationEffect.createPredefined(
+ VibrationEffect.EFFECT_DOUBLE_CLICK),
+ /*repeatingEffect=*/ TEST_WAVEFORM))
+ .compose()
+ .validate();
+ VibrationEffect.startComposition()
+ .addEffect(TEST_ONE_SHOT)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK)
+ .addEffect(VibrationEffect.createRepeatingEffect(TEST_WAVEFORM))
+ .compose()
+ .validate();
// Make sure class summary javadoc examples compile and are valid.
// NOTE: IF THIS IS UPDATED, PLEASE ALSO UPDATE Composition javadocs.
@@ -787,6 +848,31 @@ public class VibrationEffectTest {
.addEffect(TEST_ONE_SHOT)
.compose()
.validate());
+
+ assertThrows(UnreachableAfterRepeatingIndefinitelyException.class,
+ () -> VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.createRepeatingEffect(
+ /*preamble=*/ VibrationEffect.createPredefined(
+ VibrationEffect.EFFECT_DOUBLE_CLICK),
+ /*repeatingEffect=*/ TEST_WAVEFORM))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose()
+ .validate());
+ assertThrows(UnreachableAfterRepeatingIndefinitelyException.class,
+ () -> VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.createRepeatingEffect(
+ /*preamble=*/ VibrationEffect.createPredefined(
+ VibrationEffect.EFFECT_DOUBLE_CLICK),
+ /*repeatingEffect=*/ TEST_WAVEFORM))
+ .addEffect(TEST_ONE_SHOT)
+ .compose()
+ .validate());
+ assertThrows(UnreachableAfterRepeatingIndefinitelyException.class,
+ () -> VibrationEffect.startComposition()
+ .addEffect(VibrationEffect.createRepeatingEffect(TEST_WAVEFORM))
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose()
+ .validate());
}
@Test