Use consolidated zen policy for dnd

Instead of using the default notification policy,
use the consolidated zen policy when do not disturb
is in priority only dnd mode

Bug: 111474881
Test: atest ZenModeHelperTest ZenPolicyTest ZenModeFilteringTest AudioManagerTest
Test: atest SystemUITests ZenModeExtractorTest
Change-Id: I88934103a56f06d4a4f620a8f557347331a79627
diff --git a/core/java/android/app/AutomaticZenRule.java b/core/java/android/app/AutomaticZenRule.java
index 62f6bac..9d68133 100644
--- a/core/java/android/app/AutomaticZenRule.java
+++ b/core/java/android/app/AutomaticZenRule.java
@@ -151,7 +151,7 @@
      * Gets the zen policy.
      */
     public ZenPolicy getZenPolicy() {
-        return this.mZenPolicy.copy();
+        return mZenPolicy == null ? null : this.mZenPolicy.copy();
     }
 
     /**
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 357420b..bd9cf6d 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -146,6 +146,7 @@
 
     int getZenMode();
     ZenModeConfig getZenModeConfig();
+    NotificationManager.Policy getConsolidatedNotificationPolicy();
     oneway void setZenMode(int mode, in Uri conditionId, String reason);
     oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
     boolean isNotificationPolicyAccessGranted(String pkg);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 3f07024..89ec19b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -825,6 +825,18 @@
     /**
      * @hide
      */
+    public NotificationManager.Policy getConsolidatedNotificationPolicy() {
+        INotificationManager service = getService();
+        try {
+            return service.getConsolidatedNotificationPolicy();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * @hide
+     */
     public int getRuleInstanceCount(ComponentName owner) {
         INotificationManager service = getService();
         try {
@@ -1062,7 +1074,7 @@
     }
 
     /**
-     * Gets the current notification policy.
+     * Gets the current user-specified default notification policy.
      *
      * <p>
      */
@@ -1621,6 +1633,71 @@
                 return new Policy[size];
             }
         };
+
+        /** @hide **/
+        public boolean allowAlarms() {
+            return (priorityCategories & PRIORITY_CATEGORY_ALARMS) != 0;
+        }
+
+        /** @hide **/
+        public boolean allowMedia() {
+            return (priorityCategories & PRIORITY_CATEGORY_MEDIA) != 0;
+        }
+
+        /** @hide **/
+        public boolean allowSystem() {
+            return (priorityCategories & PRIORITY_CATEGORY_SYSTEM) != 0;
+        }
+
+        /** @hide **/
+        public boolean allowRepeatCallers() {
+            return (priorityCategories & PRIORITY_CATEGORY_REPEAT_CALLERS) != 0;
+        }
+
+        /** @hide **/
+        public boolean allowCalls() {
+            return (priorityCategories & PRIORITY_CATEGORY_CALLS) != 0;
+        }
+
+        /** @hide **/
+        public boolean allowMessages() {
+            return (priorityCategories & PRIORITY_CATEGORY_MESSAGES) != 0;
+        }
+
+        /** @hide **/
+        public boolean allowEvents() {
+            return (priorityCategories & PRIORITY_CATEGORY_EVENTS) != 0;
+        }
+
+        /** @hide **/
+        public boolean allowReminders() {
+            return (priorityCategories & PRIORITY_CATEGORY_REMINDERS) != 0;
+        }
+
+        /** @hide **/
+        public int allowCallsFrom() {
+            return priorityCallSenders;
+        }
+
+        /** @hide **/
+        public int allowMessagesFrom() {
+            return priorityMessageSenders;
+        }
+
+        /**
+         * returns a deep copy of this policy
+         * @hide
+         */
+        public Policy copy() {
+            final Parcel parcel = Parcel.obtain();
+            try {
+                writeToParcel(parcel, 0);
+                parcel.setDataPosition(0);
+                return new Policy(parcel);
+            } finally {
+                parcel.recycle();
+            }
+        }
     }
 
     /**
@@ -1708,5 +1785,4 @@
             default: return defValue;
         }
     }
-
 }
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 37a9b10..8371c31b 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -69,9 +69,9 @@
 public class ZenModeConfig implements Parcelable {
     private static String TAG = "ZenModeConfig";
 
-    public static final int SOURCE_ANYONE = 0;
-    public static final int SOURCE_CONTACT = 1;
-    public static final int SOURCE_STAR = 2;
+    public static final int SOURCE_ANYONE = Policy.PRIORITY_SENDERS_ANY;
+    public static final int SOURCE_CONTACT = Policy.PRIORITY_SENDERS_CONTACTS;
+    public static final int SOURCE_STAR = Policy.PRIORITY_SENDERS_STARRED;
     public static final int MAX_SOURCE = SOURCE_STAR;
     private static final int DEFAULT_SOURCE = SOURCE_CONTACT;
     private static final int DEFAULT_CALLS_SOURCE = SOURCE_STAR;
@@ -777,24 +777,6 @@
     };
 
     /**
-     * @return notification policy based on manual and automatic rules
-     */
-    public Policy getConsolidatedNotificationPolicy() {
-        ZenPolicy policy = new ZenPolicy();
-
-        // assumption: manual rule always uses the default policy
-        for (ZenRule rule : automaticRules.values()) {
-            if (rule.isAutomaticActive()) {
-                if (rule.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
-                    policy.apply(rule.zenPolicy);
-                }
-            }
-        }
-
-        return toNotificationPolicy(policy);
-    }
-
-    /**
      * Converts a zenPolicy to a notificationPolicy using this ZenModeConfig's values as its
      * defaults for all unset values in zenPolicy
      */
