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 b8a5202f139..458f6fc40d1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8727,9 +8727,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(); + } }