Loading services/core/java/com/android/server/notification/NotificationRecord.java +12 −3 Original line number Diff line number Diff line Loading @@ -330,12 +330,21 @@ public final class NotificationRecord { } final long[] vibrationPattern = channel.getVibrationPattern(); if (vibrationPattern == null) { return helper.createDefaultVibration(insistent); } if (vibrationPattern != null) { return helper.createWaveformVibration(vibrationPattern, insistent); } if (com.android.server.notification.Flags.notificationVibrationInSoundUri()) { final VibrationEffect vibrationEffectFromSoundUri = helper.createVibrationEffectFromSoundUri(channel.getSound()); if (vibrationEffectFromSoundUri != null) { return vibrationEffectFromSoundUri; } } return helper.createDefaultVibration(insistent); } private VibrationEffect calculateVibration() { VibratorHelper helper = new VibratorHelper(mContext); final Notification notification = getSbn().getNotification(); Loading services/core/java/com/android/server/notification/VibratorHelper.java +31 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.media.AudioAttributes; import android.media.RingtoneManager; import android.media.Utils; import android.net.Uri; import android.os.Process; import android.os.VibrationAttributes; import android.os.VibrationEffect; Loading Loading @@ -51,6 +54,7 @@ public final class VibratorHelper { @Nullable private final float[] mDefaultPwlePattern; @Nullable private final float[] mFallbackPwlePattern; private final int mDefaultVibrationAmplitude; private final Context mContext; public VibratorHelper(Context context) { mVibrator = context.getSystemService(Vibrator.class); Loading @@ -68,6 +72,7 @@ public final class VibratorHelper { com.android.internal.R.array.config_notificationFallbackVibeWaveform); mDefaultVibrationAmplitude = context.getResources().getInteger( com.android.internal.R.integer.config_defaultVibrationAmplitude); mContext = context; } /** Loading Loading @@ -184,6 +189,16 @@ public final class VibratorHelper { * @param insistent {@code true} if the vibration should loop until it is cancelled. */ public VibrationEffect createDefaultVibration(boolean insistent) { if (com.android.server.notification.Flags.notificationVibrationInSoundUri()) { final Uri defaultRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_NOTIFICATION); final VibrationEffect vibrationEffectFromSoundUri = createVibrationEffectFromSoundUri(defaultRingtoneUri); if (vibrationEffectFromSoundUri != null) { return vibrationEffectFromSoundUri; } } if (mVibrator.hasFrequencyControl()) { VibrationEffect effect = createPwleWaveformVibration(mDefaultPwlePattern, insistent); if (effect != null) { Loading @@ -193,6 +208,22 @@ public final class VibratorHelper { return createWaveformVibration(mDefaultPattern, insistent); } /** * Safely create a {@link VibrationEffect} from given an uri {@code Uri}. * with query parameter "vibration_uri" * * Use this function if the {@code Uri} is with a query parameter "vibration_uri" and the * vibration_uri represents a valid vibration effect in xml * * @param uri {@code Uri} an uri including query parameter "vibraiton_uri" */ public @Nullable VibrationEffect createVibrationEffectFromSoundUri(Uri uri) { if (uri == null) { return null; } return Utils.parseVibrationEffect(mVibrator, Utils.getVibrationUri(uri)); } /** Returns if a given vibration can be played by the vibrator that does notification buzz. */ public boolean areEffectComponentsSupported(VibrationEffect effect) { return mVibrator.areVibrationFeaturesSupported(effect); Loading services/core/java/com/android/server/notification/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -156,3 +156,10 @@ flag { description: "This flag enables forced auto-grouping conversations" bug: "336488844" } flag { name: "notification_vibration_in_sound_uri" namespace: "systemui" description: "This flag enables sound uri with vibration source" bug: "358524009" } services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +87 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.Icon; import android.media.AudioAttributes; import android.media.RingtoneManager; import android.media.Utils; import android.metrics.LogMaker; import android.net.Uri; import android.os.Build; Loading @@ -69,6 +71,7 @@ import android.os.Bundle; import android.os.UserHandle; import android.os.VibrationEffect; import android.os.Vibrator; import android.os.VibratorInfo; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; Loading @@ -93,6 +96,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; @SmallTest Loading Loading @@ -141,6 +147,7 @@ public class NotificationRecordTest extends UiServiceTestCase { when(mMockContext.getSystemService(eq(Vibrator.class))).thenReturn(mVibrator); when(mVibrator.areVibrationFeaturesSupported(any())).thenReturn(true); when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); final Resources res = mContext.getResources(); when(mMockContext.getResources()).thenReturn(res); when(mMockContext.getPackageManager()).thenReturn(mPm); Loading Loading @@ -510,6 +517,51 @@ public class NotificationRecordTest extends UiServiceTestCase { assertNull(record.getVibration()); } @Test @EnableFlags(com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI) public void testVibration_customVibrationForSound_withoutVibrationUri() { // prepare testing data Uri backupDefaultUri = RingtoneManager.getActualDefaultRingtoneUri(mMockContext, RingtoneManager.TYPE_NOTIFICATION); RingtoneManager.setActualDefaultRingtoneUri(mMockContext, RingtoneManager.TYPE_NOTIFICATION, Settings.System.DEFAULT_NOTIFICATION_URI); defaultChannel.enableVibration(true); defaultChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, CUSTOM_ATTRIBUTES); StatusBarNotification sbn = getNotification( /* channelVibrationPattern= */ null, /* channelVibrationEffect= */ null, /* insistent= */ false); NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel); try { assertEquals( new VibratorHelper(mMockContext).createDefaultVibration(false), record.getVibration()); } finally { // restore the data RingtoneManager.setActualDefaultRingtoneUri(mMockContext, RingtoneManager.TYPE_NOTIFICATION, backupDefaultUri); } } @Test @EnableFlags(com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI) public void testVibration_customVibrationForSound_withVibrationUri() throws IOException { defaultChannel.enableVibration(true); VibrationInfo vibration = getTestingVibration(mVibrator); Uri uriWithVibration = getVibrationUriAppended( Settings.System.DEFAULT_NOTIFICATION_URI, vibration.mUri); defaultChannel.setSound(uriWithVibration, CUSTOM_ATTRIBUTES); StatusBarNotification sbn = getNotification( /* channelVibrationPattern= */ null, /* channelVibrationEffect= */ null, /* insistent= */ false); NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel); assertEquals(vibration.mVibrationEffect, record.getVibration()); } @Test public void testImportance_preUpgrade() { StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */, Loading Loading @@ -1594,4 +1646,39 @@ public class NotificationRecordTest extends UiServiceTestCase { assertThat(record.getAudioAttributes().getUsage()).isEqualTo(USAGE_ALARM); } static class VibrationInfo { public VibrationEffect mVibrationEffect; public Uri mUri; VibrationInfo(VibrationEffect vibrationEffect, Uri uri) { mVibrationEffect = vibrationEffect; mUri = uri; } } private static VibrationInfo getTestingVibration(Vibrator vibrator) throws IOException { File tempVibrationFile = File.createTempFile("test_vibration_file", ".xml"); FileWriter writer = new FileWriter(tempVibrationFile); writer.write("<vibration-effect>\n" + " <waveform-effect>\n" + " <!-- PRIMING -->\n" + " <waveform-entry durationMs=\"0\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"250\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"500\" amplitude=\"0\"/>\n" + " </waveform-effect>\n" + "</vibration-effect>"); // Your test XML content writer.close(); Uri vibrationUri = Uri.parse(tempVibrationFile.toURI().toString()); VibrationEffect vibrationEffect = Utils.parseVibrationEffect(vibrator, vibrationUri); return new VibrationInfo(vibrationEffect, vibrationUri); } private static Uri getVibrationUriAppended(Uri audioUri, Uri vibrationUri) { Uri.Builder builder = audioUri.buildUpon(); builder.appendQueryParameter(Utils.VIBRATION_URI_PARAM, vibrationUri.toString()); return builder.build(); } } services/tests/uiservicestests/src/com/android/server/notification/VibratorHelperTest.java +59 −0 Original line number Diff line number Diff line Loading @@ -22,8 +22,12 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.when; import android.media.Utils; import android.net.Uri; import android.os.VibrationEffect; import android.os.Vibrator; import android.os.VibratorInfo; import android.provider.Settings; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; Loading @@ -36,6 +40,10 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.io.FileWriter; import java.io.IOException; @SmallTest @RunWith(AndroidJUnit4.class) public class VibratorHelperTest extends UiServiceTestCase { Loading Loading @@ -85,8 +93,35 @@ public class VibratorHelperTest extends UiServiceTestCase { assertNull(VibratorHelper.createPwleWaveformVibration(new float[] { 0, 0, 0 }, false)); } @Test public void createVibrationEffectFromSoundUri_nullInput() { assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(null)); } @Test public void createVibrationEffectFromSoundUri_emptyUri() { assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(Uri.EMPTY)); } @Test public void createVibrationEffectFromSoundUri_uriWithoutRequiredQueryParameter() { Uri uri = Settings.System.DEFAULT_NOTIFICATION_URI; assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(uri)); } @Test public void createVibrationEffectFromSoundUri_uriWithVibrationUri() throws IOException { // prepare the uri with vibration when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); Uri validUri = getVibrationUriAppended(Settings.System.DEFAULT_NOTIFICATION_URI); assertSingleVibration(mVibratorHelper.createVibrationEffectFromSoundUri(validUri)); } @Test public void createVibration_insistent_createsRepeatingVibration() { when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); when(mVibrator.hasFrequencyControl()).thenReturn(false); assertRepeatingVibration(mVibratorHelper.createDefaultVibration(/* insistent= */ true)); assertRepeatingVibration(mVibratorHelper.createFallbackVibration(/* insistent= */ true)); Loading @@ -98,6 +133,8 @@ public class VibratorHelperTest extends UiServiceTestCase { @Test public void createVibration_nonInsistent_createsSingleShotVibration() { when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); when(mVibrator.hasFrequencyControl()).thenReturn(false); assertSingleVibration(mVibratorHelper.createDefaultVibration(/* insistent= */ false)); assertSingleVibration(mVibratorHelper.createFallbackVibration(/* insistent= */ false)); Loading @@ -120,4 +157,26 @@ public class VibratorHelperTest extends UiServiceTestCase { effect instanceof VibrationEffect.Composed); return ((VibrationEffect.Composed) effect).getRepeatIndex(); } private static Uri getVibrationUriAppended(Uri baseUri) throws IOException { File tempVibrationFile = File.createTempFile("test_vibration_file", ".xml"); FileWriter writer = new FileWriter(tempVibrationFile); writer.write("<vibration-effect>\n" + " <waveform-effect>\n" + " <!-- PRIMING -->\n" + " <waveform-entry durationMs=\"0\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"250\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"500\" amplitude=\"0\"/>\n" + " </waveform-effect>\n" + "</vibration-effect>"); // Your test XML content writer.close(); Uri.Builder builder = baseUri.buildUpon(); builder.appendQueryParameter( Utils.VIBRATION_URI_PARAM, tempVibrationFile.toURI().toString()); return builder.build(); } } Loading
services/core/java/com/android/server/notification/NotificationRecord.java +12 −3 Original line number Diff line number Diff line Loading @@ -330,12 +330,21 @@ public final class NotificationRecord { } final long[] vibrationPattern = channel.getVibrationPattern(); if (vibrationPattern == null) { return helper.createDefaultVibration(insistent); } if (vibrationPattern != null) { return helper.createWaveformVibration(vibrationPattern, insistent); } if (com.android.server.notification.Flags.notificationVibrationInSoundUri()) { final VibrationEffect vibrationEffectFromSoundUri = helper.createVibrationEffectFromSoundUri(channel.getSound()); if (vibrationEffectFromSoundUri != null) { return vibrationEffectFromSoundUri; } } return helper.createDefaultVibration(insistent); } private VibrationEffect calculateVibration() { VibratorHelper helper = new VibratorHelper(mContext); final Notification notification = getSbn().getNotification(); Loading
services/core/java/com/android/server/notification/VibratorHelper.java +31 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,9 @@ import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.media.AudioAttributes; import android.media.RingtoneManager; import android.media.Utils; import android.net.Uri; import android.os.Process; import android.os.VibrationAttributes; import android.os.VibrationEffect; Loading Loading @@ -51,6 +54,7 @@ public final class VibratorHelper { @Nullable private final float[] mDefaultPwlePattern; @Nullable private final float[] mFallbackPwlePattern; private final int mDefaultVibrationAmplitude; private final Context mContext; public VibratorHelper(Context context) { mVibrator = context.getSystemService(Vibrator.class); Loading @@ -68,6 +72,7 @@ public final class VibratorHelper { com.android.internal.R.array.config_notificationFallbackVibeWaveform); mDefaultVibrationAmplitude = context.getResources().getInteger( com.android.internal.R.integer.config_defaultVibrationAmplitude); mContext = context; } /** Loading Loading @@ -184,6 +189,16 @@ public final class VibratorHelper { * @param insistent {@code true} if the vibration should loop until it is cancelled. */ public VibrationEffect createDefaultVibration(boolean insistent) { if (com.android.server.notification.Flags.notificationVibrationInSoundUri()) { final Uri defaultRingtoneUri = RingtoneManager.getActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_NOTIFICATION); final VibrationEffect vibrationEffectFromSoundUri = createVibrationEffectFromSoundUri(defaultRingtoneUri); if (vibrationEffectFromSoundUri != null) { return vibrationEffectFromSoundUri; } } if (mVibrator.hasFrequencyControl()) { VibrationEffect effect = createPwleWaveformVibration(mDefaultPwlePattern, insistent); if (effect != null) { Loading @@ -193,6 +208,22 @@ public final class VibratorHelper { return createWaveformVibration(mDefaultPattern, insistent); } /** * Safely create a {@link VibrationEffect} from given an uri {@code Uri}. * with query parameter "vibration_uri" * * Use this function if the {@code Uri} is with a query parameter "vibration_uri" and the * vibration_uri represents a valid vibration effect in xml * * @param uri {@code Uri} an uri including query parameter "vibraiton_uri" */ public @Nullable VibrationEffect createVibrationEffectFromSoundUri(Uri uri) { if (uri == null) { return null; } return Utils.parseVibrationEffect(mVibrator, Utils.getVibrationUri(uri)); } /** Returns if a given vibration can be played by the vibrator that does notification buzz. */ public boolean areEffectComponentsSupported(VibrationEffect effect) { return mVibrator.areVibrationFeaturesSupported(effect); Loading
services/core/java/com/android/server/notification/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -156,3 +156,10 @@ flag { description: "This flag enables forced auto-grouping conversations" bug: "336488844" } flag { name: "notification_vibration_in_sound_uri" namespace: "systemui" description: "This flag enables sound uri with vibration source" bug: "358524009" }
services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +87 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,8 @@ import android.content.res.Resources; import android.graphics.Color; import android.graphics.drawable.Icon; import android.media.AudioAttributes; import android.media.RingtoneManager; import android.media.Utils; import android.metrics.LogMaker; import android.net.Uri; import android.os.Build; Loading @@ -69,6 +71,7 @@ import android.os.Bundle; import android.os.UserHandle; import android.os.VibrationEffect; import android.os.Vibrator; import android.os.VibratorInfo; import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; Loading @@ -93,6 +96,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; @SmallTest Loading Loading @@ -141,6 +147,7 @@ public class NotificationRecordTest extends UiServiceTestCase { when(mMockContext.getSystemService(eq(Vibrator.class))).thenReturn(mVibrator); when(mVibrator.areVibrationFeaturesSupported(any())).thenReturn(true); when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); final Resources res = mContext.getResources(); when(mMockContext.getResources()).thenReturn(res); when(mMockContext.getPackageManager()).thenReturn(mPm); Loading Loading @@ -510,6 +517,51 @@ public class NotificationRecordTest extends UiServiceTestCase { assertNull(record.getVibration()); } @Test @EnableFlags(com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI) public void testVibration_customVibrationForSound_withoutVibrationUri() { // prepare testing data Uri backupDefaultUri = RingtoneManager.getActualDefaultRingtoneUri(mMockContext, RingtoneManager.TYPE_NOTIFICATION); RingtoneManager.setActualDefaultRingtoneUri(mMockContext, RingtoneManager.TYPE_NOTIFICATION, Settings.System.DEFAULT_NOTIFICATION_URI); defaultChannel.enableVibration(true); defaultChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, CUSTOM_ATTRIBUTES); StatusBarNotification sbn = getNotification( /* channelVibrationPattern= */ null, /* channelVibrationEffect= */ null, /* insistent= */ false); NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel); try { assertEquals( new VibratorHelper(mMockContext).createDefaultVibration(false), record.getVibration()); } finally { // restore the data RingtoneManager.setActualDefaultRingtoneUri(mMockContext, RingtoneManager.TYPE_NOTIFICATION, backupDefaultUri); } } @Test @EnableFlags(com.android.server.notification.Flags.FLAG_NOTIFICATION_VIBRATION_IN_SOUND_URI) public void testVibration_customVibrationForSound_withVibrationUri() throws IOException { defaultChannel.enableVibration(true); VibrationInfo vibration = getTestingVibration(mVibrator); Uri uriWithVibration = getVibrationUriAppended( Settings.System.DEFAULT_NOTIFICATION_URI, vibration.mUri); defaultChannel.setSound(uriWithVibration, CUSTOM_ATTRIBUTES); StatusBarNotification sbn = getNotification( /* channelVibrationPattern= */ null, /* channelVibrationEffect= */ null, /* insistent= */ false); NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel); assertEquals(vibration.mVibrationEffect, record.getVibration()); } @Test public void testImportance_preUpgrade() { StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */, Loading Loading @@ -1594,4 +1646,39 @@ public class NotificationRecordTest extends UiServiceTestCase { assertThat(record.getAudioAttributes().getUsage()).isEqualTo(USAGE_ALARM); } static class VibrationInfo { public VibrationEffect mVibrationEffect; public Uri mUri; VibrationInfo(VibrationEffect vibrationEffect, Uri uri) { mVibrationEffect = vibrationEffect; mUri = uri; } } private static VibrationInfo getTestingVibration(Vibrator vibrator) throws IOException { File tempVibrationFile = File.createTempFile("test_vibration_file", ".xml"); FileWriter writer = new FileWriter(tempVibrationFile); writer.write("<vibration-effect>\n" + " <waveform-effect>\n" + " <!-- PRIMING -->\n" + " <waveform-entry durationMs=\"0\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"250\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"500\" amplitude=\"0\"/>\n" + " </waveform-effect>\n" + "</vibration-effect>"); // Your test XML content writer.close(); Uri vibrationUri = Uri.parse(tempVibrationFile.toURI().toString()); VibrationEffect vibrationEffect = Utils.parseVibrationEffect(vibrator, vibrationUri); return new VibrationInfo(vibrationEffect, vibrationUri); } private static Uri getVibrationUriAppended(Uri audioUri, Uri vibrationUri) { Uri.Builder builder = audioUri.buildUpon(); builder.appendQueryParameter(Utils.VIBRATION_URI_PARAM, vibrationUri.toString()); return builder.build(); } }
services/tests/uiservicestests/src/com/android/server/notification/VibratorHelperTest.java +59 −0 Original line number Diff line number Diff line Loading @@ -22,8 +22,12 @@ import static junit.framework.Assert.assertTrue; import static org.mockito.Mockito.when; import android.media.Utils; import android.net.Uri; import android.os.VibrationEffect; import android.os.Vibrator; import android.os.VibratorInfo; import android.provider.Settings; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; Loading @@ -36,6 +40,10 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.io.File; import java.io.FileWriter; import java.io.IOException; @SmallTest @RunWith(AndroidJUnit4.class) public class VibratorHelperTest extends UiServiceTestCase { Loading Loading @@ -85,8 +93,35 @@ public class VibratorHelperTest extends UiServiceTestCase { assertNull(VibratorHelper.createPwleWaveformVibration(new float[] { 0, 0, 0 }, false)); } @Test public void createVibrationEffectFromSoundUri_nullInput() { assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(null)); } @Test public void createVibrationEffectFromSoundUri_emptyUri() { assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(Uri.EMPTY)); } @Test public void createVibrationEffectFromSoundUri_uriWithoutRequiredQueryParameter() { Uri uri = Settings.System.DEFAULT_NOTIFICATION_URI; assertNull(mVibratorHelper.createVibrationEffectFromSoundUri(uri)); } @Test public void createVibrationEffectFromSoundUri_uriWithVibrationUri() throws IOException { // prepare the uri with vibration when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); Uri validUri = getVibrationUriAppended(Settings.System.DEFAULT_NOTIFICATION_URI); assertSingleVibration(mVibratorHelper.createVibrationEffectFromSoundUri(validUri)); } @Test public void createVibration_insistent_createsRepeatingVibration() { when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); when(mVibrator.hasFrequencyControl()).thenReturn(false); assertRepeatingVibration(mVibratorHelper.createDefaultVibration(/* insistent= */ true)); assertRepeatingVibration(mVibratorHelper.createFallbackVibration(/* insistent= */ true)); Loading @@ -98,6 +133,8 @@ public class VibratorHelperTest extends UiServiceTestCase { @Test public void createVibration_nonInsistent_createsSingleShotVibration() { when(mVibrator.getInfo()).thenReturn(VibratorInfo.EMPTY_VIBRATOR_INFO); when(mVibrator.hasFrequencyControl()).thenReturn(false); assertSingleVibration(mVibratorHelper.createDefaultVibration(/* insistent= */ false)); assertSingleVibration(mVibratorHelper.createFallbackVibration(/* insistent= */ false)); Loading @@ -120,4 +157,26 @@ public class VibratorHelperTest extends UiServiceTestCase { effect instanceof VibrationEffect.Composed); return ((VibrationEffect.Composed) effect).getRepeatIndex(); } private static Uri getVibrationUriAppended(Uri baseUri) throws IOException { File tempVibrationFile = File.createTempFile("test_vibration_file", ".xml"); FileWriter writer = new FileWriter(tempVibrationFile); writer.write("<vibration-effect>\n" + " <waveform-effect>\n" + " <!-- PRIMING -->\n" + " <waveform-entry durationMs=\"0\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"250\" amplitude=\"0\"/>\n" + " <waveform-entry durationMs=\"12\" amplitude=\"255\"/>\n" + " <waveform-entry durationMs=\"500\" amplitude=\"0\"/>\n" + " </waveform-effect>\n" + "</vibration-effect>"); // Your test XML content writer.close(); Uri.Builder builder = baseUri.buildUpon(); builder.appendQueryParameter( Utils.VIBRATION_URI_PARAM, tempVibrationFile.toURI().toString()); return builder.build(); } }