@@ -891,7 +873,7 @@
         }
 
         return new NotificationManager.Policy(priorityCategories, callSenders,
-                messageSenders, suppressedVisualEffects);
+                messageSenders, suppressedVisualEffects, defaultPolicy.state);
     }
 
     private boolean isPriorityCategoryEnabled(int categoryType, Policy policy) {
@@ -945,6 +927,7 @@
         }
         priorityCallSenders = sourceToPrioritySenders(allowCallsFrom, priorityCallSenders);
         priorityMessageSenders = sourceToPrioritySenders(allowMessagesFrom, priorityMessageSenders);
+
         return new Policy(priorityCategories, priorityCallSenders, priorityMessageSenders,
                 suppressedVisualEffects, areChannelsBypassingDnd
                 ? Policy.STATE_CHANNELS_BYPASSING_DND : 0);
@@ -1732,13 +1715,25 @@
     }
 
     /**
+     * Determines whether dnd behavior should mute all sounds controlled by ringer
+     */
+    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);
+    }
+
+    /**
      * Determines if DND is currently overriding the ringer
      */
-    public static boolean isZenOverridingRinger(int zen, ZenModeConfig zenConfig) {
+    public static boolean isZenOverridingRinger(int zen, Policy consolidatedPolicy) {
         return zen == Global.ZEN_MODE_NO_INTERRUPTIONS
                 || zen == Global.ZEN_MODE_ALARMS
                 || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
-                && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(zenConfig));
+                && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(consolidatedPolicy));
     }
 
     /**
diff --git a/core/java/android/service/notification/ZenPolicy.java b/core/java/android/service/notification/ZenPolicy.java
index 1ccf529..43ab8dc 100644
--- a/core/java/android/service/notification/ZenPolicy.java
+++ b/core/java/android/service/notification/ZenPolicy.java
@@ -818,6 +818,10 @@
      * @hide
      */
     public void apply(ZenPolicy policyToApply) {
+        if (policyToApply == null) {
+            return;
+        }
+
         // apply priority categories
         for (int category = 0; category < mPriorityCategories.size(); category++) {
             if (mPriorityCategories.get(category) == STATE_DISALLOW) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index b988c55..326df49 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -33,19 +33,19 @@
 import android.os.Handler;
 import android.provider.AlarmClock;
 import android.service.notification.ZenModeConfig;
-import android.widget.FrameLayout;
-import androidx.annotation.VisibleForTesting;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Pair;
 import android.view.View;
 import android.view.WindowInsets;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.RelativeLayout;
 import android.widget.TextView;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.Dependency;
@@ -56,8 +56,8 @@
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
-import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.statusbar.phone.StatusIconContainer;
+import com.android.systemui.statusbar.policy.Clock;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.statusbar.policy.DateView;
@@ -205,7 +205,7 @@
 
         boolean ringerVisible = false;
         if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
-                mZenController.getConfig())) {
+                mZenController.getConsolidatedPolicy())) {
             if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
                 mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_vibrate);
                 mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 553165b..0e6efc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -57,6 +57,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.Pair;
+
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
@@ -391,7 +392,7 @@
             zenDescription = mContext.getString(R.string.interruption_level_priority);
         }
 
