diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java index 20405d3b725cb..7afe267f9c15b 100644 --- a/media/java/android/media/AudioAttributes.java +++ b/media/java/android/media/AudioAttributes.java @@ -244,6 +244,7 @@ public final class AudioAttributes implements Parcelable { SUPPRESSIBLE_USAGES.put(USAGE_GAME, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER); SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER); SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER); + SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN, SUPPRESSIBLE_MEDIA_SYSTEM_OTHER); } /** diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java index dab7632a0e53b..58976ca0d5cc8 100644 --- a/media/java/android/media/AudioManager.java +++ b/media/java/android/media/AudioManager.java @@ -43,17 +43,16 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; -import android.os.SystemClock; import android.os.ServiceManager; +import android.os.SystemClock; import android.os.UserHandle; import android.provider.Settings; import android.util.ArrayMap; import android.util.Log; -import android.util.Pair; +import android.util.Slog; import android.view.KeyEvent; import java.util.ArrayList; -import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -1966,9 +1965,28 @@ public class AudioManager { */ private boolean querySoundEffectsEnabled(int user) { return Settings.System.getIntForUser(getContext().getContentResolver(), - Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0; + Settings.System.SOUND_EFFECTS_ENABLED, 0, user) != 0 + && !areSystemSoundsZenModeBlocked(getContext()); } + private boolean areSystemSoundsZenModeBlocked(Context context) { + int zenMode = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.ZEN_MODE, 0); + + switch (zenMode) { + case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS: + case Settings.Global.ZEN_MODE_ALARMS: + return true; + case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: + final NotificationManager noMan = (NotificationManager) context + .getSystemService(Context.NOTIFICATION_SERVICE); + return (noMan.getNotificationPolicy().priorityCategories + & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0; + case Settings.Global.ZEN_MODE_OFF: + default: + return false; + } + } /** * Load Sound effects. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 28adca97b8bf8..a35ba9fadab45 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -28,6 +28,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR import android.app.Activity; import android.app.ActivityManager; import android.app.AlarmManager; +import android.app.NotificationManager; import android.app.PendingIntent; import android.app.StatusBarManager; import android.app.trust.TrustManager; @@ -1691,6 +1692,8 @@ public class KeyguardViewMediator extends SystemUI { mUiOffloadThread.submit(() -> { // If the stream is muted, don't play the sound if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return; + // If DND blocks the sound, don't play the sound + if (areSystemSoundsZenModeBlocked(mContext)) return; int id = mLockSounds.play(soundId, mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/); @@ -1702,6 +1705,25 @@ public class KeyguardViewMediator extends SystemUI { } } + private boolean areSystemSoundsZenModeBlocked(Context context) { + int zenMode = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.ZEN_MODE, 0); + + switch (zenMode) { + case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS: + case Settings.Global.ZEN_MODE_ALARMS: + return true; + case Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: + final NotificationManager noMan = (NotificationManager) context + .getSystemService(Context.NOTIFICATION_SERVICE); + return (noMan.getNotificationPolicy().priorityCategories + & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0; + case Settings.Global.ZEN_MODE_OFF: + default: + return false; + } + } + private void playTrustedSound() { playSound(mTrustedSoundId); } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index f61cec9713c01..1e9fab5ce5748 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -835,7 +835,8 @@ public class ZenModeHelper { // alarm restrictions final boolean muteMediaAndSystemSounds = zen && !mConfig.allowMediaSystemOther; // total silence restrictions - final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; + final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS + || areAllBehaviorSoundsMuted(); for (int usage : AudioAttributes.SDK_USAGES) { final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage); @@ -855,9 +856,11 @@ public class ZenModeHelper { } } + @VisibleForTesting protected void applyRestrictions(boolean mute, int usage) { final String[] exceptionPackages = null; // none (for now) + mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage, mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, exceptionPackages); @@ -866,6 +869,12 @@ public class ZenModeHelper { exceptionPackages); } + private boolean areAllBehaviorSoundsMuted() { + return !mConfig.allowAlarms && !mConfig.allowMediaSystemOther && !mConfig.allowReminders + && !mConfig.allowCalls && !mConfig.allowMessages && !mConfig.allowEvents + && !mConfig.allowRepeatCallers; + } + private void applyZenToRingerMode() { if (mAudioManager == null) return; // force the ringer mode into compliance diff --git a/services/tests/notification/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/notification/src/com/android/server/notification/ZenModeHelperTest.java index cbe9650edc43b..8ac6481e69d9a 100644 --- a/services/tests/notification/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/notification/src/com/android/server/notification/ZenModeHelperTest.java @@ -17,7 +17,7 @@ package com.android.server.notification; import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertTrue; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; @@ -100,5 +100,34 @@ public class ZenModeHelperTest extends NotificationTestCase { AudioAttributes.USAGE_GAME); verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, AudioAttributes.USAGE_ASSISTANCE_SONIFICATION); + verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, + AudioAttributes.USAGE_UNKNOWN); + } + + @Test + public void testZenAllCannotBypass() { + // Only audio attributes with SUPPRESIBLE_NEVER can bypass + mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; + mZenModeHelperSpy.mConfig.allowAlarms = false; + mZenModeHelperSpy.mConfig.allowMediaSystemOther = false; + mZenModeHelperSpy.mConfig.allowReminders = false; + mZenModeHelperSpy.mConfig.allowCalls = false; + mZenModeHelperSpy.mConfig.allowMessages = false; + mZenModeHelperSpy.mConfig.allowEvents = false; + mZenModeHelperSpy.mConfig.allowRepeatCallers= false; + assertFalse(mZenModeHelperSpy.mConfig.allowAlarms); + assertFalse(mZenModeHelperSpy.mConfig.allowMediaSystemOther); + assertFalse(mZenModeHelperSpy.mConfig.allowReminders); + assertFalse(mZenModeHelperSpy.mConfig.allowCalls); + assertFalse(mZenModeHelperSpy.mConfig.allowMessages); + assertFalse(mZenModeHelperSpy.mConfig.allowEvents); + assertFalse(mZenModeHelperSpy.mConfig.allowRepeatCallers); + mZenModeHelperSpy.applyRestrictions(); + + for (int usage : AudioAttributes.SDK_USAGES) { + boolean shouldMute = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage) + != AudioAttributes.SUPPRESSIBLE_NEVER; + verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(shouldMute, usage); + } } }