Loading core/api/current.txt +21 −0 Original line number Diff line number Diff line Loading @@ -31928,6 +31928,9 @@ 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 @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(); method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter); method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); 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 Loading @@ -31937,10 +31940,13 @@ package android.os { } public static final class VibrationEffect.Composition { method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect); method @NonNull public android.os.VibrationEffect.Composition addOffDuration(@NonNull java.time.Duration); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect compose(); method @NonNull public android.os.VibrationEffect.Composition repeatEffectIndefinitely(@NonNull android.os.VibrationEffect); field public static final int PRIMITIVE_CLICK = 1; // 0x1 field public static final int PRIMITIVE_LOW_TICK = 8; // 0x8 field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6 Loading @@ -31951,6 +31957,21 @@ package android.os { field public static final int PRIMITIVE_TICK = 7; // 0x7 } public static final class VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException extends java.lang.IllegalStateException { } public static class VibrationEffect.VibrationParameter { method @NonNull public static android.os.VibrationEffect.VibrationParameter targetAmplitude(@FloatRange(from=0, to=1) float); method @NonNull public static android.os.VibrationEffect.VibrationParameter targetFrequency(@FloatRange(from=1) float); } public static final class VibrationEffect.WaveformBuilder { method @NonNull public android.os.VibrationEffect.WaveformBuilder addSustain(@NonNull java.time.Duration); method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter); method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); method @NonNull public android.os.VibrationEffect build(); } public abstract class Vibrator { method public final int areAllEffectsSupported(@NonNull int...); method public final boolean areAllPrimitivesSupported(@NonNull int...); core/api/test-current.txt +0 −15 Original line number Diff line number Diff line Loading @@ -1793,7 +1793,6 @@ package android.os { method public static android.os.VibrationEffect get(int, boolean); method @Nullable public static android.os.VibrationEffect get(android.net.Uri, android.content.Context); method public abstract long getDuration(); method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(); field public static final int EFFECT_POP = 4; // 0x4 field public static final int EFFECT_STRENGTH_LIGHT = 0; // 0x0 field public static final int EFFECT_STRENGTH_MEDIUM = 1; // 0x1 Loading @@ -1811,20 +1810,6 @@ package android.os { field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Composed> CREATOR; } public static final class VibrationEffect.Composition { method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect); method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect, @IntRange(from=0) int); } 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) 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) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect build(); method @NonNull public android.os.VibrationEffect build(int); } public abstract class Vibrator { method public int getDefaultVibrationIntensity(int); field public static final int VIBRATION_INTENSITY_HIGH = 3; // 0x3 Loading core/java/android/os/VibrationEffect.java +330 −151 File changed.Preview size limit exceeded, changes collapsed. Show changes core/tests/coretests/src/android/os/VibrationEffectTest.java +63 −37 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.os; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; Loading @@ -32,6 +35,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.net.Uri; import android.os.VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.StepSegment; Loading @@ -43,6 +47,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; import java.time.Duration; @Presubmit @RunWith(MockitoJUnitRunner.class) public class VibrationEffectTest { Loading Loading @@ -122,16 +128,7 @@ public class VibrationEffectTest { VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, -1).validate(); VibrationEffect.createWaveform(new long[]{10, 10}, new int[] {0, 0}, -1).validate(); VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, 0).validate(); VibrationEffect.startWaveform() .addStep(/* amplitude= */ 1, /* duration= */ 10) .addRamp(/* amplitude= */ 0, /* duration= */ 20) .addStep(/* amplitude= */ 1, /* frequencyHz= */ 1, /* duration= */ 100) .addRamp(/* amplitude= */ 0.5f, /* frequencyHz= */ 100, /* duration= */ 50) .build() .validate(); assertThrows(IllegalStateException.class, () -> VibrationEffect.startWaveform().build().validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.createWaveform(new long[0], new int[0], -1).validate()); assertThrows(IllegalArgumentException.class, Loading @@ -145,27 +142,31 @@ public class VibrationEffectTest { assertThrows(IllegalArgumentException.class, () -> VibrationEffect.createWaveform( TEST_TIMINGS, TEST_AMPLITUDES, TEST_TIMINGS.length).validate()); } @Test public void testValidateWaveformBuilder() { VibrationEffect.startWaveform(targetAmplitude(1)) .addTransition(Duration.ofSeconds(1), targetAmplitude(0.5f), targetFrequency(100)) .addTransition(Duration.ZERO, targetAmplitude(0f), targetFrequency(200)) .addSustain(Duration.ofMinutes(2)) .addTransition(Duration.ofMillis(10), targetAmplitude(1f), targetFrequency(50)) .addSustain(Duration.ofMillis(1)) .addTransition(Duration.ZERO, targetFrequency(150)) .addSustain(Duration.ofMillis(2)) .addTransition(Duration.ofSeconds(15), targetAmplitude(1)) .build() .validate(); assertThrows(IllegalStateException.class, () -> VibrationEffect.startWaveform().build().validate()); assertThrows(IllegalArgumentException.class, () -> targetAmplitude(-2)); assertThrows(IllegalArgumentException.class, () -> targetFrequency(0)); 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, 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()); () -> VibrationEffect.startWaveform().addTransition( Duration.ofMillis(-10), targetAmplitude(1)).build().validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startWaveform() .addRamp(1, 10f, /* duration= */ -3).build().validate()); () -> VibrationEffect.startWaveform().addSustain(Duration.ZERO).build().validate()); } @Test Loading @@ -174,14 +175,24 @@ public class VibrationEffectTest { .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK) .addEffect(TEST_ONE_SHOT) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f) .addEffect(TEST_WAVEFORM, 100) .addOffDuration(Duration.ofMillis(100)) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10) .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) .compose() .validate(); VibrationEffect.startComposition() .repeatEffectIndefinitely(TEST_ONE_SHOT) .compose() .validate(); assertThrows(IllegalStateException.class, () -> VibrationEffect.startComposition().compose().validate()); assertThrows(IllegalStateException.class, () -> VibrationEffect.startComposition() .addOffDuration(Duration.ofSeconds(0)) .compose() .validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startComposition().addPrimitive(-1).compose().validate()); assertThrows(IllegalArgumentException.class, Loading @@ -196,12 +207,27 @@ public class VibrationEffectTest { .validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startComposition() .addEffect(TEST_ONE_SHOT, /* delay= */ -10) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1) .compose() .validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1) .repeatEffectIndefinitely( // Repeating waveform. VibrationEffect.createWaveform( new long[] { 10 }, new int[] { 100}, 0)) .compose() .validate()); assertThrows(UnreachableAfterRepeatingIndefinitelyException.class, () -> VibrationEffect.startComposition() .repeatEffectIndefinitely(TEST_WAVEFORM) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK) .compose() .validate()); assertThrows(UnreachableAfterRepeatingIndefinitelyException.class, () -> VibrationEffect.startComposition() .repeatEffectIndefinitely(TEST_WAVEFORM) .addEffect(TEST_ONE_SHOT) .compose() .validate()); } Loading Loading @@ -354,9 +380,9 @@ public class VibrationEffectTest { assertFalse(VibrationEffect.createWaveform( new long[]{200, 200, 700}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate()); assertFalse(VibrationEffect.startWaveform() .addRamp(1, 500) .addStep(1, 200) .addRamp(0, 500) .addTransition(Duration.ofMillis(500), targetAmplitude(1)) .addTransition(Duration.ofMillis(200), targetAmplitude(0.5f)) .addTransition(Duration.ofMillis(500), targetAmplitude(0)) .build() .isHapticFeedbackCandidate()); } Loading @@ -367,9 +393,9 @@ public class VibrationEffectTest { assertTrue(VibrationEffect.createWaveform( new long[]{100, 200, 300}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate()); assertTrue(VibrationEffect.startWaveform() .addRamp(1, 300) .addStep(1, 200) .addRamp(0, 300) .addTransition(Duration.ofMillis(300), targetAmplitude(1)) .addTransition(Duration.ofMillis(200), targetAmplitude(0.5f)) .addTransition(Duration.ofMillis(300), targetAmplitude(0)) .build() .isHapticFeedbackCandidate()); } Loading services/core/java/com/android/server/notification/VibratorHelper.java +12 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.server.notification; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import android.annotation.Nullable; import android.content.Context; import android.content.res.Resources; Loading @@ -30,6 +33,7 @@ import android.util.Slog; import com.android.internal.R; import com.android.server.pm.PackageManagerService; import java.time.Duration; import java.util.Arrays; /** Loading Loading @@ -89,8 +93,7 @@ public final class VibratorHelper { * Safely create a {@link VibrationEffect} from given waveform description. * * <p>The waveform is described by a sequence of values for target amplitude, frequency and * duration, that are forwarded to * {@link VibrationEffect.WaveformBuilder#addRamp(float, float, int)}. * duration, that are forwarded to {@link VibrationEffect.WaveformBuilder#addTransition}. * * <p>This method returns {@code null} if the pattern is also {@code null} or invalid. * Loading @@ -114,16 +117,17 @@ public final class VibratorHelper { VibrationEffect.WaveformBuilder waveformBuilder = VibrationEffect.startWaveform(); for (int i = 0; i < length; i += 3) { waveformBuilder.addRamp( /* amplitude= */ values[i], /* frequencyHz= */ values[i + 1], /* duration= */ (int) values[i + 2]); waveformBuilder.addTransition(Duration.ofMillis((int) values[i + 2]), targetAmplitude(values[i]), targetFrequency(values[i + 1])); } VibrationEffect effect = waveformBuilder.build(); if (insistent) { return waveformBuilder.build(/* repeat= */ 0); return VibrationEffect.startComposition() .repeatEffectIndefinitely(effect) .compose(); } return waveformBuilder.build(); return effect; } catch (IllegalArgumentException e) { Slog.e(TAG, "Error creating vibration PWLE waveform with pattern: " + Arrays.toString(values)); Loading Loading
core/api/current.txt +21 −0 Original line number Diff line number Diff line Loading @@ -31928,6 +31928,9 @@ 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 @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(); method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter); method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(@NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); 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 Loading @@ -31937,10 +31940,13 @@ package android.os { } public static final class VibrationEffect.Composition { method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect); method @NonNull public android.os.VibrationEffect.Composition addOffDuration(@NonNull java.time.Duration); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float); method @NonNull public android.os.VibrationEffect.Composition addPrimitive(int, @FloatRange(from=0.0f, to=1.0f) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect compose(); method @NonNull public android.os.VibrationEffect.Composition repeatEffectIndefinitely(@NonNull android.os.VibrationEffect); field public static final int PRIMITIVE_CLICK = 1; // 0x1 field public static final int PRIMITIVE_LOW_TICK = 8; // 0x8 field public static final int PRIMITIVE_QUICK_FALL = 6; // 0x6 Loading @@ -31951,6 +31957,21 @@ package android.os { field public static final int PRIMITIVE_TICK = 7; // 0x7 } public static final class VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException extends java.lang.IllegalStateException { } public static class VibrationEffect.VibrationParameter { method @NonNull public static android.os.VibrationEffect.VibrationParameter targetAmplitude(@FloatRange(from=0, to=1) float); method @NonNull public static android.os.VibrationEffect.VibrationParameter targetFrequency(@FloatRange(from=1) float); } public static final class VibrationEffect.WaveformBuilder { method @NonNull public android.os.VibrationEffect.WaveformBuilder addSustain(@NonNull java.time.Duration); method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter); method @NonNull public android.os.VibrationEffect.WaveformBuilder addTransition(@NonNull java.time.Duration, @NonNull android.os.VibrationEffect.VibrationParameter, @NonNull android.os.VibrationEffect.VibrationParameter); method @NonNull public android.os.VibrationEffect build(); } public abstract class Vibrator { method public final int areAllEffectsSupported(@NonNull int...); method public final boolean areAllPrimitivesSupported(@NonNull int...);
core/api/test-current.txt +0 −15 Original line number Diff line number Diff line Loading @@ -1793,7 +1793,6 @@ package android.os { method public static android.os.VibrationEffect get(int, boolean); method @Nullable public static android.os.VibrationEffect get(android.net.Uri, android.content.Context); method public abstract long getDuration(); method @NonNull public static android.os.VibrationEffect.WaveformBuilder startWaveform(); field public static final int EFFECT_POP = 4; // 0x4 field public static final int EFFECT_STRENGTH_LIGHT = 0; // 0x0 field public static final int EFFECT_STRENGTH_MEDIUM = 1; // 0x1 Loading @@ -1811,20 +1810,6 @@ package android.os { field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Composed> CREATOR; } public static final class VibrationEffect.Composition { method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect); method @NonNull public android.os.VibrationEffect.Composition addEffect(@NonNull android.os.VibrationEffect, @IntRange(from=0) int); } 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) 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) float, @IntRange(from=0) int); method @NonNull public android.os.VibrationEffect build(); method @NonNull public android.os.VibrationEffect build(int); } public abstract class Vibrator { method public int getDefaultVibrationIntensity(int); field public static final int VIBRATION_INTENSITY_HIGH = 3; // 0x3 Loading
core/java/android/os/VibrationEffect.java +330 −151 File changed.Preview size limit exceeded, changes collapsed. Show changes
core/tests/coretests/src/android/os/VibrationEffectTest.java +63 −37 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.os; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; Loading @@ -32,6 +35,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.net.Uri; import android.os.VibrationEffect.Composition.UnreachableAfterRepeatingIndefinitelyException; import android.os.vibrator.PrebakedSegment; import android.os.vibrator.PrimitiveSegment; import android.os.vibrator.StepSegment; Loading @@ -43,6 +47,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; import java.time.Duration; @Presubmit @RunWith(MockitoJUnitRunner.class) public class VibrationEffectTest { Loading Loading @@ -122,16 +128,7 @@ public class VibrationEffectTest { VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, -1).validate(); VibrationEffect.createWaveform(new long[]{10, 10}, new int[] {0, 0}, -1).validate(); VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, 0).validate(); VibrationEffect.startWaveform() .addStep(/* amplitude= */ 1, /* duration= */ 10) .addRamp(/* amplitude= */ 0, /* duration= */ 20) .addStep(/* amplitude= */ 1, /* frequencyHz= */ 1, /* duration= */ 100) .addRamp(/* amplitude= */ 0.5f, /* frequencyHz= */ 100, /* duration= */ 50) .build() .validate(); assertThrows(IllegalStateException.class, () -> VibrationEffect.startWaveform().build().validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.createWaveform(new long[0], new int[0], -1).validate()); assertThrows(IllegalArgumentException.class, Loading @@ -145,27 +142,31 @@ public class VibrationEffectTest { assertThrows(IllegalArgumentException.class, () -> VibrationEffect.createWaveform( TEST_TIMINGS, TEST_AMPLITUDES, TEST_TIMINGS.length).validate()); } @Test public void testValidateWaveformBuilder() { VibrationEffect.startWaveform(targetAmplitude(1)) .addTransition(Duration.ofSeconds(1), targetAmplitude(0.5f), targetFrequency(100)) .addTransition(Duration.ZERO, targetAmplitude(0f), targetFrequency(200)) .addSustain(Duration.ofMinutes(2)) .addTransition(Duration.ofMillis(10), targetAmplitude(1f), targetFrequency(50)) .addSustain(Duration.ofMillis(1)) .addTransition(Duration.ZERO, targetFrequency(150)) .addSustain(Duration.ofMillis(2)) .addTransition(Duration.ofSeconds(15), targetAmplitude(1)) .build() .validate(); assertThrows(IllegalStateException.class, () -> VibrationEffect.startWaveform().build().validate()); assertThrows(IllegalArgumentException.class, () -> targetAmplitude(-2)); assertThrows(IllegalArgumentException.class, () -> targetFrequency(0)); 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, 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()); () -> VibrationEffect.startWaveform().addTransition( Duration.ofMillis(-10), targetAmplitude(1)).build().validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startWaveform() .addRamp(1, 10f, /* duration= */ -3).build().validate()); () -> VibrationEffect.startWaveform().addSustain(Duration.ZERO).build().validate()); } @Test Loading @@ -174,14 +175,24 @@ public class VibrationEffectTest { .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK) .addEffect(TEST_ONE_SHOT) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f) .addEffect(TEST_WAVEFORM, 100) .addOffDuration(Duration.ofMillis(100)) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 0.5f, 10) .addEffect(VibrationEffect.get(VibrationEffect.EFFECT_CLICK)) .compose() .validate(); VibrationEffect.startComposition() .repeatEffectIndefinitely(TEST_ONE_SHOT) .compose() .validate(); assertThrows(IllegalStateException.class, () -> VibrationEffect.startComposition().compose().validate()); assertThrows(IllegalStateException.class, () -> VibrationEffect.startComposition() .addOffDuration(Duration.ofSeconds(0)) .compose() .validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startComposition().addPrimitive(-1).compose().validate()); assertThrows(IllegalArgumentException.class, Loading @@ -196,12 +207,27 @@ public class VibrationEffectTest { .validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startComposition() .addEffect(TEST_ONE_SHOT, /* delay= */ -10) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1) .compose() .validate()); assertThrows(IllegalArgumentException.class, () -> VibrationEffect.startComposition() .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, 1f, -1) .repeatEffectIndefinitely( // Repeating waveform. VibrationEffect.createWaveform( new long[] { 10 }, new int[] { 100}, 0)) .compose() .validate()); assertThrows(UnreachableAfterRepeatingIndefinitelyException.class, () -> VibrationEffect.startComposition() .repeatEffectIndefinitely(TEST_WAVEFORM) .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK) .compose() .validate()); assertThrows(UnreachableAfterRepeatingIndefinitelyException.class, () -> VibrationEffect.startComposition() .repeatEffectIndefinitely(TEST_WAVEFORM) .addEffect(TEST_ONE_SHOT) .compose() .validate()); } Loading Loading @@ -354,9 +380,9 @@ public class VibrationEffectTest { assertFalse(VibrationEffect.createWaveform( new long[]{200, 200, 700}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate()); assertFalse(VibrationEffect.startWaveform() .addRamp(1, 500) .addStep(1, 200) .addRamp(0, 500) .addTransition(Duration.ofMillis(500), targetAmplitude(1)) .addTransition(Duration.ofMillis(200), targetAmplitude(0.5f)) .addTransition(Duration.ofMillis(500), targetAmplitude(0)) .build() .isHapticFeedbackCandidate()); } Loading @@ -367,9 +393,9 @@ public class VibrationEffectTest { assertTrue(VibrationEffect.createWaveform( new long[]{100, 200, 300}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate()); assertTrue(VibrationEffect.startWaveform() .addRamp(1, 300) .addStep(1, 200) .addRamp(0, 300) .addTransition(Duration.ofMillis(300), targetAmplitude(1)) .addTransition(Duration.ofMillis(200), targetAmplitude(0.5f)) .addTransition(Duration.ofMillis(300), targetAmplitude(0)) .build() .isHapticFeedbackCandidate()); } Loading
services/core/java/com/android/server/notification/VibratorHelper.java +12 −8 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package com.android.server.notification; import static android.os.VibrationEffect.VibrationParameter.targetAmplitude; import static android.os.VibrationEffect.VibrationParameter.targetFrequency; import android.annotation.Nullable; import android.content.Context; import android.content.res.Resources; Loading @@ -30,6 +33,7 @@ import android.util.Slog; import com.android.internal.R; import com.android.server.pm.PackageManagerService; import java.time.Duration; import java.util.Arrays; /** Loading Loading @@ -89,8 +93,7 @@ public final class VibratorHelper { * Safely create a {@link VibrationEffect} from given waveform description. * * <p>The waveform is described by a sequence of values for target amplitude, frequency and * duration, that are forwarded to * {@link VibrationEffect.WaveformBuilder#addRamp(float, float, int)}. * duration, that are forwarded to {@link VibrationEffect.WaveformBuilder#addTransition}. * * <p>This method returns {@code null} if the pattern is also {@code null} or invalid. * Loading @@ -114,16 +117,17 @@ public final class VibratorHelper { VibrationEffect.WaveformBuilder waveformBuilder = VibrationEffect.startWaveform(); for (int i = 0; i < length; i += 3) { waveformBuilder.addRamp( /* amplitude= */ values[i], /* frequencyHz= */ values[i + 1], /* duration= */ (int) values[i + 2]); waveformBuilder.addTransition(Duration.ofMillis((int) values[i + 2]), targetAmplitude(values[i]), targetFrequency(values[i + 1])); } VibrationEffect effect = waveformBuilder.build(); if (insistent) { return waveformBuilder.build(/* repeat= */ 0); return VibrationEffect.startComposition() .repeatEffectIndefinitely(effect) .compose(); } return waveformBuilder.build(); return effect; } catch (IllegalArgumentException e) { Slog.e(TAG, "Error creating vibration PWLE waveform with pattern: " + Arrays.toString(values)); Loading