-        if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConfig())) {
+        if (!ZenModeConfig.isZenOverridingRinger(zen, mZenController.getConsolidatedPolicy())) {
             if (audioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE) {
                 volumeVisible = true;
                 volumeIconId = R.drawable.stat_sys_ringer_vibrate;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index 4ee8059..ad19729 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.net.Uri;
 import android.service.notification.Condition;
@@ -29,6 +30,8 @@
     int getZen();
     ZenRule getManualRule();
     ZenModeConfig getConfig();
+    /** Gets consolidated zen policy that will apply when DND is on in priority only mode */
+    NotificationManager.Policy getConsolidatedPolicy();
     long getNextAlarm();
     boolean isZenAvailable();
     ComponentName getEffectsSuppressor();
@@ -45,6 +48,8 @@
         default void onEffectsSupressorChanged() {}
         default void onManualRuleChanged(ZenRule rule) {}
         default void onConfigChanged(ZenModeConfig config) {}
+        /** Called when the consolidated zen policy changes */
+        default void onConsolidatedPolicyChanged(NotificationManager.Policy policy) {}
     }
 
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 8d2552f..89ccff0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -69,6 +69,7 @@
     private ZenModeConfig mConfig;
     private int mZenMode;
     private long mZenUpdateTime;
+    private NotificationManager.Policy mConsolidatedNotificationPolicy;
 
     public ZenModeControllerImpl(Context context, Handler handler) {
         super(context);
@@ -91,6 +92,7 @@
         updateZenMode(mModeSetting.getValue());
         mConfigSetting.setListening(true);
         updateZenModeConfig();
+        updateConsolidatedNotificationPolicy();
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mSetupObserver = new SetupObserver(handler);
         mSetupObserver.register();
@@ -153,6 +155,11 @@
     }
 
     @Override
+    public NotificationManager.Policy getConsolidatedPolicy() {
+        return mConsolidatedNotificationPolicy;
+    }
+
+    @Override
     public long getNextAlarm() {
         final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
         return info != null ? info.getTriggerTime() : 0;
@@ -217,6 +224,12 @@
         }
     }
 
+    private void fireConsolidatedPolicyChanged(NotificationManager.Policy policy) {
+        synchronized (mCallbacksLock) {
+            Utils.safeForeach(mCallbacks, c -> c.onConsolidatedPolicyChanged(policy));
+        }
+    }
+
     @VisibleForTesting
     protected void fireConfigChanged(ZenModeConfig config) {
         synchronized (mCallbacksLock) {
@@ -231,6 +244,16 @@
     }
 
     @VisibleForTesting
+    protected void updateConsolidatedNotificationPolicy() {
+        final NotificationManager.Policy policy = mNoMan.getConsolidatedNotificationPolicy();
+        if (!Objects.equals(policy, mConsolidatedNotificationPolicy)) {
+            mConsolidatedNotificationPolicy = policy;
+            fireConsolidatedPolicyChanged(policy);
+        }
+    }
+
+
+    @VisibleForTesting
     protected void updateZenModeConfig() {
         final ZenModeConfig config = mNoMan.getZenModeConfig();
         if (Objects.equals(config, mConfig)) return;
@@ -238,9 +261,19 @@
         mConfig = config;
         mZenUpdateTime = System.currentTimeMillis();
         fireConfigChanged(config);
+
         final ZenRule newRule = config != null ? config.manualRule : null;
-        if (Objects.equals(oldRule, newRule)) return;
-        fireManualRuleChanged(newRule);
+        if (!Objects.equals(oldRule, newRule)) {
+            fireManualRuleChanged(newRule);
+        }
+
+        final NotificationManager.Policy consolidatedPolicy =
+                mNoMan.getConsolidatedNotificationPolicy();
+        if (!Objects.equals(consolidatedPolicy, mConsolidatedNotificationPolicy)) {
+            mConsolidatedNotificationPolicy = consolidatedPolicy;
+            fireConsolidatedPolicyChanged(consolidatedPolicy);
+        }
+
     }
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -260,6 +293,7 @@
         pw.println("ZenModeControllerImpl:");
         pw.println("  mZenMode=" + mZenMode);
         pw.println("  mConfig=" + mConfig);
+        pw.println("  mConsolidatedNotificationPolicy=" + mConsolidatedNotificationPolicy);
         pw.println("  mZenUpdateTime=" + DateFormat.format("MM-dd HH:mm:ss", mZenUpdateTime));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
index 86c43c9..75df4e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeZenModeController.java
@@ -14,6 +14,7 @@
 
 package com.android.systemui.utils.leaks;
 
+import android.app.NotificationManager;
 import android.content.ComponentName;
 import android.net.Uri;
 import android.service.notification.ZenModeConfig;
@@ -49,6 +50,11 @@
     }
 
     @Override
+    public NotificationManager.Policy getConsolidatedPolicy() {
+        return null;
+    }
+
+    @Override
     public long getNextAlarm() {
         return 0;
     }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index f56d8e6..f3a28cc 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4293,7 +4293,7 @@
             return false;
         }
 
