Alarms and Media visibly muted in PriorityOnly dnd

- if alarms and/or media cannot pass dnd and the phone is currently
in priority only dnd, then the alarm and/or media volume stream
will appear muted in the volume dialog and sound settings
(Settings > Sound)
- if all behavior for priority only dnd is not allowed to bypass dnd
(discluding alarms and media), then ringer is muted when priority-only
dnd mode is on. If a user clicks this ringer in the volume dialog, then
dnd ends
- Updated default zen config to version 3 (added alarms and media)
Test: manually toggle alarms + media in Settings > Sound > DND >
Behavior, toggle on/off dnd and then look at volume dialog and
volume bars in Settings > Sound
Test: runtest --path cts/tests/tests/media/src/android/media/cts/AudioManagerTest.java
Fixes: 72052742

Change-Id: Ia9e809ec2be93cb5a9ba6518dce04bf3ce45110b
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index 3d2e1d1..d774281 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -34,6 +34,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.provider.Settings.System;
+import android.service.notification.ZenModeConfig;
 import android.util.Log;
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
@@ -87,10 +88,22 @@
     private static final int MSG_INIT_SAMPLE = 3;
     private static final int CHECK_RINGTONE_PLAYBACK_DELAY_MS = 1000;
 
+    private NotificationManager.Policy mNotificationPolicy;
+    private boolean mAllowAlarms;
+    private boolean mAllowMediaSystem;
+    private boolean mAllowRinger;
+
     public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
         mContext = context;
         mAudioManager = context.getSystemService(AudioManager.class);
         mNotificationManager = context.getSystemService(NotificationManager.class);
+        mNotificationPolicy = mNotificationManager.getNotificationPolicy();
+        mAllowAlarms = (mNotificationPolicy.priorityCategories & NotificationManager.Policy
+                .PRIORITY_CATEGORY_ALARMS) != 0;
+        mAllowMediaSystem = (mNotificationPolicy.priorityCategories & NotificationManager.Policy
+                .PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0;
+        mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
+                mNotificationPolicy);
         mStreamType = streamType;
         mAffectedByRingerMode = mAudioManager.isStreamAffectedByRingerMode(mStreamType);
         mNotificationOrRing = isNotificationOrRing(mStreamType);
@@ -122,6 +135,14 @@
         return stream == AudioManager.STREAM_RING || stream == AudioManager.STREAM_NOTIFICATION;
     }
 
+    private static boolean isAlarmsStream(int stream) {
+        return stream == AudioManager.STREAM_ALARM;
+    }
+
+    private static boolean isMediaOrSystemStream(int stream) {
+        return stream == AudioManager.STREAM_MUSIC || stream == AudioManager.STREAM_SYSTEM;
+    }
+
     public void setSeekBar(SeekBar seekBar) {
         if (mSeekBar != null) {
             mSeekBar.setOnSeekBarChangeListener(null);
@@ -135,7 +156,11 @@
 
     private boolean isZenMuted() {
         return mNotificationOrRing && mZenMode == Global.ZEN_MODE_ALARMS
-                || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+                || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
+                || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                    && ((!mAllowAlarms && isAlarmsStream(mStreamType))
+                        || (!mAllowMediaSystem && isMediaOrSystemStream(mStreamType))
+                        || (!mAllowRinger && isNotificationOrRing(mStreamType))));
     }
 
     protected void updateSeekBar() {
@@ -396,6 +421,7 @@
                 final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
                 filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
                 filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+                filter.addAction(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
                 filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
                 mContext.registerReceiver(this, filter);
             } else {
@@ -424,6 +450,15 @@
             } else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) {
                 mZenMode = mNotificationManager.getZenMode();
                 updateSlider();
+            } else if (NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED.equals(action)) {
+                mNotificationPolicy = mNotificationManager.getNotificationPolicy();
+                mAllowAlarms = (mNotificationPolicy.priorityCategories & NotificationManager.Policy
+                        .PRIORITY_CATEGORY_ALARMS) != 0;
+                mAllowMediaSystem = (mNotificationPolicy.priorityCategories
+                        & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) != 0;
+                mAllowRinger = !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
+                        mNotificationPolicy);
+                updateSlider();
             }
         }
 
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index f658ae0..5e56d07 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -17,6 +17,7 @@
 package android.service.notification;
 
 import android.app.ActivityManager;
