Merge "Muting ring volume slider disables notification" into tm-qpr-dev
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d2871ea..ecf378d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -8828,6 +8828,9 @@
<!-- Sound: Title for the option managing notification volume. [CHAR LIMIT=30] -->
<string name="notification_volume_option_title">Notification volume</string>
+ <!-- Sound: Summary for when notification volume is disabled. [CHAR LIMIT=100] -->
+ <string name="notification_volume_disabled_summary">Unavailable because ring is muted</string>
+
<!-- Sound: Title for the option defining the phone ringtone. [CHAR LIMIT=30] -->
<string name="ringtone_title">Phone ringtone</string>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index a84b0ae..7181e80 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -86,8 +86,8 @@
android:icon="@drawable/ic_notifications"
android:title="@string/notification_volume_option_title"
android:order="-150"
- settings:controller=
- "com.android.settings.notification.NotificationVolumePreferenceController"/>
+ settings:controller="com.android.settings.notification.NotificationVolumePreferenceController"
+ settings:unavailableSliceSubtitle="@string/notification_volume_disabled_summary"/>
<!-- Alarm volume -->
<com.android.settings.notification.VolumeSeekBarPreference
diff --git a/src/com/android/settings/notification/NotificationVolumePreferenceController.java b/src/com/android/settings/notification/NotificationVolumePreferenceController.java
index 4fd2341..54d7854 100644
--- a/src/com/android/settings/notification/NotificationVolumePreferenceController.java
+++ b/src/com/android/settings/notification/NotificationVolumePreferenceController.java
@@ -51,7 +51,6 @@
private final RingReceiver mReceiver = new RingReceiver();
private final H mHandler = new H();
-
public NotificationVolumePreferenceController(Context context) {
this(context, KEY_NOTIFICATION_VOLUME);
}
@@ -63,7 +62,9 @@
mVibrateIconId = R.drawable.ic_volume_ringer_vibrate;
mSilentIconId = R.drawable.ic_notifications_off_24dp;
- updateRingerMode();
+ if (updateRingerMode()) {
+ updateEnabledState();
+ }
}
/**
@@ -77,12 +78,10 @@
if (mPreference == null) {
setupVolPreference(screen);
}
- mSeparateNotification = isSeparateNotificationConfigEnabled();
- if (mPreference != null) {
- mPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
- }
+
updateEffectsSuppressor();
selectPreferenceIconState();
+ updateEnabledState();
}
/**
@@ -95,15 +94,19 @@
boolean newVal = isSeparateNotificationConfigEnabled();
if (newVal != mSeparateNotification) {
mSeparateNotification = newVal;
- // manually hiding the preference because being unavailable does not do the job
+ // Update UI if config change happens when Sound Settings page is on the foreground
if (mPreference != null) {
- mPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
+ int status = getAvailabilityStatus();
+ mPreference.setVisible(status == AVAILABLE
+ || status == DISABLED_DEPENDENT_SETTING);
+ if (status == DISABLED_DEPENDENT_SETTING) {
+ mPreference.setEnabled(false);
+ }
}
}
}
}
-
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@Override
public void onResume() {
@@ -126,10 +129,11 @@
@Override
public int getAvailabilityStatus() {
boolean separateNotification = isSeparateNotificationConfigEnabled();
-
return mContext.getResources().getBoolean(R.bool.config_show_notification_volume)
&& !mHelper.isSingleVolume() && separateNotification
- ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ ? (mRingerMode == AudioManager.RINGER_MODE_NORMAL
+ ? AVAILABLE : DISABLED_DEPENDENT_SETTING)
+ : UNSUPPORTED_ON_DEVICE;
}
@Override
@@ -158,7 +162,6 @@
if (mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
mMuteIcon = mVibrateIconId;
mPreference.showIcon(mVibrateIconId);
-
} else if (mRingerMode == AudioManager.RINGER_MODE_SILENT
|| mVibrator == null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
mMuteIcon = mSilentIconId;
@@ -175,6 +178,12 @@
}
}
+ private void updateEnabledState() {
+ if (mPreference != null) {
+ mPreference.setEnabled(mRingerMode == AudioManager.RINGER_MODE_NORMAL);
+ }
+ }
+
private final class H extends Handler {
private static final int UPDATE_EFFECTS_SUPPRESSOR = 1;
private static final int UPDATE_RINGER_MODE = 2;
@@ -191,10 +200,13 @@
updateEffectsSuppressor();
break;
case UPDATE_RINGER_MODE:
- updateRingerMode();
+ if (updateRingerMode()) {
+ updateEnabledState();
+ }
break;
case NOTIFICATION_VOLUME_CHANGED:
selectPreferenceIconState();
+ updateEnabledState();
break;
}
}
@@ -239,5 +251,4 @@
}
}
}
-
}
diff --git a/src/com/android/settings/notification/RingerModeAffectedVolumePreferenceController.java b/src/com/android/settings/notification/RingerModeAffectedVolumePreferenceController.java
index 255fe2f..ec619b4 100644
--- a/src/com/android/settings/notification/RingerModeAffectedVolumePreferenceController.java
+++ b/src/com/android/settings/notification/RingerModeAffectedVolumePreferenceController.java
@@ -140,11 +140,18 @@
return valueUpdated;
}
- protected void updateRingerMode() {
+ /**
+ * Updates UI Icon in response to ringer mode changes.
+ * @return whether the ringer mode has changed.
+ */
+ protected boolean updateRingerMode() {
final int ringerMode = mHelper.getRingerModeInternal();
- if (mRingerMode == ringerMode) return;
+ if (mRingerMode == ringerMode) {
+ return false;
+ }
mRingerMode = ringerMode;
selectPreferenceIconState();
+ return true;
}
/**
diff --git a/src/com/android/settings/slices/VolumeSliceHelper.java b/src/com/android/settings/slices/VolumeSliceHelper.java
index 4861482..1ba1778 100644
--- a/src/com/android/settings/slices/VolumeSliceHelper.java
+++ b/src/com/android/settings/slices/VolumeSliceHelper.java
@@ -93,8 +93,9 @@
if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) {
handleVolumeChanged(context, intent);
- } else if (AudioManager.STREAM_MUTE_CHANGED_ACTION.equals(action)
- || AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) {
+ } else if (AudioManager.STREAM_MUTE_CHANGED_ACTION.equals(action)) {
+ handleMuteChanged(context, intent);
+ } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) {
handleStreamChanged(context, intent);
} else {
notifyAllStreamsChanged(context);
@@ -109,8 +110,29 @@
}
}
+ /**
+ * When mute is changed, notifyChange on relevant Volume Slice ContentResolvers to mark them
+ * as needing update.
+ *
+ * In addition to the matching stream, we always notifyChange for the Notification stream
+ * when Ring events are issued. This is to make sure that Notification always gets updated
+ * for RingerMode changes, even if Notification's volume is zero and therefore it would not
+ * get its own AudioManager.VOLUME_CHANGED_ACTION.
+ */
+ private static void handleMuteChanged(Context context, Intent intent) {
+ final int inputType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ handleStreamChanged(context, inputType);
+ if (inputType == AudioManager.STREAM_RING) {
+ handleStreamChanged(context, AudioManager.STREAM_NOTIFICATION);
+ }
+ }
+
private static void handleStreamChanged(Context context, Intent intent) {
final int inputType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ handleStreamChanged(context, inputType);
+ }
+
+ private static void handleStreamChanged(Context context, int inputType) {
synchronized (sRegisteredUri) {
for (Map.Entry<Uri, Integer> entry : sRegisteredUri.entrySet()) {
if (entry.getValue() == inputType) {
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
index 7e7ad10..594ef62 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
@@ -198,6 +198,7 @@
com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
// block the alternative condition to enable controller
when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "false", false);
@@ -217,8 +218,8 @@
SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, Boolean.toString(true),
false);
- assertThat(controller.getAvailabilityStatus()
- == BasePreferenceController.AVAILABLE).isTrue();
+ assertThat(controller.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.AVAILABLE);
}
@Test
@@ -233,9 +234,10 @@
// block the alternative condition to enable controller
when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_NORMAL);
+
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "true", false);
-
NotificationVolumePreferenceController controller =
new NotificationVolumePreferenceController(mContext);
@@ -254,4 +256,19 @@
== BasePreferenceController.UNSUPPORTED_ON_DEVICE).isTrue();
}
+ @Test
+ public void ringerModeSilent_unaliased_getAvailability_returnsDisabled() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
+ when(mHelper.isSingleVolume()).thenReturn(false);
+
+ when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
+
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.VOLUME_SEPARATE_NOTIFICATION, "true", false);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING);
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/slices/VolumeSliceHelperTest.java b/tests/robotests/src/com/android/settings/slices/VolumeSliceHelperTest.java
index 2ceeb25..b4abd8c 100644
--- a/tests/robotests/src/com/android/settings/slices/VolumeSliceHelperTest.java
+++ b/tests/robotests/src/com/android/settings/slices/VolumeSliceHelperTest.java
@@ -34,6 +34,7 @@
import android.net.Uri;
import com.android.settings.notification.MediaVolumePreferenceController;
+import com.android.settings.notification.NotificationVolumePreferenceController;
import com.android.settings.notification.RingVolumePreferenceController;
import com.android.settings.notification.SeparateRingVolumePreferenceController;
import com.android.settings.notification.VolumeSeekBarPreferenceController;
@@ -64,6 +65,7 @@
private VolumeSeekBarPreferenceController mMediaController;
private VolumeSeekBarPreferenceController mRingController;
private VolumeSeekBarPreferenceController mSeparateRingController;
+ private VolumeSeekBarPreferenceController mNotificationController;
@Before
public void setUp() {
@@ -72,8 +74,9 @@
when(mContext.getContentResolver()).thenReturn(mResolver);
mMediaController = new MediaVolumePreferenceController(mContext);
- mSeparateRingController = new SeparateRingVolumePreferenceController(mContext);
mRingController = new RingVolumePreferenceController(mContext);
+ mSeparateRingController = new SeparateRingVolumePreferenceController(mContext);
+ mNotificationController = new NotificationVolumePreferenceController(mContext);
mIntent = createIntent(AudioManager.VOLUME_CHANGED_ACTION)
.putExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, 1)
@@ -238,6 +241,40 @@
verify(mResolver).notifyChange(mMediaController.getSliceUri(), null);
}
+ /**
+ * Without this test passing, when notification is separated from ring and its value is already
+ * zero, setting ringermode to silent would not disable notification slider.
+ * Note: the above scenario happens only in volume panel where controllers do not get to
+ * register for events such as RINGER_MODE_CHANGE.
+ */
+ @Test
+ public void onReceive_ringVolumeMuted_shouldNotifyChangeNotificationSlice() {
+ final Intent intent = createIntent(AudioManager.STREAM_MUTE_CHANGED_ACTION)
+ .putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mRingController.getAudioStream());
+ registerIntentToUri(mRingController);
+ registerIntentToUri(mNotificationController);
+
+ VolumeSliceHelper.onReceive(mContext, intent);
+
+ verify(mResolver).notifyChange(mNotificationController.getSliceUri(), null);
+ }
+
+ /**
+ * Notifying notification slice on ring mute does not mean it should not notify ring slice.
+ * Rather, it should notify both slices.
+ */
+ @Test
+ public void onReceive_ringVolumeMuted_shouldNotifyChangeRingSlice() {
+ final Intent intent = createIntent(AudioManager.STREAM_MUTE_CHANGED_ACTION)
+ .putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mRingController.getAudioStream());
+ registerIntentToUri(mRingController);
+ registerIntentToUri(mNotificationController);
+
+ VolumeSliceHelper.onReceive(mContext, intent);
+
+ verify(mResolver).notifyChange(mRingController.getSliceUri(), null);
+ }
+
@Test
public void onReceive_streamDevicesChanged_shouldNotifyChange() {
final Intent intent = createIntent(AudioManager.STREAM_DEVICES_CHANGED_ACTION)