-        NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
+        NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
         final boolean muteAlarms = (zenPolicy.priorityCategories
                 & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0;
         final boolean muteMedia = (zenPolicy.priorityCategories
@@ -4301,7 +4301,8 @@
         final boolean muteSystem = (zenPolicy.priorityCategories
                 & NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM) == 0;
         final boolean muteNotificationAndRing = ZenModeConfig
-                .areAllPriorityOnlyNotificationZenSoundsMuted(mNm.getNotificationPolicy());
+                .areAllPriorityOnlyNotificationZenSoundsMuted(
+                        mNm.getConsolidatedNotificationPolicy());
         return muteAlarms && isAlarm(streamType)
                 || muteMedia && isMedia(streamType)
                 || muteSystem && isSystem(streamType)
@@ -4323,7 +4324,7 @@
     private boolean updateZenModeAffectedStreams() {
         int zenModeAffectedStreams = 0;
         if (mSystemReady && mNm.getZenMode() == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
-            NotificationManager.Policy zenPolicy = mNm.getNotificationPolicy();
+            NotificationManager.Policy zenPolicy = mNm.getConsolidatedNotificationPolicy();
             if ((zenPolicy.priorityCategories
                     & NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS) == 0) {
                 zenModeAffectedStreams |= 1 << AudioManager.STREAM_ALARM;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 93b83ae..924b075 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3399,6 +3399,16 @@
             }
         }
 
+        @Override
+        public Policy getConsolidatedNotificationPolicy() {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                return mZenModeHelper.getConsolidatedNotificationPolicy();
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
         /**
          * Sets the notification policy.  Apps that target API levels below
          * {@link android.os.Build.VERSION_CODES#P} cannot change user-designated values to
@@ -4660,7 +4670,6 @@
                 }
 
                 mRankingHelper.extractSignals(r);
-
                 // tell the assistant service about the notification
                 if (mAssistants.isEnabled()) {
                     mAssistants.onNotificationEnqueued(r);
@@ -5570,7 +5579,7 @@
         record.setIntercepted(mZenModeHelper.shouldIntercept(record));
         if (record.isIntercepted()) {
             record.setSuppressedVisualEffects(
-                    mZenModeHelper.getNotificationPolicy().suppressedVisualEffects);
+                    mZenModeHelper.getConsolidatedNotificationPolicy().suppressedVisualEffects);
         } else {
             record.setSuppressedVisualEffects(0);
         }
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index b016faf..c6af756 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -63,6 +63,7 @@
     private static final int TYPE_SUPPRESSOR_CHANGED = 14;
     private static final int TYPE_LISTENER_HINTS_CHANGED = 15;
     private static final int TYPE_SET_NOTIFICATION_POLICY = 16;
+    private static final int TYPE_SET_CONSOLIDATED_ZEN_POLICY = 17;
 
     private static int sNext;
     private static int sSize;
@@ -103,6 +104,14 @@
         append(TYPE_SET_ZEN_MODE, zenModeToString(zenMode) + "," + reason);
     }
 
+    /**
+     * trace setting the consolidated zen policy
+     */
+    public static void traceSetConsolidatedZenPolicy(NotificationManager.Policy policy,
+            String reason) {
+        append(TYPE_SET_CONSOLIDATED_ZEN_POLICY, policy.toString() + "," + reason);
+    }
+
     public static void traceUpdateZenMode(int fromMode, int toMode) {
         append(TYPE_UPDATE_ZEN_MODE, zenModeToString(fromMode) + " -> " + zenModeToString(toMode));
     }
diff --git a/services/core/java/com/android/server/notification/ZenModeExtractor.java b/services/core/java/com/android/server/notification/ZenModeExtractor.java
index a0aa1c3..f3da079 100644
--- a/services/core/java/com/android/server/notification/ZenModeExtractor.java
+++ b/services/core/java/com/android/server/notification/ZenModeExtractor.java
@@ -16,9 +16,6 @@
 
 package com.android.server.notification;
 
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
-import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
-
 import android.content.Context;
 import android.util.Log;
 import android.util.Slog;
@@ -50,7 +47,7 @@
         record.setIntercepted(mZenModeHelper.shouldIntercept(record));
         if (record.isIntercepted()) {
             record.setSuppressedVisualEffects(
-                    mZenModeHelper.getNotificationPolicy().suppressedVisualEffects);
+                    mZenModeHelper.getConsolidatedNotificationPolicy().suppressedVisualEffects);
         } else {
             record.setSuppressedVisualEffects(0);
         }
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index 28cee7a..6045f6c 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -23,11 +23,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.media.AudioAttributes;
-import android.media.AudioManager;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
-import android.provider.Settings.Secure;
 import android.service.notification.ZenModeConfig;
 import android.telecom.TelecomManager;
 import android.util.ArrayMap;
@@ -38,7 +36,6 @@
 
 import java.io.PrintWriter;
 import java.util.Date;
-import java.util.Objects;
 
 public class ZenModeFiltering {
     private static final String TAG = ZenModeHelper.TAG;
@@ -88,20 +85,21 @@
      * @param timeoutAffinity affinity to return when the timeout specified via
      *                        <code>contactsTimeoutMs</code> is hit
      */
-    public static boolean matchesCallFilter(Context context, int zen, ZenModeConfig config,
-            UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator,
-            int contactsTimeoutMs, float timeoutAffinity) {
+    public static boolean matchesCallFilter(Context context, int zen, NotificationManager.Policy
+            consolidatedPolicy, UserHandle userHandle, Bundle extras,
+            ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
         if (zen == Global.ZEN_MODE_NO_INTERRUPTIONS) return false; // nothing gets through
         if (zen == Global.ZEN_MODE_ALARMS) return false; // not an alarm
         if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) {
-            if (config.allowRepeatCallers && REPEAT_CALLERS.isRepeat(context, extras)) {
+            if (consolidatedPolicy.allowRepeatCallers()
+                    && REPEAT_CALLERS.isRepeat(context, extras)) {
                 return true;
             }
-            if (!config.allowCalls) return false; // no other calls get through
+            if (!consolidatedPolicy.allowCalls()) return false; // no other calls get through
             if (validator != null) {
                 final float contactAffinity = validator.getContactAffinity(userHandle, extras,
                         contactsTimeoutMs, timeoutAffinity);
-                return audienceMatches(config.allowCallsFrom, contactAffinity);
+                return audienceMatches(consolidatedPolicy.allowCallsFrom(), contactAffinity);
             }
         }
         return true;
@@ -116,13 +114,17 @@
         REPEAT_CALLERS.recordCall(mContext, extras(record));
     }
 
-    public boolean shouldIntercept(int zen, ZenModeConfig config, NotificationRecord record) {
+    /**
+     * Whether to intercept the notification based on the policy
+     */
+    public boolean shouldIntercept(int zen, NotificationManager.Policy policy,
+            NotificationRecord record) {
         // Zen mode is ignored for critical notifications.
         if (zen == ZEN_MODE_OFF || isCritical(record)) {
             return false;
         }
         // Make an exception to policy for the notification saying that policy has changed
-        if (NotificationManager.Policy.areAllVisualEffectsSuppressed(config.suppressedVisualEffects)
+        if (NotificationManager.Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects)
                 && "android".equals(record.sbn.getPackageName())
                 && SystemMessageProto.SystemMessage.NOTE_ZEN_UPGRADE == record.sbn.getId()) {
             ZenLog.traceNotIntercepted(record, "systemDndChangedNotification");
@@ -148,54 +150,54 @@
                 }
 
                 if (isAlarm(record)) {
-                    if (!config.allowAlarms) {
+                    if (!policy.allowAlarms()) {
                         ZenLog.traceIntercepted(record, "!allowAlarms");
                         return true;
                     }
                     return false;
                 }
                 if (isCall(record)) {
-                    if (config.allowRepeatCallers
+                    if (policy.allowRepeatCallers()
                             && REPEAT_CALLERS.isRepeat(mContext, extras(record))) {
                         ZenLog.traceNotIntercepted(record, "repeatCaller");
                         return false;
                     }
-                    if (!config.allowCalls) {
+                    if (!policy.allowCalls()) {
                         ZenLog.traceIntercepted(record, "!allowCalls");
                         return true;
                     }
-                    return shouldInterceptAudience(config.allowCallsFrom, record);
+                    return shouldInterceptAudience(policy.allowCallsFrom(), record);
                 }
                 if (isMessage(record)) {
-                    if (!config.allowMessages) {
+                    if (!policy.allowMessages()) {
                         ZenLog.traceIntercepted(record, "!allowMessages");
                         return true;
                     }
-                    return shouldInterceptAudience(config.allowMessagesFrom, record);
+                    return shouldInterceptAudience(policy.allowMessagesFrom(), record);
                 }
                 if (isEvent(record)) {
-                    if (!config.allowEvents) {
+                    if (!policy.allowEvents()) {
                         ZenLog.traceIntercepted(record, "!allowEvents");
                         return true;
                     }
                     return false;
                 }
                 if (isReminder(record)) {
-                    if (!config.allowReminders) {
+                    if (!policy.allowReminders()) {
                         ZenLog.traceIntercepted(record, "!allowReminders");
                         return true;
                     }
                     return false;
                 }
                 if (isMedia(record)) {
-                    if (!config.allowMedia) {
+                    if (!policy.allowMedia()) {
                         ZenLog.traceIntercepted(record, "!allowMedia");
                         return true;
                     }
                     return false;
                 }
                 if (isSystem(record)) {
-                    if (!config.allowSystem) {
+                    if (!policy.allowSystem()) {
                         ZenLog.traceIntercepted(record, "!allowSystem");
                         return true;
                     }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 44b80c1..fc9bd37 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -54,6 +54,7 @@
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ZenRule;
 import android.service.notification.ZenModeProto;
+import android.service.notification.ZenPolicy;
 import android.util.AndroidRuntimeException;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -106,6 +107,7 @@
     private final ConditionProviders.Config mServiceConfig;
 
     @VisibleForTesting protected int mZenMode;
+    @VisibleForTesting protected NotificationManager.Policy mConsolidatedPolicy;
     private int mUser = UserHandle.USER_SYSTEM;
     @VisibleForTesting protected ZenModeConfig mConfig;
     @VisibleForTesting protected AudioManagerInternal mAudioManager;
@@ -150,8 +152,8 @@
     public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
             ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
         synchronized (mConfig) {
-            return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle,
-                    extras, validator, contactsTimeoutMs, timeoutAffinity);
+            return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy,
+                    userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity);
         }
     }
 
@@ -165,7 +167,7 @@
 
     public boolean shouldIntercept(NotificationRecord record) {
         synchronized (mConfig) {
-            return mFiltering.shouldIntercept(mZenMode, mConfig, record);
+            return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record);
         }
     }
 
@@ -479,6 +481,9 @@
         rule.condition = null;
         rule.conditionId = automaticZenRule.getConditionId();
         rule.enabled = automaticZenRule.isEnabled();
+        if (automaticZenRule.getZenPolicy() != null) {
+            rule.zenPolicy = automaticZenRule.getZenPolicy();
+        }
         rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
                 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
     }
@@ -549,6 +554,7 @@
     public void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("mZenMode=");
         pw.println(Global.zenModeToString(mZenMode));
+        pw.print("mConsolidatedPolicy=" + mConsolidatedPolicy.toString());
         final int N = mConfigs.size();
         for (int i = 0; i < N; i++) {
             dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
@@ -713,6 +719,16 @@
         }
     }
 
+    /**
+     * @return a copy of the zen mode consolidated policy
+     */
+    public Policy getConsolidatedNotificationPolicy() {
+        if (mConsolidatedPolicy == null) {
+            return null;
+        }
+        return mConsolidatedPolicy.copy();
+    }
+
     public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
             String reason) {
         return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);
@@ -747,6 +763,7 @@
                     getNotificationPolicy(config));
             if (!config.equals(mConfig)) {
                 dispatchOnConfigChanged();
+                updateConsolidatedPolicy(reason);
             }
             if (policyChanged) {
                 dispatchOnPolicyChanged();
@@ -794,13 +811,18 @@
     @VisibleForTesting
     protected void evaluateZenMode(String reason, boolean setRingerMode) {
         if (DEBUG) Log.d(TAG, "evaluateZenMode");
+        if (mConfig == null) return;
+        final int policyHashBefore = mConsolidatedPolicy == null ? 0
+                : mConsolidatedPolicy.hashCode();
         final int zenBefore = mZenMode;
         final int zen = computeZenMode();
         ZenLog.traceSetZenMode(zen, reason);
         mZenMode = zen;
         setZenModeSetting(mZenMode);
+        updateConsolidatedPolicy(reason);
         updateRingerModeAffectedStreams();
-        if (setRingerMode && zen != zenBefore) {
+        if (setRingerMode && (zen != zenBefore || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                && policyHashBefore != mConsolidatedPolicy.hashCode()))) {
             applyZenToRingerMode();
         }
         applyRestrictions();
@@ -815,9 +837,7 @@
         }
     }
 
-
     private int computeZenMode() {
-        // TODO: use mConfig.zenPolicy
         if (mConfig == null) return Global.ZEN_MODE_OFF;
         synchronized (mConfig) {
             if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
@@ -839,6 +859,24 @@
         }
     }
 
+    private void updateConsolidatedPolicy(String reason) {
+        if (mConfig == null) return;
+        synchronized (mConfig) {
+            ZenPolicy policy = new ZenPolicy();
+            for (ZenRule automaticRule : mConfig.automaticRules.values()) {
+                if (automaticRule.isAutomaticActive()) {
+                    policy.apply(automaticRule.zenPolicy);
+                }
+            }
+            Policy newPolicy = mConfig.toNotificationPolicy(policy);
+            if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
+                mConsolidatedPolicy = newPolicy;
+                dispatchOnConsolidatedPolicyChanged();
+                ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason);
+            }
+        }
+    }
+
     private void updateDefaultAutomaticRuleNames() {
         for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
             if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) {
@@ -856,23 +894,28 @@
         final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
         final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
+        final boolean allowCalls = mConsolidatedPolicy.allowCalls();
+        final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
+        final boolean allowSystem = mConsolidatedPolicy.allowSystem();
+        final boolean allowMedia = mConsolidatedPolicy.allowMedia();
+        final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
 
         // notification restrictions
         final boolean muteNotifications =
                 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
         // call restrictions
         final boolean muteCalls = zenAlarmsOnly
-                || (zenPriorityOnly && !mConfig.allowCalls && !mConfig.allowRepeatCallers)
+                || (zenPriorityOnly && !allowCalls && !allowRepeatCallers)
                 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
         // alarm restrictions
-        final boolean muteAlarms = zenPriorityOnly && !mConfig.allowAlarms;
+        final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
         // media restrictions
-        final boolean muteMedia = zenPriorityOnly && !mConfig.allowMedia;
+        final boolean muteMedia = zenPriorityOnly && !allowMedia;
         // system restrictions
-        final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !mConfig.allowSystem);
+        final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
         // total silence restrictions
-        final boolean muteEverything = zenSilence
-                || (zenPriorityOnly && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConfig));
+        final boolean muteEverything = zenSilence || (zenPriorityOnly
+                && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
 
         for (int usage : AudioAttributes.SDK_USAGES) {
             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
@@ -968,6 +1011,12 @@
         }
     }
 
+    private void dispatchOnConsolidatedPolicyChanged() {
+        for (Callback callback : mCallbacks) {
+            callback.onConsolidatedPolicyChanged();
+        }
+    }
+
     private void dispatchOnZenModeChanged() {
         for (Callback callback : mCallbacks) {
             callback.onZenModeChanged();
@@ -1188,7 +1237,7 @@
         int content = R.string.zen_upgrade_notification_content;
         int drawable = R.drawable.ic_zen_24dp;
         if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
-                getNotificationPolicy().suppressedVisualEffects)) {
+                getConsolidatedNotificationPolicy().suppressedVisualEffects)) {
             title = R.string.zen_upgrade_notification_visd_title;
             content = R.string.zen_upgrade_notification_visd_content;
             drawable = R.drawable.ic_dnd_block_notifications;
@@ -1362,6 +1411,6 @@
         void onConfigChanged() {}
         void onZenModeChanged() {}
         void onPolicyChanged() {}
+        void onConsolidatedPolicyChanged() {}
     }
-
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java
index beff0d1..95bfa44 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeExtractorTest.java
@@ -59,7 +59,7 @@
         assertFalse(r.isIntercepted());
 
         when(mZenModeHelper.shouldIntercept(any())).thenReturn(true);
-        when(mZenModeHelper.getNotificationPolicy()).thenReturn(
+        when(mZenModeHelper.getConsolidatedNotificationPolicy()).thenReturn(
                 new NotificationManager.Policy(0,0,0));
 
         extractor.process(r);
@@ -74,7 +74,7 @@
         NotificationRecord r = generateRecord();
 
         when(mZenModeHelper.shouldIntercept(any())).thenReturn(false);
-        when(mZenModeHelper.getNotificationPolicy()).thenReturn(
+        when(mZenModeHelper.getConsolidatedNotificationPolicy()).thenReturn(
                 new NotificationManager.Policy(0,0,0));
 
         extractor.process(r);
@@ -89,7 +89,7 @@
         NotificationRecord r = generateRecord();
 
         when(mZenModeHelper.shouldIntercept(any())).thenReturn(true);
-        when(mZenModeHelper.getNotificationPolicy()).thenReturn(
+        when(mZenModeHelper.getConsolidatedNotificationPolicy()).thenReturn(
                 new NotificationManager.Policy(0,0,0, SUPPRESSED_EFFECT_PEEK
                         | SUPPRESSED_EFFECT_NOTIFICATION_LIST));
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index d335450..6c125d1 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -32,6 +32,7 @@
 import android.app.Notification;
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
+import android.app.NotificationManager.Policy;
 import android.media.AudioAttributes;
 import android.service.notification.StatusBarNotification;
 import android.service.notification.ZenModeConfig;
@@ -121,11 +122,10 @@
         NotificationRecord r = getNotificationRecord();
         when(r.sbn.getPackageName()).thenReturn("android");
         when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
-        ZenModeConfig config = mock(ZenModeConfig.class);
-        config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects()
-                - SUPPRESSED_EFFECT_STATUS_BAR;
+        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects()
+                - SUPPRESSED_EFFECT_STATUS_BAR);
 
-        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
+        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
     }
 
     @Test
@@ -133,10 +133,9 @@
         NotificationRecord r = getNotificationRecord();
         when(r.sbn.getPackageName()).thenReturn("android");
         when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ACCOUNT_CREDENTIAL_PERMISSION);
-        ZenModeConfig config = mock(ZenModeConfig.class);
-        config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
+        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects());
 
-        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
+        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
     }
 
     @Test
@@ -144,10 +143,9 @@
         NotificationRecord r = getNotificationRecord();
         when(r.sbn.getPackageName()).thenReturn("android2");
         when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
-        ZenModeConfig config = mock(ZenModeConfig.class);
-        config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
+        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects());
 
-        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
+        assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
     }
 
     @Test
