Updated VolumeSettingsRingtoneManager to read from configuration file to am: 4f16120f5a am: 7626fe8705
am: 682b16ff04
Change-Id: Ic361188169d6647b68c6dc8447d9fccf9ac7e1df
diff --git a/res/values/config.xml b/res/values/config.xml
index 67c2f3d..a00ed09 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -45,6 +45,43 @@
major class for PHONE.
-->
<integer-array name="config_unbonded_device_filter_whitelist"/>
+ <!--
+ Array of keys that should be used for determining how audio attribute
+ usage should be mapped to ringtone uris.
+
+ The values of the keys can be found in android.media.AudioAttributes.
+ The number of items in this array must equal the number of items in
+ config_ringtone_uri_map_value, and the usages are mapped to the ringtone
+ uri based on positions in the array. The lowest rank usage (based on the
+ order in car_volume_items.xml) in each audio group (in Car service's
+ car_volume_groups.xml) will be used to sound for a given volume group's
+ slider.
+
+ If empty, all ringtones will default to the default ringtone uri.
+
+ TODO(b/144382611): Instead of mapping by usage, we should map by audio
+ group so as to make it clearer to define the sound to be played with a
+ given slider.
+ -->
+ <integer-array name="config_ringtone_audio_attribute_usages_map_key">
+ <item>5</item>
+ <item>4</item>
+ </integer-array>
+ <!--
+ Array of values that should be used to determine how audio attribute
+ usage should be mapped to ringtone uris.
+
+ The values should be uri strings that can be parsed into Uri. The number
+ of items in this array must equal the number of items in
+ config_ringtone_audio_attributes_map_key, and the ringtone uris are
+ mapped to the audio attributes based on positions in the array.
+
+ If empty, all ringtones will default to the default ringtone uri.
+ -->
+ <string-array name="config_ringtone_uri_map_value">
+ <item>content://settings/system/notification_sound</item>
+ <item>content://settings/system/alarm_alert</item>
+ </string-array>
<!-- Whether all preferences should always ignore UX Restrictions -->
<bool name="config_always_ignore_ux_restrictions">false</bool>
<!-- Array of Preference Keys that ignore UX Restrictions -->
diff --git a/src/com/android/car/settings/sound/VolumeSettingsRingtoneManager.java b/src/com/android/car/settings/sound/VolumeSettingsRingtoneManager.java
index 51f8bd8..a6c406b 100644
--- a/src/com/android/car/settings/sound/VolumeSettingsRingtoneManager.java
+++ b/src/com/android/car/settings/sound/VolumeSettingsRingtoneManager.java
@@ -26,6 +26,10 @@
import android.provider.Settings;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.car.settings.R;
+import com.android.car.settings.common.Logger;
import java.util.HashMap;
import java.util.Map;
@@ -33,11 +37,14 @@
/** Manges the audio played by the {@link VolumeSettingsPreferenceController}. */
public class VolumeSettingsRingtoneManager {
+ private static final Logger LOG = new Logger(VolumeSettingsRingtoneManager.class);
+
private static final int AUDIO_FEEDBACK_DURATION_MS = 1000;
private final Context mContext;
private final Handler mUiHandler;
private final Map<Integer, Ringtone> mGroupToRingtoneMap = new HashMap<>();
+ private final Map<Integer, Uri> mAttributeUsageToRingtoneUriMap = new HashMap<>();
@Nullable
private Ringtone mCurrentRingtone;
@@ -45,6 +52,32 @@
public VolumeSettingsRingtoneManager(Context context) {
mContext = context;
mUiHandler = new Handler(Looper.getMainLooper());
+ populateAttributeUsageToRingtoneUriMap();
+ }
+
+ private void populateAttributeUsageToRingtoneUriMap() {
+ int[] audioAttributeUsages = mContext
+ .getResources()
+ .getIntArray(R.array.config_ringtone_audio_attribute_usages_map_key);
+ String[] ringtoneStrings = mContext
+ .getResources()
+ .getStringArray(R.array.config_ringtone_uri_map_value);
+ if (audioAttributeUsages.length != ringtoneStrings.length) {
+ throw new IllegalArgumentException(
+ "config_ringtone_audio_attribute_usages_map_key and config_ringtone_uri_map_value "
+ + "must have the same number of items");
+ }
+
+ for (int i = 0; i < audioAttributeUsages.length; i++) {
+ @AudioAttributes.AttributeUsage int usage = audioAttributeUsages[i];
+ if (AudioAttributes.usageToString(usage).contains("unknown usage")) {
+ throw new IllegalArgumentException(
+ "Invalid usage in config_ringtone_audio_attribute_usages_map_key");
+ }
+ Uri ringtoneUri = Uri.parse(ringtoneStrings[i]);
+ LOG.d("Usage " + usage + " mapped to ringtone " + ringtoneUri);
+ mAttributeUsageToRingtoneUriMap.put(usage, ringtoneUri);
+ }
}
/**
@@ -87,14 +120,9 @@
}
// TODO: bundle car-specific audio sample assets in res/raw by usage
- private Uri getRingtoneUri(@AudioAttributes.AttributeUsage int usage) {
- switch (usage) {
- case AudioAttributes.USAGE_NOTIFICATION:
- return Settings.System.DEFAULT_NOTIFICATION_URI;
- case AudioAttributes.USAGE_ALARM:
- return Settings.System.DEFAULT_ALARM_ALERT_URI;
- default:
- return Settings.System.DEFAULT_RINGTONE_URI;
- }
+ @VisibleForTesting
+ Uri getRingtoneUri(@AudioAttributes.AttributeUsage int usage) {
+ return mAttributeUsageToRingtoneUriMap.getOrDefault(
+ usage, Settings.System.DEFAULT_RINGTONE_URI);
}
}
diff --git a/tests/robotests/src/com/android/car/settings/sound/VolumeSettingsRingtoneManagerTest.java b/tests/robotests/src/com/android/car/settings/sound/VolumeSettingsRingtoneManagerTest.java
index b6e3f85..9de35b6 100644
--- a/tests/robotests/src/com/android/car/settings/sound/VolumeSettingsRingtoneManagerTest.java
+++ b/tests/robotests/src/com/android/car/settings/sound/VolumeSettingsRingtoneManagerTest.java
@@ -16,14 +16,25 @@
package com.android.car.settings.sound;
+import static android.media.AudioAttributes.USAGE_ALARM;
+import static android.media.AudioAttributes.USAGE_MEDIA;
+
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
+import android.media.AudioAttributes.AttributeUsage;
import android.media.Ringtone;
+import android.net.Uri;
+import android.provider.Settings.System;
import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.R;
import com.android.car.settings.testutils.ShadowRingtoneManager;
import org.junit.After;
@@ -52,7 +63,7 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowRingtoneManager.setRingtone(mRingtone);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mRingtoneManager = new VolumeSettingsRingtoneManager(mContext);
}
@@ -63,6 +74,40 @@
}
@Test
+ public void getRingtoneUri_defaultsToDefaultRingtoneUriIfConfigIsEmpty() {
+ setResources(new int[] {}, new String[] {});
+ mRingtoneManager = new VolumeSettingsRingtoneManager(mContext);
+ Uri ringtoneUri = mRingtoneManager.getRingtoneUri(USAGE_ALARM);
+
+ assertThat(ringtoneUri).isEqualTo(System.DEFAULT_RINGTONE_URI);
+ }
+
+ @Test
+ public void getRingtoneUri_defaultsToDefaultRingtoneUriIfUsageNotInConfig() {
+ setResources(
+ new int[] {USAGE_MEDIA},
+ new String[] {"content://settings/system/notification_sound"}
+ );
+ mRingtoneManager = new VolumeSettingsRingtoneManager(mContext);
+
+ Uri ringtoneUri = mRingtoneManager.getRingtoneUri(USAGE_ALARM);
+
+ assertThat(ringtoneUri).isEqualTo(System.DEFAULT_RINGTONE_URI);
+ }
+
+ @Test
+ public void getRingtoneUri_usesConfigValuesForUsageRingtoneMapping() {
+ @AttributeUsage int usage = USAGE_MEDIA;
+ String ringtoneValue = "content://settings/system/notification_sound";
+ setResources(new int[] {usage}, new String[] {ringtoneValue});
+ mRingtoneManager = new VolumeSettingsRingtoneManager(mContext);
+
+ Uri ringtoneUri = mRingtoneManager.getRingtoneUri(usage);
+
+ assertThat(ringtoneUri).isEqualTo(Uri.parse(ringtoneValue));
+ }
+
+ @Test
public void testPlayAudioFeedback_play_playUntilTimeout() {
mRingtoneManager.playAudioFeedback(TEST_GROUP_ID, TEST_USAGE_ID);
verify(mRingtone).play();
@@ -92,4 +137,13 @@
mRingtoneManager.stopCurrentRingtone();
verify(mRingtone, never()).stop();
}
+
+ private void setResources(int[] ringtoneAudioAttributeUsages, String[] ringtoneUris) {
+ Resources resources = spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(resources);
+ when(resources.getIntArray(R.array.config_ringtone_audio_attribute_usages_map_key))
+ .thenReturn(ringtoneAudioAttributeUsages);
+ when(resources.getStringArray(R.array.config_ringtone_uri_map_value))
+ .thenReturn(ringtoneUris);
+ }
}