diff --git a/res/drawable/ic_ring_volume.xml b/res/drawable/ic_ring_volume.xml
new file mode 100644
index 00000000000..343fe5d4cb6
--- /dev/null
+++ b/res/drawable/ic_ring_volume.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable/ic_ring_volume_off.xml b/res/drawable/ic_ring_volume_off.xml
new file mode 100644
index 00000000000..74f30d1a44d
--- /dev/null
+++ b/res/drawable/ic_ring_volume_off.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6ac39b88f40..0a4421a5b33 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -7187,9 +7187,12 @@
Alarm volume
-
+
Ring & notification volume
+
+ Ring volume
+
Notification volume
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index f25b6ec54b0..914ce72428d 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -72,23 +72,23 @@
android:order="-160"
settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
+
+
-
-
-
-
+ settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
+x
> mSliceLiveData;
private final int mMetricsCategory;
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index d1b169c2976..569a0eaac7f 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -217,6 +217,16 @@ public class CustomSliceRegistry {
.appendPath("ring_volume")
.build();
+ /**
+ * Full {@link Uri} for the Notification volume Slice.
+ */
+ public static final Uri VOLUME_NOTIFICATION_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("notification_volume")
+ .build();
+
/**
* Full {@link Uri} for the all volume Slices.
*/
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
index fe4744fecab..96b9e6219c8 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
@@ -22,10 +22,14 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Vibrator;
+import android.service.notification.NotificationListenerService;
import android.telephony.TelephonyManager;
+import com.android.internal.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,6 +50,8 @@ public class NotificationVolumePreferenceControllerTest {
private AudioManager mAudioManager;
@Mock
private Vibrator mVibrator;
+ @Mock
+ private Resources mResources;
private Context mContext;
private NotificationVolumePreferenceController mController;
@@ -57,6 +63,8 @@ public class NotificationVolumePreferenceControllerTest {
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager);
when(mContext.getSystemService(Context.VIBRATOR_SERVICE)).thenReturn(mVibrator);
+ when(mContext.getResources()).thenReturn(mResources);
+
mController = new NotificationVolumePreferenceController(mContext);
mController.setAudioHelper(mHelper);
}
@@ -76,15 +84,50 @@ public class NotificationVolumePreferenceControllerTest {
}
@Test
- public void isAvailable_voiceCapable_shouldReturnFalse() {
+ public void isAvailable_voiceCapable_aliasedWithRing_shouldReturnFalse() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_alias_ring_notif_stream_types)).thenReturn(true);
+
+ NotificationVolumePreferenceController controller =
+ new NotificationVolumePreferenceController(mContext);
when(mHelper.isSingleVolume()).thenReturn(false);
when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ assertThat(controller.isAvailable()).isFalse();
+ }
+
+ /**
+ * With the introduction of ring-notification volume separation, voice-capable devices could now
+ * display the notification volume slider.
+ */
+ @Test
+ public void isAvailable_voiceCapable_separatedFromRing_shouldReturnTrue() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_alias_ring_notif_stream_types)).thenReturn(false);
+
+ NotificationVolumePreferenceController controller =
+ new NotificationVolumePreferenceController(mContext);
+
+ when(mHelper.isSingleVolume()).thenReturn(false);
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+
+ assertThat(controller.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_notShowNotificationVolume_shouldReturnFalse() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(false);
+
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_notSingleVolume_notVoiceCapable_shouldReturnTrue() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
when(mHelper.isSingleVolume()).thenReturn(false);
when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
@@ -107,4 +150,24 @@ public class NotificationVolumePreferenceControllerTest {
public void isPublicSlice_returnTrue() {
assertThat(mController.isPublicSlice()).isTrue();
}
+
+ @Test
+ public void setHintsRing_DoesNotMatch() {
+ assertThat(mController.hintsMatch(
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS)).isFalse();
+ }
+
+ @Test
+ public void setHintsAll_Matches() {
+ assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS))
+ .isTrue();
+ }
+
+ @Test
+ public void setHintNotification_Matches() {
+ assertThat(mController
+ .hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS))
+ .isTrue();
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
index 5e484a3bfd5..02757d52874 100644
--- a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
@@ -18,15 +18,20 @@ package com.android.settings.notification;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Vibrator;
+import android.service.notification.NotificationListenerService;
import android.telephony.TelephonyManager;
+import com.android.settings.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,8 +56,13 @@ public class RingVolumePreferenceControllerTest {
private NotificationManager mNotificationManager;
@Mock
private ComponentName mSuppressor;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private VolumeSeekBarPreference mPreference;
private Context mContext;
+
private RingVolumePreferenceController mController;
@Before
@@ -63,8 +73,9 @@ public class RingVolumePreferenceControllerTest {
shadowContext.setSystemService(Context.AUDIO_SERVICE, mAudioManager);
shadowContext.setSystemService(Context.VIBRATOR_SERVICE, mVibrator);
shadowContext.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
when(mNotificationManager.getEffectsSuppressor()).thenReturn(mSuppressor);
+ when(mContext.getResources()).thenReturn(mResources);
mController = new RingVolumePreferenceController(mContext);
mController.setAudioHelper(mHelper);
}
@@ -109,4 +120,92 @@ public class RingVolumePreferenceControllerTest {
public void isPublicSlice_returnTrue() {
assertThat(mController.isPublicSlice()).isTrue();
}
+
+ // todo: verify that the title change is displayed, by examining the underlying preference
+ @Test
+ public void ringNotificationStreamsNotAliased_sliderTitleSetToRingOnly() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types))
+ .thenReturn(false);
+ final RingVolumePreferenceController controller =
+ new RingVolumePreferenceController(mContext);
+
+ int expectedTitleId = R.string.separate_ring_volume_option_title;
+
+ assertThat(controller.mTitleId).isEqualTo(expectedTitleId);
+ }
+
+ @Test
+ public void ringNotificationStreamsAliased_sliderTitleIncludesBothRingNotification() {
+
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types)).thenReturn(true);
+ final RingVolumePreferenceController control = new RingVolumePreferenceController(mContext);
+
+ int expectedTitleId = R.string.ring_volume_option_title;
+
+ assertThat(control.mTitleId).isEqualTo(expectedTitleId);
+ }
+
+ @Test
+ public void setHintsRing_aliased_Matches() {
+ assertThat(mController.hintsMatch(
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, true)).isTrue();
+ }
+
+ @Test
+ public void setHintsRingNotification_aliased_Matches() {
+ assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS,
+ true)).isTrue();
+ }
+
+ @Test
+ public void setHintNotification_aliased_Matches() {
+ assertThat(mController
+ .hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS,
+ true)).isTrue();
+ }
+
+ @Test
+ public void setHintsRing_unaliased_Matches() {
+ assertThat(mController.hintsMatch(
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, false)).isTrue();
+ }
+
+ @Test
+ public void setHintsRingNotification_unaliased_Matches() {
+ assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS,
+ false)).isTrue();
+ }
+
+ @Test
+ public void setHintNotification_unaliased_doesNotMatch() {
+ assertThat(mController
+ .hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS,
+ false)).isFalse();
+ }
+
+ @Test
+ public void setRingerModeToVibrate_butNoVibratorAvailable_iconIsSilent() {
+ when(mHelper.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+
+ mController.setPreference(mPreference);
+ mController.setVibrator(null);
+ mController.updateRingerMode();
+
+ assertThat(mController.getMuteIcon()).isEqualTo(mController.mSilentIconId);
+ }
+
+ @Test
+ public void setRingerModeToVibrate_VibratorAvailable_iconIsVibrate() {
+ when(mHelper.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+ when(mVibrator.hasVibrator()).thenReturn(true);
+
+ mController.setPreference(mPreference);
+ mController.setVibrator(mVibrator);
+ mController.updateRingerMode();
+
+ assertThat(mController.getMuteIcon()).isEqualTo(mController.mVibrateIconId);
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java b/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
index c2ea6e70105..9e84883b7e6 100644
--- a/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
@@ -35,6 +35,7 @@ import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settings.testutils.shadow.ShadowUserManager;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -44,8 +45,6 @@ import org.robolectric.util.ReflectionHelpers;
import java.util.List;
-import org.junit.Ignore;
-
@RunWith(RobolectricTestRunner.class)
public class SoundSettingsTest {
@@ -86,4 +85,19 @@ public class SoundSettingsTest {
assertThat(settings.mHandler.hasMessages(SoundSettings.STOP_SAMPLE)).isTrue();
}
+
+ @Test
+ public void notificationVolume_isBetweenRingAndAlarm() {
+ final Context context = spy(RuntimeEnvironment.application);
+ final SoundSettings settings = new SoundSettings();
+ final int xmlId = settings.getPreferenceScreenResId();
+ final List keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
+
+ int ring = keys.indexOf("ring_volume");
+ int notification = keys.indexOf("notification_volume");
+ int alarm = keys.indexOf("alarm_volume");
+
+ assertThat(ring < notification).isTrue();
+ assertThat(notification < alarm).isTrue();
+ }
}