@@ -155,21 +153,20 @@
         NotificationRecord r = getNotificationRecord();
         when(r.sbn.getPackageName()).thenReturn("android");
         when(r.sbn.getId()).thenReturn(SystemMessage.NOTE_ZEN_UPGRADE);
-        ZenModeConfig config = mock(ZenModeConfig.class);
-        config.suppressedVisualEffects = NotificationManager.Policy.getAllSuppressedVisualEffects();
+        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects());
 
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config, r));
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_ALARMS, config, r));
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, config, r));
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_ALARMS, policy, r));
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
     }
 
     @Test
     public void testSuppressAnything_yes_ZenModeOff() {
         NotificationRecord r = getNotificationRecord();
         when(r.sbn.getPackageName()).thenReturn("bananas");
-        ZenModeConfig config = mock(ZenModeConfig.class);
+        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects());
 
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_OFF, config, r));
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_OFF, policy, r));
     }
 
     @Test
@@ -177,11 +174,11 @@
         NotificationRecord r = getNotificationRecord();
         r.setCriticality(CriticalNotificationExtractor.CRITICAL);
         when(r.sbn.getPackageName()).thenReturn("bananas");
-        ZenModeConfig config = mock(ZenModeConfig.class);
+        Policy policy = new Policy(0, 0, 0, Policy.getAllSuppressedVisualEffects());
 
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, config, r));
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
 
         r.setCriticality(CriticalNotificationExtractor.CRITICAL_LOW);