+import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.content.ComponentName;
 import android.content.Context;
@@ -1385,4 +1386,38 @@
         }
     }
 
+    /**
+     * Determines whether dnd behavior should mute all notification sounds
+     */
+    public static boolean areAllPriorityOnlyNotificationZenSoundsMuted(NotificationManager.Policy
+            policy) {
+        boolean allowReminders = (policy.priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS) != 0;
+        boolean allowCalls = (policy.priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_CALLS) != 0;
+        boolean allowMessages = (policy.priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES) != 0;
+        boolean allowEvents = (policy.priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS) != 0;
+        boolean allowRepeatCallers = (policy.priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) != 0;
+        return !allowReminders && !allowCalls && !allowMessages && !allowEvents
+                && !allowRepeatCallers;
+    }
+
+    /**
+     * Determines whether dnd behavior should mute all notification sounds
+     */
+    public static boolean areAllPriorityOnlyNotificationZenSoundsMuted(ZenModeConfig config) {
+        return !config.allowReminders && !config.allowCalls && !config.allowMessages
+                && !config.allowEvents && !config.allowRepeatCallers;
+    }
+
+    /**
+     * Determines whether all dnd mutes all sounds
+     */
+    public static boolean areAllZenBehaviorSoundsMuted(ZenModeConfig config) {
+        return !config.allowAlarms  && !config.allowMediaSystemOther
+                && areAllPriorityOnlyNotificationZenSoundsMuted(config);
+    }
 }
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index 1e4c03e..a446088 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -19,5 +19,6 @@
 
 <!-- Default configuration for zen mode.  See android.service.notification.ZenModeConfig. -->
 <zen version="2">
-    <allow alarms="true" media_system_other="true" calls="false" messages="false" reminders="false" events="false" />
+    <allow alarms="true" media_system_other="true" calls="false" messages="false" reminders="false"
+           events="false" />
 </zen>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
index 32eb5d5..4b3afdc 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/VolumeDialogController.java
@@ -99,6 +99,9 @@
         public ComponentName effectsSuppressor;
         public String effectsSuppressorName;
         public int activeStream = NO_ACTIVE_STREAM;
+        public boolean disallowAlarms;
+        public boolean disallowMedia;
+        public boolean disallowRinger;
 
         public State copy() {
             final State rt = new State();
@@ -113,6 +116,9 @@
             }
             rt.effectsSuppressorName = effectsSuppressorName;
             rt.activeStream = activeStream;
+            rt.disallowAlarms = disallowAlarms;
+            rt.disallowMedia = disallowMedia;
+            rt.disallowRinger = disallowRinger;
             return rt;
         }
 
@@ -142,6 +148,9 @@
             sep(sb, indent); sb.append("effectsSuppressor:").append(effectsSuppressor);
             sep(sb, indent); sb.append("effectsSuppressorName:").append(effectsSuppressorName);
             sep(sb, indent); sb.append("activeStream:").append(activeStream);
+            sep(sb, indent); sb.append("disallowAlarms:").append(disallowAlarms);
+            sep(sb, indent); sb.append("disallowMedia:").append(disallowMedia);
+            sep(sb, indent); sb.append("disallowRinger:").append(disallowRinger);
             if (indent > 0) sep(sb, indent);
             return sb.append('}').toString();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index e1376ca..2c85bb6 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -51,6 +51,7 @@
     public static final int EVENT_SUPPRESSOR_CHANGED = 14;  // (component|string) (name|string)
     public static final int EVENT_MUTE_CHANGED = 15;  // (stream|int) (muted|bool)
     public static final int EVENT_TOUCH_LEVEL_DONE = 16;  // (stream|int) (level|bool)
