From 85dfc2e225153b9b1b3c9e1e3f907736d0542b37 Mon Sep 17 00:00:00 2001 From: Beverly Date: Fri, 20 Sep 2019 11:26:34 -0400 Subject: [PATCH] Ringer toggle always affects system sounds Background: - When DND is on, users can allow "touch sounds" (system sounds) to bypass DND - The user-visible ringer stream and toggle controls notification, ringer, and system sounds Previously, allowing system sounds to bypass DND overrode the ringer from affecting the system sound stream which made the volume functionality of touch sounds different from in/out of DND. This fix ensures that DND always respects the fact that the ringer toggle and stream controls notifications, ringer, and system sounds at all times (whether in/out of DND). Test: atest ZenModeHelperTest Test: atest ZenModeConfigTest Test: atest AudioManagerTest Test: atest AudioManagerTest#testPriorityOnlySystemDisallowedWithRingerMuted Test: atest AudioManagerTest#testPriorityOnlySystemAllowed Fixes: 141292611 Change-Id: I6e36097f18a93ce554b3fad7e1a2bd1057ac9e1d --- .../android/preference/SeekBarVolumizer.java | 4 +- .../service/notification/ZenModeConfig.java | 30 +++++++------- .../volume/VolumeDialogControllerImpl.java | 4 +- .../android/server/audio/AudioService.java | 22 +++++++--- .../server/notification/ZenModeHelper.java | 20 +++------ .../notification/ZenModeConfigTest.java | 41 ++++++++++--------- .../notification/ZenModeHelperTest.java | 8 ++-- 7 files changed, 68 insertions(+), 61 deletions(-) diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index 2b3a2ab05e821..4dd9baba3e5f5 100644 --- a/core/java/android/preference/SeekBarVolumizer.java +++ b/core/java/android/preference/SeekBarVolumizer.java @@ -151,7 +151,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba .PRIORITY_CATEGORY_ALARMS) != 0; mAllowMedia = (mNotificationPolicy.priorityCategories & NotificationManager.Policy .PRIORITY_CATEGORY_MEDIA) != 0; - mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( + mAllowRinger = !ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted( mNotificationPolicy); mStreamType = streamType; mAffectedByRingerMode = mAudioManager.isStreamAffectedByRingerMode(mStreamType); @@ -571,7 +571,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba .PRIORITY_CATEGORY_ALARMS) != 0; mAllowMedia = (mNotificationPolicy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA) != 0; - mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( + mAllowRinger = !ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted( mNotificationPolicy); updateSlider(); } diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java index 937990f7e88e0..1f2c872a22334 100644 --- a/core/java/android/service/notification/ZenModeConfig.java +++ b/core/java/android/service/notification/ZenModeConfig.java @@ -1904,10 +1904,10 @@ public class ZenModeConfig implements Parcelable { } /** - * Determines whether dnd behavior should mute all notification/ringer sounds - * (sounds associated with ringer volume discluding system) + * Determines whether dnd behavior should mute all ringer-controlled sounds + * This includes notification, ringer and system sounds */ - public static boolean areAllPriorityOnlyNotificationZenSoundsMuted(NotificationManager.Policy + public static boolean areAllPriorityOnlyRingerSoundsMuted(NotificationManager.Policy policy) { boolean allowReminders = (policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS) != 0; @@ -1920,20 +1920,19 @@ public class ZenModeConfig implements Parcelable { boolean allowRepeatCallers = (policy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) != 0; boolean areChannelsBypassingDnd = (policy.state & Policy.STATE_CHANNELS_BYPASSING_DND) != 0; + boolean allowSystem = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_SYSTEM) != 0; return !allowReminders && !allowCalls && !allowMessages && !allowEvents - && !allowRepeatCallers && !areChannelsBypassingDnd; + && !allowRepeatCallers && !areChannelsBypassingDnd && !allowSystem; } /** - * Determines whether dnd behavior should mute all sounds controlled by ringer + * Determines whether dnd behavior should mute all sounds */ public static boolean areAllZenBehaviorSoundsMuted(NotificationManager.Policy policy) { boolean allowAlarms = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_ALARMS) != 0; boolean allowMedia = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_MEDIA) != 0; - boolean allowSystem = (policy.priorityCategories & Policy.PRIORITY_CATEGORY_SYSTEM) != 0; - return !allowAlarms && !allowMedia && !allowSystem - && areAllPriorityOnlyNotificationZenSoundsMuted(policy); + return !allowAlarms && !allowMedia && areAllPriorityOnlyRingerSoundsMuted(policy); } /** @@ -1943,24 +1942,25 @@ public class ZenModeConfig implements Parcelable { return zen == Global.ZEN_MODE_NO_INTERRUPTIONS || zen == Global.ZEN_MODE_ALARMS || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS - && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(consolidatedPolicy)); + && ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(consolidatedPolicy)); } /** - * Determines whether dnd behavior should mute all sounds controlled by ringer + * Determines whether dnd behavior should mute all ringer-controlled sounds + * This includes notification, ringer and system sounds */ - public static boolean areAllPriorityOnlyNotificationZenSoundsMuted(ZenModeConfig config) { + public static boolean areAllPriorityOnlyRingerSoundsMuted(ZenModeConfig config) { return !config.allowReminders && !config.allowCalls && !config.allowMessages && !config.allowEvents && !config.allowRepeatCallers - && !config.areChannelsBypassingDnd; + && !config.areChannelsBypassingDnd && !config.allowSystem; } /** - * Determines whether all dnd mutes all sounds + * Determines whether dnd mutes all sounds */ public static boolean areAllZenBehaviorSoundsMuted(ZenModeConfig config) { - return !config.allowAlarms && !config.allowMedia && !config.allowSystem - && areAllPriorityOnlyNotificationZenSoundsMuted(config); + return !config.allowAlarms && !config.allowMedia + && areAllPriorityOnlyRingerSoundsMuted(config); } /** diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java index edea92f5952a7..2c70fb4c50ecc 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java @@ -621,7 +621,9 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa .PRIORITY_CATEGORY_MEDIA) == 0; boolean disallowSystem = (policy.priorityCategories & NotificationManager.Policy .PRIORITY_CATEGORY_SYSTEM) == 0; - boolean disallowRinger = ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(policy); + // ringer controls notifications, ringer and system sounds, so only disallow ringer changes + // if all relevant (notifications + ringer + system) sounds are not allowed to bypass DND + boolean disallowRinger = ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(policy); if (mState.disallowAlarms == disallowAlarms && mState.disallowMedia == disallowMedia && mState.disallowRinger == disallowRinger diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 77b3feec700e2..ccbe08f475c34 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -3854,7 +3854,7 @@ public class AudioService extends IAudioService.Stub final boolean muteSystem = (zenPolicy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0; final boolean muteNotificationAndRing = ZenModeConfig - .areAllPriorityOnlyNotificationZenSoundsMuted( + .areAllPriorityOnlyRingerSoundsMuted( mNm.getConsolidatedNotificationPolicy()); return muteAlarms && isAlarm(streamType) || muteMedia && isMedia(streamType) @@ -3867,16 +3867,26 @@ public class AudioService extends IAudioService.Stub } /** - * DND total silence: media and alarms streams are tied to the muted ringer + * Notifications, ringer and system sounds are controlled by the ringer: * {@link ZenModeHelper.RingerModeDelegate#getRingerModeAffectedStreams(int)} - * DND alarms only: notification, ringer + system muted (by default tied to muted ringer mode) - * DND priority only: alarms, media, system streams can be muted separate from ringer based on + * DND total silence: media and alarms streams can be muted by DND + * DND alarms only: no streams additionally controlled by DND + * DND priority only: alarms, media, system streams can be muted by DND based on * zenPolicy (this method determines which streams) * @return true if changed, else false */ private boolean updateZenModeAffectedStreams() { + if (!mSystemReady) { + return false; + } + int zenModeAffectedStreams = 0; - if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { + final int zenMode = mNm.getZenMode(); + + if (zenMode == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS) { + zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM; + zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC; + } else if (zenMode == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy(); if ((zenPolicy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) { @@ -3888,6 +3898,8 @@ public class AudioService extends IAudioService.Stub zenModeAffectedStreams |= 1 << AudioManager.STREAM_MUSIC; } + // even if zen isn't muting the system stream, the ringer mode can still mute + // the system stream if ((zenPolicy.priorityCategories & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0) { zenModeAffectedStreams |= 1 << AudioManager.STREAM_SYSTEM; diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index f63aa52560783..65109230bb9a1 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -1179,7 +1179,7 @@ public class ZenModeHelper { if (mZenMode == Global.ZEN_MODE_OFF || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS - && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) { + && !ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(mConfig))) { // in priority only with ringer not muted, save ringer mode changes // in dnd off, save ringer mode changes setPreviousRingerModeSetting(ringerModeNew); @@ -1200,7 +1200,7 @@ public class ZenModeHelper { && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS || mZenMode == Global.ZEN_MODE_ALARMS || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS - && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( + && ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted( mConfig)))) { newZen = Global.ZEN_MODE_OFF; } else if (mZenMode != Global.ZEN_MODE_OFF) { @@ -1264,29 +1264,21 @@ public class ZenModeHelper { @Override public int getRingerModeAffectedStreams(int streams) { - // ringtone and notification streams are always affected by ringer mode - // system stream is affected by ringer mode when not in priority-only + // ringtone, notification and system streams are always affected by ringer mode + // zen muting is handled in AudioService.java's mZenModeAffectedStreams streams |= (1 << AudioSystem.STREAM_RING) | (1 << AudioSystem.STREAM_NOTIFICATION) | (1 << AudioSystem.STREAM_SYSTEM); if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { - // alarm and music streams affected by ringer mode when in total silence + // alarm and music streams affected by ringer mode (cannot be adjusted) when in + // total silence streams |= (1 << AudioSystem.STREAM_ALARM) | (1 << AudioSystem.STREAM_MUSIC); } else { streams &= ~((1 << AudioSystem.STREAM_ALARM) | (1 << AudioSystem.STREAM_MUSIC)); } - - if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS - && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) { - // system stream is not affected by ringer mode in priority only when the ringer - // is zen muted (all other notification categories are muted) - streams &= ~(1 << AudioSystem.STREAM_SYSTEM); - } else { - streams |= (1 << AudioSystem.STREAM_SYSTEM); - } return streams; } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java index dcab78ede2876..3d872237d8d46 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeConfigTest.java @@ -16,9 +16,10 @@ package com.android.server.notification; -import static junit.framework.Assert.assertEquals; +import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertNull; +import static junit.framework.TestCase.assertTrue; import android.app.NotificationManager.Policy; import android.content.ComponentName; @@ -52,18 +53,18 @@ public class ZenModeConfigTest extends UiServiceTestCase { @Test public void testPriorityOnlyMutingAllNotifications() { - ZenModeConfig config = getMutedNotificationsConfig(); - assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); + ZenModeConfig config = getMutedRingerConfig(); + assertTrue(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); config.allowReminders = true; - assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); + assertFalse(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); config.allowReminders = false; config.areChannelsBypassingDnd = true; - assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); + assertFalse(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); config.areChannelsBypassingDnd = false; - assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); + assertTrue(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); } @Test @@ -106,26 +107,26 @@ public class ZenModeConfigTest extends UiServiceTestCase { @Test public void testPriorityOnlyMutingAll() { ZenModeConfig config = getMutedAllConfig(); - assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); - assertEquals(true, ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); + assertTrue(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); + assertTrue(ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); config.allowReminders = true; - assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); - assertEquals(false, ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); + assertFalse(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); + assertFalse(ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); config.allowReminders = false; config.areChannelsBypassingDnd = true; - assertEquals(false, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); - assertEquals(false, ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); + assertFalse(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); + assertFalse(ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); config.areChannelsBypassingDnd = false; config.allowAlarms = true; - assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); - assertEquals(false, ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); + assertTrue(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); + assertFalse(ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); config.allowAlarms = false; - assertEquals(true, ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(config)); - assertEquals(true, ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); + assertTrue(ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(config)); + assertTrue(ZenModeConfig.areAllZenBehaviorSoundsMuted(config)); } @Test @@ -200,14 +201,14 @@ public class ZenModeConfigTest extends UiServiceTestCase { assertEquals(rule.zenMode, fromXml.zenMode); } - private ZenModeConfig getMutedNotificationsConfig() { + private ZenModeConfig getMutedRingerConfig() { ZenModeConfig config = new ZenModeConfig(); - // Allow alarms, media, and system + // Allow alarms, media config.allowAlarms = true; config.allowMedia = true; - config.allowSystem = true; - // All notification sounds are not allowed + // All sounds that respect the ringer are not allowed + config.allowSystem = false; config.allowCalls = false; config.allowRepeatCallers = false; config.allowMessages = false; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index 89364500fd80d..99771b91ee2ab 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -487,7 +487,6 @@ public class ZenModeHelperTest extends UiServiceTestCase { public void testRingerAffectedStreamsPriorityOnly() { // in priority only mode: // ringtone, notification and system streams are affected by ringer mode - // UNLESS ringer is muted due to all the other priority only dnd sounds being muted mZenModeHelperSpy.mConfig.allowAlarms = true; mZenModeHelperSpy.mConfig.allowReminders = true; mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; @@ -503,8 +502,9 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_ALARM)) == 0); assertTrue((ringerModeAffectedStreams & (1 << AudioSystem.STREAM_MUSIC)) == 0); - // special case: if ringer is muted (since all notification sounds cannot bypass) - // then system stream is not affected by ringer mode + // even when ringer is muted (since all ringer sounds cannot bypass DND), + // system stream is still affected by ringer mode + mZenModeHelperSpy.mConfig.allowSystem = false; mZenModeHelperSpy.mConfig.allowReminders = false; mZenModeHelperSpy.mConfig.allowCalls = false; mZenModeHelperSpy.mConfig.allowMessages = false; @@ -519,7 +519,7 @@ public class ZenModeHelperTest extends UiServiceTestCase { assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_NOTIFICATION)) != 0); assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_SYSTEM)) - == 0); + != 0); assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_ALARM)) == 0); assertTrue((ringerMutedRingerModeAffectedStreams & (1 << AudioSystem.STREAM_MUSIC)) == 0); }