-        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, config, r));
+        assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_NO_INTERRUPTIONS, policy, r));
     }
 }
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 13f3e5e..b19cc86 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -41,6 +41,7 @@
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
+import android.app.NotificationManager.Policy;
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -165,7 +166,8 @@
     @Test
     public void testZenOff_NoMuteApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_OFF;
-        assertTrue(mZenModeHelperSpy.mConfig.allowAlarms);
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
+                Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyInt());
@@ -178,8 +180,9 @@
     @Test
     public void testZenOn_AllowAlarmsMedia_NoAlarmMediaMuteApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        assertTrue(mZenModeHelperSpy.mConfig.allowAlarms);
-        assertTrue(mZenModeHelperSpy.mConfig.allowMedia);
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
+                Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0);
+
         mZenModeHelperSpy.applyRestrictions();
         verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
                 AudioAttributes.USAGE_ALARM);
@@ -190,12 +193,7 @@
     @Test
     public void testZenOn_DisallowAlarmsMedia_AlarmMediaMuteApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelperSpy.mConfig.allowAlarms = false;
-        mZenModeHelperSpy.mConfig.allowMedia = false;
-        mZenModeHelperSpy.mConfig.allowSystem = false;
-        assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
-        assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
-        assertFalse(mZenModeHelperSpy.mConfig.allowSystem);
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
         verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true,
                 AudioAttributes.USAGE_ALARM);