+    public static final int EVENT_ZEN_CONFIG_CHANGED = 17; // (allow/disallow|string)
 
     private static final String[] EVENT_TAGS = {
         "show_dialog",
@@ -70,6 +71,7 @@
         "suppressor_changed",
         "mute_changed",
         "touch_level_done",
+        "zen_mode_config_changed",
     };
 
     public static final int DISMISS_REASON_UNKNOWN = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 2e23920..a166db5 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -43,6 +43,7 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.service.notification.Condition;
+import android.service.notification.ZenModeConfig;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.accessibility.AccessibilityManager;
@@ -109,6 +110,7 @@
     private boolean mShowSafetyWarning;
     private DeviceCallback mDeviceCallback = new DeviceCallback();
     private AudioDeviceInfo mConnectedDevice;
+    private final NotificationManager mNotificationManager;
 
     private boolean mDestroyed;
     private VolumePolicy mVolumePolicy;
@@ -120,6 +122,8 @@
 
     public VolumeDialogControllerImpl(Context context) {
         mContext = context.getApplicationContext();
+        mNotificationManager = (NotificationManager) mContext.getSystemService(
+                Context.NOTIFICATION_SERVICE);
         Events.writeEvent(mContext, Events.EVENT_COLLECTION_STARTED);
         mWorkerThread = new HandlerThread(VolumeDialogControllerImpl.class.getSimpleName());
         mWorkerThread.start();
@@ -425,6 +429,7 @@
         }
         updateRingerModeExternalW(mAudio.getRingerMode());
         updateZenModeW();
+        updateZenConfig();
         updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
         mCallbacks.onStateChanged(mState);
     }
@@ -510,6 +515,26 @@
         return true;
     }
 
+    private boolean updateZenConfig() {
+        final NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy();
+        boolean disallowAlarms = (policy.priorityCategories & NotificationManager.Policy
+                .PRIORITY_CATEGORY_ALARMS) == 0;
+        boolean disallowMedia = (policy.priorityCategories & NotificationManager.Policy
+                .PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0;
+        boolean disallowRinger = ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(policy);
+        if (mState.disallowAlarms == disallowAlarms && mState.disallowMedia == disallowMedia
+                && mState.disallowRinger == disallowRinger) {
+            return false;
+        }
+        mState.disallowAlarms = disallowAlarms;
+        mState.disallowMedia = disallowMedia;
+        mState.disallowRinger = disallowRinger;
+        Events.writeEvent(mContext, Events.EVENT_ZEN_CONFIG_CHANGED, "disallowAlarms=" +
+                disallowAlarms + " disallowMedia=" + disallowMedia + " disallowRinger=" +
+                disallowRinger);
+        return true;
+    }
+
     private boolean updateRingerModeExternalW(int rm) {
         if (rm == mState.ringerModeExternal) return false;
         mState.ringerModeExternal = rm;
@@ -850,6 +875,10 @@
             if (ZEN_MODE_URI.equals(uri)) {
                 changed = updateZenModeW();
             }
+            if (ZEN_MODE_CONFIG_URI.equals(uri)) {
+                changed |= updateZenConfig();
+            }
+
             if (changed) {
                 mCallbacks.onStateChanged(mState);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 56b7201..f8fabda 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -668,10 +668,14 @@
                 && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
         final boolean isRingSilent = isRingStream
                 && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;
+        final boolean isZenPriorityOnly = mState.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;
         final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
         final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)
                 : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream)
+                : isZenPriorityOnly ? ((isAlarmStream && mState.disallowAlarms) ||
+                        (isMusicStream && mState.disallowMedia) ||
+                        (isRingStream && mState.disallowRinger))
                 : false;
 
         // update slider max
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index bedf043..0b78a3b 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -16,11 +16,6 @@
 
 package com.android.server.audio;
 
-import com.android.server.audio.AudioServiceEvents.ForceUseEvent;
-import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
-import com.android.server.audio.AudioServiceEvents.VolumeEvent;
-import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;
-
 import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
 import static android.media.AudioManager.RINGER_MODE_NORMAL;
 import static android.media.AudioManager.RINGER_MODE_SILENT;
@@ -64,14 +59,14 @@
 import android.media.AudioDevicePort;
 import android.media.AudioFocusInfo;
 import android.media.AudioFocusRequest;
-import android.media.AudioSystem;
 import android.media.AudioFormat;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
-import android.media.AudioPort;
 import android.media.AudioPlaybackConfiguration;
+import android.media.AudioPort;
 import android.media.AudioRecordingConfiguration;
 import android.media.AudioRoutesInfo;
+import android.media.AudioSystem;
 import android.media.IAudioFocusDispatcher;
 import android.media.IAudioRoutesObserver;
 import android.media.IAudioService;
@@ -80,12 +75,12 @@
 import android.media.IRingtonePlayer;
 import android.media.IVolumeController;
 import android.media.MediaPlayer;
-import android.media.SoundPool;
-import android.media.VolumePolicy;
-import android.media.audiofx.AudioEffect;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.media.PlayerBase;
+import android.media.SoundPool;
+import android.media.VolumePolicy;
+import android.media.audiofx.AudioEffect;
 import android.media.audiopolicy.AudioMix;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicyConfig;
@@ -110,6 +105,7 @@
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.provider.Settings.System;
+import android.service.notification.ZenModeConfig;
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.util.AndroidRuntimeException;
@@ -129,6 +125,10 @@
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.audio.AudioServiceEvents.ForceUseEvent;
+import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
+import com.android.server.audio.AudioServiceEvents.VolumeEvent;
+import com.android.server.audio.AudioServiceEvents.WiredDevConnectEvent;
 import com.android.server.pm.UserManagerService;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -1852,10 +1852,12 @@
         sendVolumeUpdate(streamType, oldIndex, index, flags);
     }
 
