Merge "Create API to Compute Vibration Pattern Equivalent to a VibrationEffect"
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index fa73178..725cef6 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1908,6 +1908,7 @@
}
public abstract class VibrationEffect implements android.os.Parcelable {
+ method @Nullable public abstract long[] computeCreateWaveformOffOnTimingsOrNull();
method public static android.os.VibrationEffect get(int);
method public static android.os.VibrationEffect get(int, boolean);
method @Nullable public static android.os.VibrationEffect get(android.net.Uri, android.content.Context);
@@ -1922,6 +1923,7 @@
}
public static final class VibrationEffect.Composed extends android.os.VibrationEffect {
+ method @Nullable public long[] computeCreateWaveformOffOnTimingsOrNull();
method public long getDuration();
method public int getRepeatIndex();
method @NonNull public java.util.List<android.os.vibrator.VibrationEffectSegment> getSegments();
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index 71bc4b3..3448a9e 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -227,6 +227,31 @@
}
/**
+ * Computes a legacy vibration pattern (i.e. a pattern with duration values for "off/on"
+ * vibration components) that is equivalent to this VibrationEffect.
+ *
+ * <p>All non-repeating effects created with {@link #createWaveform(int[], int)} are convertible
+ * into an equivalent vibration pattern with this method. It is not guaranteed that an effect
+ * created with other means becomes converted into an equivalent legacy vibration pattern, even
+ * if it has an equivalent vibration pattern. If this method is unable to create an equivalent
+ * vibration pattern for such effects, it will return {@code null}.
+ *
+ * <p>Note that a valid equivalent long[] pattern cannot be created for an effect that has any
+ * form of repeating behavior, regardless of how the effect was created. For repeating effects,
+ * the method will always return {@code null}.
+ *
+ * @return a long array representing a vibration pattern equivalent to the VibrationEffect, if
+ * the method successfully derived a vibration pattern equivalent to the effect
+ * (this will always be the case if the effect was created via
+ * {@link #createWaveform(int[], int)} and is non-repeating). Otherwise, returns
+ * {@code null}.
+ * @hide
+ */
+ @TestApi
+ @Nullable
+ public abstract long[] computeCreateWaveformOffOnTimingsOrNull();
+
+ /**
* Create a waveform vibration.
*
* <p>Waveform vibrations are a potentially repeating series of timing and amplitude pairs,
@@ -641,6 +666,51 @@
return mRepeatIndex;
}
+ /** @hide */
+ @Override
+ @Nullable
+ public long[] computeCreateWaveformOffOnTimingsOrNull() {
+ if (getRepeatIndex() >= 0) {
+ // Repeating effects cannot be fully represented as a long[] legacy pattern.
+ return null;
+ }
+
+ List<VibrationEffectSegment> segments = getSegments();
+
+ // The maximum possible size of the final pattern is 1 plus the number of segments in
+ // the original effect. This is because we will add an empty "off" segment at the
+ // start of the pattern if the first segment of the original effect is an "on" segment.
+ // (because the legacy patterns start with an "off" pattern). Other than this one case,
+ // we will add the durations of back-to-back segments of similar amplitudes (amplitudes
+ // that are all "on" or "off") and create a pattern entry for the total duration, which
+ // will not take more number pattern entries than the number of segments processed.
+ long[] patternBuffer = new long[segments.size() + 1];
+ int patternIndex = 0;
+
+ for (int i = 0; i < segments.size(); i++) {
+ StepSegment stepSegment =
+ castToValidStepSegmentForOffOnTimingsOrNull(segments.get(i));
+ if (stepSegment == null) {
+ // This means that there is 1 or more segments of this effect that is/are not a
+ // possible component of a legacy vibration pattern. Thus, the VibrationEffect
+ // does not have any equivalent legacy vibration pattern.
+ return null;
+ }
+
+ boolean isSegmentOff = stepSegment.getAmplitude() == 0;
+ // Even pattern indices are "off", and odd pattern indices are "on"
+ boolean isCurrentPatternIndexOff = (patternIndex % 2) == 0;
+ if (isSegmentOff != isCurrentPatternIndexOff) {
+ // Move the pattern index one step ahead, so that the current segment's
+ // "off"/"on" property matches that of the index's
+ ++patternIndex;
+ }
+ patternBuffer[patternIndex] += stepSegment.getDuration();
+ }
+
+ return Arrays.copyOf(patternBuffer, patternIndex + 1);
+ }
+
/** @hide */
@Override
public void validate() {
@@ -806,6 +876,31 @@
return new Composed[size];
}
};
+
+ /**
+ * Casts a provided {@link VibrationEffectSegment} to a {@link StepSegment} and returns it,
+ * only if it can possibly be a segment for an effect created via
+ * {@link #createWaveform(int[], int)}. Otherwise, returns {@code null}.
+ */
+ @Nullable
+ private static StepSegment castToValidStepSegmentForOffOnTimingsOrNull(
+ VibrationEffectSegment segment) {
+ if (!(segment instanceof StepSegment)) {
+ return null;
+ }
+
+ StepSegment stepSegment = (StepSegment) segment;
+ if (stepSegment.getFrequencyHz() != 0) {
+ return null;
+ }
+
+ float amplitude = stepSegment.getAmplitude();
+ if (amplitude != 0 && amplitude != DEFAULT_AMPLITUDE) {
+ return null;
+ }
+
+ return stepSegment;
+ }
}
/**
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index f7ca822..0c7ff4a 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -16,6 +16,7 @@
package android.os;
+import static android.os.VibrationEffect.DEFAULT_AMPLITUDE;
import static android.os.VibrationEffect.VibrationParameter.targetAmplitude;
import static android.os.VibrationEffect.VibrationParameter.targetFrequency;
@@ -48,6 +49,7 @@
import org.mockito.junit.MockitoJUnitRunner;
import java.time.Duration;
+import java.util.Arrays;
@Presubmit
@RunWith(MockitoJUnitRunner.class)
@@ -62,16 +64,363 @@
private static final int TEST_AMPLITUDE = 100;
private static final long[] TEST_TIMINGS = new long[] { 100, 100, 200 };
private static final int[] TEST_AMPLITUDES =
- new int[] { 255, 0, VibrationEffect.DEFAULT_AMPLITUDE };
+ new int[] { 255, 0, DEFAULT_AMPLITUDE };
private static final VibrationEffect TEST_ONE_SHOT =
VibrationEffect.createOneShot(TEST_TIMING, TEST_AMPLITUDE);
private static final VibrationEffect DEFAULT_ONE_SHOT =
- VibrationEffect.createOneShot(TEST_TIMING, VibrationEffect.DEFAULT_AMPLITUDE);
+ VibrationEffect.createOneShot(TEST_TIMING, DEFAULT_AMPLITUDE);
private static final VibrationEffect TEST_WAVEFORM =
VibrationEffect.createWaveform(TEST_TIMINGS, TEST_AMPLITUDES, -1);
@Test
+ public void computeLegacyPattern_timingsAndAmplitudes_zeroAmplitudesOnEvenIndices() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3, 4, 5},
+ /* amplitudes= */ new int[] {0, DEFAULT_AMPLITUDE, 0, DEFAULT_AMPLITUDE, 0},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {1, 2, 3, 4, 5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_zeroAmplitudesOnOddIndices() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3, 4, 5},
+ /* amplitudes= */ new int[] {
+ DEFAULT_AMPLITUDE, 0, DEFAULT_AMPLITUDE, 0, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {0, 1, 2, 3, 4, 5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_zeroAmplitudesAtTheStart() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {0, 0, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {3, 3};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_zeroAmplitudesAtTheEnd() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {DEFAULT_AMPLITUDE, 0, 0},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {0, 1, 5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_allDefaultAmplitudes() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {
+ DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {0, 6};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_allZeroAmplitudes() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* amplitudes= */ new int[] {0, 0, 0},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {6};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_sparsedZeroAmplitudes() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3, 4, 5, 6, 7},
+ /* amplitudes= */ new int[] {
+ 0, 0, DEFAULT_AMPLITUDE, 0, DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE, 0},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {3, 3, 4, 11, 7};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_oneTimingWithDefaultAmplitude() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1},
+ /* amplitudes= */ new int[] {DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {0, 1};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_oneTimingWithZeroAmplitude() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1},
+ /* amplitudes= */ new int[] {0},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {1};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_repeating() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3, 4, 5},
+ /* amplitudes= */ new int[] {0, DEFAULT_AMPLITUDE, 0, DEFAULT_AMPLITUDE, 0},
+ /* repeatIndex= */ 0);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+
+ effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3, 4, 5},
+ /* amplitudes= */ new int[] {0, DEFAULT_AMPLITUDE, 0, DEFAULT_AMPLITUDE, 0},
+ /* repeatIndex= */ 3);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+
+ effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2},
+ /* amplitudes= */ new int[] {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ 1);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsAndAmplitudes_badAmplitude() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1},
+ /* amplitudes= */ new int[] {200},
+ /* repeatIndex= */ -1);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsOnly_nonZeroTimings() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {1, 2, 3};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsOnly_oneValue() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {5},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsOnly_zeroesAtTheEnd() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3, 0, 0},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {1, 2, 3, 0, 0};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsOnly_zeroesAtTheStart() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {0, 0, 1, 2, 3},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {0, 0, 1, 2, 3};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsOnly_zeroesAtTheMiddle() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 0, 0, 3, 4, 5},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {1, 2, 0, 0, 3, 4, 5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsOnly_sparsedZeroes() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {0, 1, 2, 0, 0, 3, 4, 5, 0},
+ /* repeatIndex= */ -1);
+ long[] expectedPattern = new long[] {0, 1, 2, 0, 0, 3, 4, 5, 0};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_timingsOnly_repeating() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {0, 1, 2, 0, 0, 3, 4, 5, 0},
+ /* repeatIndex= */ 0);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+
+ effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[] {1, 2, 3, 4},
+ /* repeatIndex= */ 2);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_notPatternPased() {
+ VibrationEffect effect = VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_oneShot_defaultAmplitude() {
+ VibrationEffect effect = VibrationEffect.createOneShot(
+ /* milliseconds= */ 5, /* ampliutde= */ DEFAULT_AMPLITUDE);
+ long[] expectedPattern = new long[] {0, 5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_oneShot_badAmplitude() {
+ VibrationEffect effect = VibrationEffect.createOneShot(
+ /* milliseconds= */ 5, /* ampliutde= */ 50);
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_composition_noOffDuration() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {5},
+ /* repeatIndex= */ -1))
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {2, 3},
+ /* repeatIndex= */ -1))
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {10, 20},
+ /* amplitudes= */ new int[] {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1))
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {4, 5},
+ /* amplitudes= */ new int[] {0, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1))
+ .compose();
+ long[] expectedPattern = new long[] {7, 33, 4, 5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_composition_withOffDuration() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addOffDuration(Duration.ofMillis(20))
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {10, 20},
+ /* amplitudes= */ new int[] {0, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1))
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {30, 40},
+ /* amplitudes= */ new int[] {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE},
+ /* repeatIndex= */ -1))
+ .addOffDuration(Duration.ofMillis(10))
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {4, 5},
+ /* repeatIndex= */ -1))
+ .addOffDuration(Duration.ofMillis(5))
+ .compose();
+ long[] expectedPattern = new long[] {30, 90, 14, 5, 5};
+
+ assertArrayEq(expectedPattern, effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_composition_withPrimitives() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .addOffDuration(Duration.ofMillis(20))
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {5},
+ /* repeatIndex= */ -1))
+ .compose();
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_composition_repeating() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addEffect(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {5},
+ /* repeatIndex= */ -1))
+ .repeatEffectIndefinitely(
+ VibrationEffect.createWaveform(
+ /* timings= */ new long[] {2, 3},
+ /* repeatIndex= */ -1))
+ .compose();
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
+ public void computeLegacyPattern_effectsViaStartWaveform() {
+ // Effects created via startWaveform are not expected to be converted to long[] patterns, as
+ // they are not configured to always play with the default amplitude.
+ VibrationEffect effect = VibrationEffect.startWaveform(targetFrequency(60))
+ .addTransition(Duration.ofMillis(100), targetAmplitude(1), targetFrequency(120))
+ .addSustain(Duration.ofMillis(200))
+ .addTransition(Duration.ofMillis(100), targetAmplitude(0), targetFrequency(60))
+ .build();
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+
+ effect = VibrationEffect.startWaveform(targetFrequency(60))
+ .addTransition(Duration.ofMillis(80), targetAmplitude(1))
+ .addSustain(Duration.ofMillis(200))
+ .addTransition(Duration.ofMillis(100), targetAmplitude(0))
+ .build();
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+
+ effect = VibrationEffect.startWaveform(targetFrequency(60))
+ .addTransition(Duration.ofMillis(100), targetFrequency(50))
+ .addSustain(Duration.ofMillis(50))
+ .addTransition(Duration.ofMillis(20), targetFrequency(75))
+ .build();
+
+ assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
+ }
+
+ @Test
public void getRingtones_noPrebakedRingtones() {
Resources r = mockRingtoneResources(new String[0]);
Context context = mockContext(r);
@@ -100,7 +449,7 @@
@Test
public void testValidateOneShot() {
VibrationEffect.createOneShot(1, 255).validate();
- VibrationEffect.createOneShot(1, VibrationEffect.DEFAULT_AMPLITUDE).validate();
+ VibrationEffect.createOneShot(1, DEFAULT_AMPLITUDE).validate();
assertThrows(IllegalArgumentException.class,
() -> VibrationEffect.createOneShot(-1, 255).validate());
@@ -501,6 +850,13 @@
assertTrue(VibrationEffect.get(VibrationEffect.EFFECT_TICK).isHapticFeedbackCandidate());
}
+ private void assertArrayEq(long[] expected, long[] actual) {
+ assertTrue(
+ String.format("Expected pattern %s, but was %s",
+ Arrays.toString(expected), Arrays.toString(actual)),
+ Arrays.equals(expected, actual));
+ }
+
private Resources mockRingtoneResources() {
return mockRingtoneResources(new String[]{
RINGTONE_URI_1,