@@ -210,6 +208,8 @@
     @Test
     public void testTotalSilence() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
+                Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         // Total silence will silence alarms, media and system noises (but not vibrations)
@@ -230,11 +230,7 @@
     @Test
     public void testAlarmsOnly_alarmMediaMuteNotApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
-        mZenModeHelperSpy.mConfig.allowAlarms = false;
-        mZenModeHelperSpy.mConfig.allowSystem = false;
-        mZenModeHelperSpy.mConfig.allowMedia = false;
-        assertFalse(mZenModeHelperSpy.mConfig.allowAlarms);
-        assertFalse(mZenModeHelperSpy.mConfig.allowMedia);
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         // Alarms only mode will not silence alarms
@@ -257,8 +253,7 @@
     @Test
     public void testAlarmsOnly_callsMuteApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
-        mZenModeHelperSpy.mConfig.allowCalls = true;
-        assertTrue(mZenModeHelperSpy.mConfig.allowCalls);
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         // Alarms only mode will silence calls despite priority-mode config
@@ -272,21 +267,7 @@
     public void testAlarmsOnly_allZenConfigToggledCannotBypass_alarmMuteNotApplied() {
         // Only audio attributes with SUPPRESIBLE_NEVER can bypass
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_ALARMS;
-        mZenModeHelperSpy.mConfig.allowAlarms = false;
-        mZenModeHelperSpy.mConfig.allowMedia = false;
-        mZenModeHelperSpy.mConfig.allowSystem = 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.allowMedia);
-        assertFalse(mZenModeHelperSpy.mConfig.allowReminders);
-        assertFalse(mZenModeHelperSpy.mConfig.allowCalls);
-        assertFalse(mZenModeHelperSpy.mConfig.allowMessages);
-        assertFalse(mZenModeHelperSpy.mConfig.allowEvents);
-        assertFalse(mZenModeHelperSpy.mConfig.allowRepeatCallers);
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(false,
@@ -298,21 +279,7 @@
         // Only audio attributes with SUPPRESIBLE_NEVER can bypass
         // with special case USAGE_ASSISTANCE_SONIFICATION
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelperSpy.mConfig.allowAlarms = false;
-        mZenModeHelperSpy.mConfig.allowMedia = false;
-        mZenModeHelperSpy.mConfig.allowSystem = 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.allowMedia);
-        assertFalse(mZenModeHelperSpy.mConfig.allowReminders);
-        assertFalse(mZenModeHelperSpy.mConfig.allowCalls);
-        assertFalse(mZenModeHelperSpy.mConfig.allowMessages);
-        assertFalse(mZenModeHelperSpy.mConfig.allowEvents);
-        assertFalse(mZenModeHelperSpy.mConfig.allowRepeatCallers);
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         for (int usage : AudioAttributes.SDK_USAGES) {
@@ -338,6 +305,7 @@
         Settings.Secure.putInt(mContentResolver, Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
         Settings.Secure.putInt(mContentResolver, Settings.Secure.ZEN_SETTINGS_UPDATED, 0);
         mZenModeHelperSpy.mIsBootComplete = true;
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(0, 0, 0, 0, 0);
         mZenModeHelperSpy.setZenModeSetting(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
 
         verify(mZenModeHelperSpy, times(1)).createZenUpgradeNotification();
@@ -548,6 +516,7 @@
     @Test
     public void testSilentRingerSavedInZenOff_startsZenOff() {
         AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
+        mZenModeHelperSpy.mConfig = new ZenModeConfig();
         mZenModeHelperSpy.mAudioManager = mAudioManager;
 
         // apply zen off multiple times - verify ringer is not set to normal
@@ -568,6 +537,7 @@
         AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
         mZenModeHelperSpy.mAudioManager = mAudioManager;
         mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
+        mZenModeHelperSpy.mConfig = new ZenModeConfig();
 
         // previously set silent ringer
         ZenModeHelper.RingerModeDelegate ringerModeDelegate =
@@ -581,7 +551,6 @@
         // apply zen off multiple times - verify ringer is not set to normal
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_SILENT);
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelperSpy.mConfig = null; // will evaluate config to zen mode off
         for (int i = 0; i < 3; i++) {
             // if zen doesn't change, zen should not reapply itself to the ringer
             mZenModeHelperSpy.evaluateZenMode("test", true);
@@ -596,6 +565,7 @@
         AudioManagerInternal mAudioManager = mock(AudioManagerInternal.class);
         mZenModeHelperSpy.mAudioManager = mAudioManager;
         mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_OFF;
+        mZenModeHelperSpy.mConfig = new ZenModeConfig();
 
         // previously set silent ringer
         ZenModeHelper.RingerModeDelegate ringerModeDelegate =
@@ -609,7 +579,6 @@
         // apply zen off multiple times - verify ringer is not set to normal
         when(mAudioManager.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-        mZenModeHelperSpy.mConfig = null; // will evaluate config to zen mode off
         for (int i = 0; i < 3; i++) {
             // if zen doesn't change, zen should not reapply itself to the ringer
             mZenModeHelperSpy.evaluateZenMode("test", true);