-    // No ringer affected streams can be changed in total silence mode except those that
-    // will cause the device to exit total silence mode.
+    // No ringer affected streams can be changed in total silence mode or priority-only
+    // (with alarms/media toggled off) except those that will cause the device to exit
+    // the mode.
     private boolean volumeAdjustmentAllowedByDnd(int streamTypeAlias, int flags) {
-        if (mNm.getZenMode() == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
+        if ((mNm.getZenMode() == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS
+                || mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS)
                 && isStreamMutedByRingerMode(streamTypeAlias)) {
             if (!(((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) ||
                     (streamTypeAlias == getUiSoundsStreamType()))) {
@@ -2380,11 +2382,30 @@
         // Unmute stream if previously muted by ringer mode and ringer mode
         // is RINGER_MODE_NORMAL or stream is not affected by ringer mode.
         int numStreamTypes = AudioSystem.getNumStreamTypes();
+
+        if (mNm == null) {
+            mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        }
+
+        // in priority only dnd, alarms and media streams can be muted when ringer is not muted
+        boolean isZenPriorityMode = mNm.getZenMode() ==
+                Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
+        boolean muteAlarms = isZenPriorityMode && ((zenPolicy.priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0);
+        boolean muteMedia = isZenPriorityMode && ((zenPolicy.priorityCategories
+                & NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA_SYSTEM_OTHER) == 0);
+
         final boolean ringerModeMute = mRingerMode == AudioManager.RINGER_MODE_VIBRATE
                 || mRingerMode == AudioManager.RINGER_MODE_SILENT;
+
         for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
             final boolean isMuted = isStreamMutedByRingerMode(streamType);
-            final boolean shouldMute = ringerModeMute && isStreamAffectedByRingerMode(streamType);
+
+            final boolean shouldZenMute = (isAlarm(streamType) && muteAlarms)
+                    || (isMedia(streamType) && muteMedia);
+            final boolean shouldMute = (shouldZenMute || ringerModeMute)
+                    && isStreamAffectedByRingerMode(streamType);
             if (isMuted == shouldMute) continue;
             if (!shouldMute) {
                 // unmute
@@ -2420,6 +2441,19 @@
         }
     }
 
+    private boolean isAlarm(int streamType) {
+        return streamType == AudioSystem.STREAM_ALARM;
+    }
+
+    private boolean isNotificationOrRinger(int streamType) {
+        return streamType == AudioSystem.STREAM_NOTIFICATION
+                || streamType == AudioSystem.STREAM_RING;
+    }
+
+    private boolean isMedia(int streamType) {
+        return streamType == AudioSystem.STREAM_SYSTEM || streamType == AudioSystem.STREAM_MUSIC;
+    }
+
     private void setRingerModeInt(int ringerMode, boolean persist) {
         final boolean change;
         synchronized(mSettingsLock) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 932e4f9..dce6bfb 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -129,7 +129,6 @@
         mFiltering = new ZenModeFiltering(mContext);
         mConditions = new ZenModeConditions(this, conditionProviders);
         mServiceConfig = conditionProviders.getConfig();
-
     }
 
     public Looper getLooper() {
@@ -823,7 +822,7 @@
     @VisibleForTesting
     protected void applyRestrictions() {
         final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        final boolean zenSilence  = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
+        final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
         final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
 
         // notification restrictions
@@ -839,7 +838,7 @@
         final boolean muteMediaAndSystemSounds = zenPriorityOnly && !mConfig.allowMediaSystemOther;
         // total silence restrictions
         final boolean muteEverything = zenSilence
-                || (zenPriorityOnly && areAllBehaviorSoundsMuted());
+                || (zenPriorityOnly && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConfig));
 
         for (int usage : AudioAttributes.SDK_USAGES) {
             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
@@ -872,12 +871,6 @@
                 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
@@ -892,6 +885,18 @@
                 }
                 break;
             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
+                if (ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
+                    if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
+                        setPreviousRingerModeSetting(ringerModeInternal);
+                        newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
+                    }
+                } else {
+                    if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
+                        newRingerModeInternal = getPreviousRingerModeSetting();
+                        setPreviousRingerModeSetting(null);
+                    }
+                }
+                break;
             case Global.ZEN_MODE_OFF:
                 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
                     newRingerModeInternal = getPreviousRingerModeSetting();
@@ -1000,8 +1005,7 @@
             switch (ringerModeNew) {
                 case AudioManager.RINGER_MODE_SILENT:
                     if (isChange && policy.doNotDisturbWhenSilent) {
-                        if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS
-                                && mZenMode != Global.ZEN_MODE_ALARMS) {
+                        if (mZenMode == Global.ZEN_MODE_OFF) {
                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
                         }
                         setPreviousRingerModeSetting(ringerModeOld);
@@ -1011,7 +1015,10 @@
                 case AudioManager.RINGER_MODE_NORMAL:
                     if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
                             && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
-                                    || mZenMode == Global.ZEN_MODE_ALARMS)) {
+                            || mZenMode == Global.ZEN_MODE_ALARMS
+                            || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                            && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
+                                    mConfig)))) {
                         newZen = Global.ZEN_MODE_OFF;
                     } else if (mZenMode != Global.ZEN_MODE_OFF) {
                         ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
@@ -1079,10 +1086,24 @@
                        (1 << AudioSystem.STREAM_NOTIFICATION) |
                        (1 << AudioSystem.STREAM_SYSTEM);
 
-            // alarm and music streams are only affected by ringer mode when in total silence
             if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
+                // alarm and music streams affected by ringer mode when in total silence
                 streams |= (1 << AudioSystem.STREAM_ALARM) |
                            (1 << AudioSystem.STREAM_MUSIC);
+            } else if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
+                // alarm and music streams affected by ringer mode when in priority only with
+                // media and alarms not allowed to bypass dnd
+                if (!mConfig.allowMediaSystemOther) {
+                    streams |= (1 << AudioSystem.STREAM_MUSIC);
+                } else {
+                    streams &= ~(1 << AudioSystem.STREAM_MUSIC);
+                }
+
+                if (!mConfig.allowAlarms) {
+                    streams |= (1 << AudioSystem.STREAM_ALARM);
+                } else {
+                    streams &= ~(1 << AudioSystem.STREAM_ALARM);
+                }
             } else {
                 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
                              (1 << AudioSystem.STREAM_MUSIC));