Loading core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -34380,6 +34380,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(); core/java/android/os/VibrationEffect.java +43 −0 Original line number Diff line number Diff line Loading @@ -1403,6 +1403,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}. Loading core/tests/vibrator/src/android/os/VibrationEffectTest.java +86 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,17 @@ public class VibrationEffectTest { assertNull(effect.computeCreateWaveformOffOnTimingsOrNull()); } @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() { Loading Loading @@ -525,6 +536,17 @@ public class VibrationEffectTest { assertThat(effect.cropToLengthOrNull(2)).isNull(); } @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]); Loading Loading @@ -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, Loading Loading @@ -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. Loading Loading @@ -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 Loading Loading
core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -34380,6 +34380,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();
core/java/android/os/VibrationEffect.java +43 −0 Original line number Diff line number Diff line Loading @@ -1403,6 +1403,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}. Loading
core/tests/vibrator/src/android/os/VibrationEffectTest.java +86 −0 Original line number Diff line number Diff line Loading @@ -401,6 +401,17 @@ public class VibrationEffectTest { assertNull(effect.computeCreateWaveformOffOnTimingsOrNull()); } @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() { Loading Loading @@ -525,6 +536,17 @@ public class VibrationEffectTest { assertThat(effect.cropToLengthOrNull(2)).isNull(); } @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]); Loading Loading @@ -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, Loading Loading @@ -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. Loading Loading @@ -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 Loading