Merge changes Ic196ef31,Ifeb8d038

* changes:
  Uses a custom JUnit rule to preserve value of autofill service settings.
  Moar PERF tests for autofill.
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9a491bc..9511786 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1048,6 +1048,22 @@
     }
 
     @Override
+    public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+            String[] receiverPermissions) {
+        warnIfCallingFromSystemProcess();
+        String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
+        try {
+            intent.prepareToLeaveProcess(this);
+            ActivityManager.getService().broadcastIntent(
+                    mMainThread.getApplicationThread(), intent, resolvedType, null,
+                    Activity.RESULT_OK, null, null, receiverPermissions, AppOpsManager.OP_NONE,
+                    null, false, false, user.getIdentifier());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @Override
     public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
         warnIfCallingFromSystemProcess();
         String resolvedType = intent.resolveTypeIfNeeded(getContentResolver());
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 64998a3..133f339 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1977,6 +1977,33 @@
 
     /**
      * Broadcast the given intent to all interested BroadcastReceivers, allowing
+     * an array of required permissions to be enforced.  This call is asynchronous; it returns
+     * immediately, and you will continue executing while the receivers are run.  No results are
+     * propagated from receivers and receivers can not abort the broadcast. If you want to allow
+     * receivers to propagate results or abort the broadcast, you must send an ordered broadcast
+     * using {@link #sendOrderedBroadcast(Intent, String)}.
+     *
+     * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
+     *
+     * @param intent The Intent to broadcast; all receivers matching this
+     *               Intent will receive the broadcast.
+     * @param user The user to send the broadcast to.
+     * @param receiverPermissions Array of names of permissions that a receiver must hold
+     *                            in order to receive your broadcast.
+     *                            If null or empty, no permissions are required.
+     *
+     * @see android.content.BroadcastReceiver
+     * @see #registerReceiver
+     * @see #sendBroadcast(Intent)
+     * @see #sendOrderedBroadcast(Intent, String)
+     * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
+     * @hide
+     */
+    public abstract void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+            String[] receiverPermissions);
+
+    /**
+     * Broadcast the given intent to all interested BroadcastReceivers, allowing
      * an optional required permission to be enforced.  This
      * call is asynchronous; it returns immediately, and you will continue
      * executing while the receivers are run.  No results are propagated from
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 1867a6d..bae99b8 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -456,6 +456,13 @@
     }
 
     /** @hide */
+    @Override
+    public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+            String[] receiverPermissions) {
+        mBase.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions);
+    }
+
+    /** @hide */
     @SystemApi
     @Override
     public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6c57d88..f1dcaf9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1785,6 +1785,12 @@
     public static final int USER_SETUP_PERSONALIZATION_STARTED = 1;
 
     /**
+     * User has snoozed personalization and will complete it later.
+     * @hide
+     */
+    public static final int USER_SETUP_PERSONALIZATION_PAUSED = 2;
+
+    /**
      * User has completed setup personalization.
      * @hide
      */
@@ -1795,6 +1801,7 @@
     @IntDef({
             USER_SETUP_PERSONALIZATION_NOT_STARTED,
             USER_SETUP_PERSONALIZATION_STARTED,
+            USER_SETUP_PERSONALIZATION_PAUSED,
             USER_SETUP_PERSONALIZATION_COMPLETE
     })
     public @interface UserSetupPersonalization {}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index 309fa4a..510626b 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -16,6 +16,10 @@
 
 package android.service.notification;
 
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.NotificationManager;
@@ -68,6 +72,7 @@
     public static final int SOURCE_STAR = 2;
     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;
 
     public static final String EVENTS_DEFAULT_RULE_ID = "EVENTS_DEFAULT_RULE";
     public static final String EVERY_NIGHT_DEFAULT_RULE_ID = "EVERY_NIGHT_DEFAULT_RULE";
@@ -93,13 +98,10 @@
     private static final boolean DEFAULT_ALLOW_REMINDERS = false;
     private static final boolean DEFAULT_ALLOW_EVENTS = false;
     private static final boolean DEFAULT_ALLOW_REPEAT_CALLERS = false;
-    private static final boolean DEFAULT_ALLOW_SCREEN_OFF = false;
-    private static final boolean DEFAULT_ALLOW_SCREEN_ON = false;
     private static final boolean DEFAULT_CHANNELS_BYPASSING_DND = false;
-    private static final int DEFAULT_SUPPRESSED_VISUAL_EFFECTS =
-            Policy.getAllSuppressedVisualEffects();
+    private static final int DEFAULT_SUPPRESSED_VISUAL_EFFECTS = 0;
 
-    public static final int XML_VERSION = 7;
+    public static final int XML_VERSION = 8;
     public static final String ZEN_TAG = "zen";
     private static final String ZEN_ATT_VERSION = "version";
     private static final String ZEN_ATT_USER = "user";
@@ -151,12 +153,10 @@
     public boolean allowMessages = DEFAULT_ALLOW_MESSAGES;
     public boolean allowReminders = DEFAULT_ALLOW_REMINDERS;
     public boolean allowEvents = DEFAULT_ALLOW_EVENTS;
-    public int allowCallsFrom = DEFAULT_SOURCE;
+    public int allowCallsFrom = DEFAULT_CALLS_SOURCE;
     public int allowMessagesFrom = DEFAULT_SOURCE;
     public int user = UserHandle.USER_SYSTEM;
     public int suppressedVisualEffects = DEFAULT_SUPPRESSED_VISUAL_EFFECTS;
-    public boolean allowWhenScreenOff = DEFAULT_ALLOW_SCREEN_OFF;
-    public boolean allowWhenScreenOn = DEFAULT_ALLOW_SCREEN_ON;
     public boolean areChannelsBypassingDnd = DEFAULT_CHANNELS_BYPASSING_DND;
     public int version;
 
@@ -185,8 +185,6 @@
                 automaticRules.put(ids[i], rules[i]);
             }
         }
-        allowWhenScreenOff = source.readInt() == 1;
-        allowWhenScreenOn = source.readInt() == 1;
         allowAlarms = source.readInt() == 1;
         allowMedia = source.readInt() == 1;
         allowSystem = source.readInt() == 1;
@@ -219,8 +217,6 @@
         } else {
             dest.writeInt(0);
         }
-        dest.writeInt(allowWhenScreenOff ? 1 : 0);
-        dest.writeInt(allowWhenScreenOn ? 1 : 0);
         dest.writeInt(allowAlarms ? 1 : 0);
         dest.writeInt(allowMedia ? 1 : 0);
         dest.writeInt(allowSystem ? 1 : 0);
@@ -242,8 +238,6 @@
                 .append(",allowMessages=").append(allowMessages)
                 .append(",allowCallsFrom=").append(sourceToString(allowCallsFrom))
                 .append(",allowMessagesFrom=").append(sourceToString(allowMessagesFrom))
-                .append(",allowWhenScreenOff=").append(allowWhenScreenOff)
-                .append(",allowWhenScreenOn=").append(allowWhenScreenOn)
                 .append(",suppressedVisualEffects=").append(suppressedVisualEffects)
                 .append(",areChannelsBypassingDnd=").append(areChannelsBypassingDnd)
                 .append(",automaticRules=").append(automaticRules)
@@ -289,12 +283,6 @@
         if (allowMessagesFrom != to.allowMessagesFrom) {
             d.addLine("allowMessagesFrom", allowMessagesFrom, to.allowMessagesFrom);
         }
-        if (allowWhenScreenOff != to.allowWhenScreenOff) {
-            d.addLine("allowWhenScreenOff", allowWhenScreenOff, to.allowWhenScreenOff);
-        }
-        if (allowWhenScreenOn != to.allowWhenScreenOn) {
-            d.addLine("allowWhenScreenOn", allowWhenScreenOn, to.allowWhenScreenOn);
-        }
         if (suppressedVisualEffects != to.suppressedVisualEffects) {
             d.addLine("suppressedVisualEffects", suppressedVisualEffects,
                     to.suppressedVisualEffects);
@@ -404,8 +392,6 @@
                 && other.allowMessagesFrom == allowMessagesFrom
                 && other.allowReminders == allowReminders
                 && other.allowEvents == allowEvents
-                && other.allowWhenScreenOff == allowWhenScreenOff
-                && other.allowWhenScreenOn == allowWhenScreenOn
                 && other.user == user
                 && Objects.equals(other.automaticRules, automaticRules)
                 && Objects.equals(other.manualRule, manualRule)
@@ -418,7 +404,7 @@
         return Objects.hash(allowAlarms, allowMedia, allowSystem, allowCalls,
                 allowRepeatCallers, allowMessages,
                 allowCallsFrom, allowMessagesFrom, allowReminders, allowEvents,
-                allowWhenScreenOff, allowWhenScreenOn, user, automaticRules, manualRule,
+                user, automaticRules, manualRule,
                 suppressedVisualEffects, areChannelsBypassingDnd);
     }
 
@@ -472,6 +458,7 @@
         final ZenModeConfig rt = new ZenModeConfig();
         rt.version = safeInt(parser, ZEN_ATT_VERSION, XML_VERSION);
         rt.user = safeInt(parser, ZEN_ATT_USER, rt.user);
+        boolean readSuppressedEffects = false;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
             tag = parser.getName();
             if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) {
@@ -502,17 +489,33 @@
                         rt.allowCallsFrom = DEFAULT_SOURCE;
                         rt.allowMessagesFrom = DEFAULT_SOURCE;
                     }
-                    // continue to read even though we now have suppressedVisualEffects, in case
-                    // we need to revert to users' previous settings
-                    rt.allowWhenScreenOff =
-                            safeBoolean(parser, ALLOW_ATT_SCREEN_OFF, DEFAULT_ALLOW_SCREEN_OFF);
-                    rt.allowWhenScreenOn =
-                            safeBoolean(parser, ALLOW_ATT_SCREEN_ON, DEFAULT_ALLOW_SCREEN_ON);
                     rt.allowAlarms = safeBoolean(parser, ALLOW_ATT_ALARMS, DEFAULT_ALLOW_ALARMS);
                     rt.allowMedia = safeBoolean(parser, ALLOW_ATT_MEDIA,
                             DEFAULT_ALLOW_MEDIA);
                     rt.allowSystem = safeBoolean(parser, ALLOW_ATT_SYSTEM, DEFAULT_ALLOW_SYSTEM);
-                } else if (DISALLOW_TAG.equals(tag)) {
+
+                    // migrate old suppressed visual effects fields, if they still exist in the xml
+                    Boolean allowWhenScreenOff = unsafeBoolean(parser, ALLOW_ATT_SCREEN_OFF);
+                    if (allowWhenScreenOff != null) {
+                        readSuppressedEffects = true;
+                        if (allowWhenScreenOff) {
+                            rt.suppressedVisualEffects |= SUPPRESSED_EFFECT_LIGHTS
+                                    | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+                        }
+                    }
+                    Boolean allowWhenScreenOn = unsafeBoolean(parser, ALLOW_ATT_SCREEN_ON);
+                    if (allowWhenScreenOn != null) {
+                        readSuppressedEffects = true;
+                        if (allowWhenScreenOn) {
+                            rt.suppressedVisualEffects |= SUPPRESSED_EFFECT_PEEK;
+                        }
+                    }
+                    if (readSuppressedEffects) {
+                        Slog.d(TAG, "Migrated visual effects to " + rt.suppressedVisualEffects);
+                    }
+                } else if (DISALLOW_TAG.equals(tag) && !readSuppressedEffects) {
+                    // only read from suppressed visual effects field if we haven't just migrated
+                    // the values from allowOn/allowOff, lest we wipe out those settings
                     rt.suppressedVisualEffects = safeInt(parser, DISALLOW_ATT_VISUAL_EFFECTS,
                             DEFAULT_SUPPRESSED_VISUAL_EFFECTS);
                 } else if (MANUAL_TAG.equals(tag)) {
@@ -552,8 +555,6 @@
         out.attribute(null, ALLOW_ATT_EVENTS, Boolean.toString(allowEvents));
         out.attribute(null, ALLOW_ATT_CALLS_FROM, Integer.toString(allowCallsFrom));
         out.attribute(null, ALLOW_ATT_MESSAGES_FROM, Integer.toString(allowMessagesFrom));
-        out.attribute(null, ALLOW_ATT_SCREEN_OFF, Boolean.toString(allowWhenScreenOff));
-        out.attribute(null, ALLOW_ATT_SCREEN_ON, Boolean.toString(allowWhenScreenOn));
         out.attribute(null, ALLOW_ATT_ALARMS, Boolean.toString(allowAlarms));
         out.attribute(null, ALLOW_ATT_MEDIA, Boolean.toString(allowMedia));
         out.attribute(null, ALLOW_ATT_SYSTEM, Boolean.toString(allowSystem));
@@ -673,6 +674,12 @@
         return source >= SOURCE_ANYONE && source <= MAX_SOURCE;
     }
 
+    private static Boolean unsafeBoolean(XmlPullParser parser, String att) {
+        final String val = parser.getAttributeValue(null, att);
+        if (TextUtils.isEmpty(val)) return null;
+        return Boolean.parseBoolean(val);
+    }
+
     private static boolean safeBoolean(XmlPullParser parser, String att, boolean defValue) {
         final String val = parser.getAttributeValue(null, att);
         return safeBoolean(val, defValue);
diff --git a/core/java/android/view/RecordingCanvas.java b/core/java/android/view/RecordingCanvas.java
index f7a41ff..18cc10f 100644
--- a/core/java/android/view/RecordingCanvas.java
+++ b/core/java/android/view/RecordingCanvas.java
@@ -34,6 +34,7 @@
 import android.graphics.RectF;
 import android.graphics.TemporaryBuffer;
 import android.text.GraphicsOperations;
+import android.text.MeasuredParagraph;
 import android.text.PrecomputedText;
 import android.text.SpannableString;
 import android.text.SpannedString;
@@ -500,21 +501,31 @@
             ((GraphicsOperations) text).drawTextRun(this, start, end,
                     contextStart, contextEnd, x, y, isRtl, paint);
         } else {
+            if (text instanceof PrecomputedText) {
+                final PrecomputedText pt = (PrecomputedText) text;
+                final int paraIndex = pt.findParaIndex(start);
+                if (end <= pt.getParagraphEnd(paraIndex)) {
+                    final int paraStart = pt.getParagraphStart(paraIndex);
+                    final MeasuredParagraph mp = pt.getMeasuredParagraph(paraIndex);
+                    // Only support if the target is in the same paragraph.
+                    nDrawTextRun(mNativeCanvasWrapper,
+                            mp.getChars(),
+                            start - paraStart,
+                            end - start,
+                            contextStart - paraStart,
+                            contextEnd - contextStart,
+                            x, y, isRtl, paint.getNativeInstance(),
+                            mp.getNativePtr());
+                    return;
+                }
+            }
             int contextLen = contextEnd - contextStart;
             int len = end - start;
             char[] buf = TemporaryBuffer.obtain(contextLen);
             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-            long measuredTextPtr = 0;
-            if (text instanceof PrecomputedText) {
-                PrecomputedText mt = (PrecomputedText) text;
-                int paraIndex = mt.findParaIndex(start);
-                if (end <= mt.getParagraphEnd(paraIndex)) {
-                    // Only support if the target is in the same paragraph.
-                    measuredTextPtr = mt.getMeasuredParagraph(paraIndex).getNativePtr();
-                }
-            }
             nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
-                    0, contextLen, x, y, isRtl, paint.getNativeInstance(), measuredTextPtr);
+                    0, contextLen, x, y, isRtl, paint.getNativeInstance(),
+                    0 /* measured paragraph pointer */);
             TemporaryBuffer.recycle(buf);
         }
     }
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 1c2e43e..6bacdfe 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -901,7 +901,7 @@
      * Refreshes this info with the latest state of the view it represents, and request new
      * data be added by the View.
      *
-     * @param extraDataKey A bitmask of the extra data requested. Data that must be requested
+     * @param extraDataKey The extra data requested. Data that must be requested
      *                     with this mechanism is generally expensive to retrieve, so should only be
      *                     requested when needed. See
      *                     {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
diff --git a/core/res/res/drawable/ic_dnd_block_notifications.xml b/core/res/res/drawable/ic_dnd_block_notifications.xml
new file mode 100644
index 0000000..4983614
--- /dev/null
+++ b/core/res/res/drawable/ic_dnd_block_notifications.xml
@@ -0,0 +1,30 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="40dp"
+        android:height="40dp"
+        android:viewportWidth="40.0"
+        android:viewportHeight="40.0">
+    <path
+        android:pathData="M34,20H2c-1.1,0 -2,-0.9 -2,-2V6c0,-1.1 0.9,-2 2,-2h32c1.1,0 2,0.9 2,2v12C36,19.1 35.1,20 34,20z"
+        android:fillColor="#FBBC04"/>
+    <path
+        android:pathData="M4.63,10L4.63,10c-0.83,0 -1.5,-0.67 -1.5,-1.5v0C3.12,7.67 3.8,7 4.62,7h0c0.82,0 1.5,0.67 1.5,1.5v0C6.12,9.33 5.45,10 4.63,10z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M8.62,7.5h9.5v2h-9.5z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M3.12,15h24v2h-24z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M3.12,12h17.5v2h-17.5z"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M33.59,6.41m-5.78,0a5.78,5.78 0,1 1,11.56 0a5.78,5.78 0,1 1,-11.56 0"
+        android:fillColor="#FFFFFF"/>
+    <path
+        android:pathData="M33.5,0C29.91,0 27,2.91 27,6.5s2.91,6.5 6.5,6.5S40,10.09 40,6.5S37.09,0 33.5,0zM33.5,11.7c-2.87,0 -5.2,-2.33 -5.2,-5.2s2.33,-5.2 5.2,-5.2s5.2,2.33 5.2,5.2S36.37,11.7 33.5,11.7z"
+        android:fillColor="#4285F4"/>
+    <path
+        android:pathData="M30.25,5.85h6.5v1.3h-6.5z"
+        android:fillColor="#4285F4"/>
+</vector>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5298e5b..c3ab1a6 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2555,6 +2555,7 @@
   <java-symbol type="drawable" name="ic_storage_48dp" />
   <java-symbol type="drawable" name="ic_usb_48dp" />
   <java-symbol type="drawable" name="ic_zen_24dp" />
+  <java-symbol type="drawable" name="ic_dnd_block_notifications" />
 
   <!-- Floating toolbar -->
   <java-symbol type="id" name="floating_toolbar_menu_item_image" />
diff --git a/core/res/res/xml/default_zen_mode_config.xml b/core/res/res/xml/default_zen_mode_config.xml
index 3a71851..ba8173e 100644
--- a/core/res/res/xml/default_zen_mode_config.xml
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -19,7 +19,7 @@
 
 <!-- Default configuration for zen mode.  See android.service.notification.ZenModeConfig. -->
 <zen version="7">
-    <allow alarms="true" media="true" system="false" calls="false" messages="false"
+    <allow alarms="true" media="true" system="false" calls="false" callsFrom="2" messages="false"
            reminders="false" events="false" />
 
     <!-- all visual effects that exist as of P -->
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
index 71ee6c2..97130f1 100644
--- a/graphics/java/android/graphics/BaseCanvas.java
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -22,6 +22,7 @@
 import android.annotation.Size;
 import android.graphics.Canvas.VertexMode;
 import android.text.GraphicsOperations;
+import android.text.MeasuredParagraph;
 import android.text.PrecomputedText;
 import android.text.SpannableString;
 import android.text.SpannedString;
@@ -486,21 +487,31 @@
             ((GraphicsOperations) text).drawTextRun(this, start, end,
                     contextStart, contextEnd, x, y, isRtl, paint);
         } else {
+            if (text instanceof PrecomputedText) {
+                final PrecomputedText pt = (PrecomputedText) text;
+                final int paraIndex = pt.findParaIndex(start);
+                if (end <= pt.getParagraphEnd(paraIndex)) {
+                    final int paraStart = pt.getParagraphStart(paraIndex);
+                    final MeasuredParagraph mp = pt.getMeasuredParagraph(paraIndex);
+                    // Only support the text in the same paragraph.
+                    nDrawTextRun(mNativeCanvasWrapper,
+                            mp.getChars(),
+                            start - paraStart,
+                            end - start,
+                            contextStart - paraStart,
+                            contextEnd - contextStart,
+                            x, y, isRtl, paint.getNativeInstance(),
+                            mp.getNativePtr());
+                    return;
+                }
+            }
             int contextLen = contextEnd - contextStart;
             int len = end - start;
             char[] buf = TemporaryBuffer.obtain(contextLen);
             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
-            long measuredTextPtr = 0;
-            if (text instanceof PrecomputedText) {
-                PrecomputedText mt = (PrecomputedText) text;
-                int paraIndex = mt.findParaIndex(start);
-                if (end <= mt.getParagraphEnd(paraIndex)) {
-                    // Only suppor the text in the same paragraph.
-                    measuredTextPtr = mt.getMeasuredParagraph(paraIndex).getNativePtr();
-                }
-            }
             nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
-                    0, contextLen, x, y, isRtl, paint.getNativeInstance(), measuredTextPtr);
+                    0, contextLen, x, y, isRtl, paint.getNativeInstance(),
+                    0 /* measured paragraph pointer */);
             TemporaryBuffer.recycle(buf);
         }
     }
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index 1d3e521..32aafea 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2935,7 +2935,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 164;
+            private static final int SETTINGS_VERSION = 165;
 
             private final int mUserId;
 
@@ -3710,17 +3710,7 @@
                 }
 
                 if (currentVersion == 162) {
-                    // Version 162: Add a gesture for silencing phones
-                    final SettingsState settings = getGlobalSettingsLocked();
-                    final Setting currentSetting = settings.getSettingLocked(
-                            Global.SHOW_ZEN_UPGRADE_NOTIFICATION);
-                    if (!currentSetting.isNull()
-                            && TextUtils.equals("0", currentSetting.getValue())) {
-                        settings.insertSettingLocked(
-                                Global.SHOW_ZEN_UPGRADE_NOTIFICATION, "1",
-                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
-
+                    // Version 162: REMOVED: Add a gesture for silencing phones
                     currentVersion = 163;
                 }
 
@@ -3742,6 +3732,21 @@
                     currentVersion = 164;
                 }
 
+                if (currentVersion == 164) {
+                    // Version 164: Add a gesture for silencing phones
+                    final SettingsState settings = getGlobalSettingsLocked();
+                    final Setting currentSetting = settings.getSettingLocked(
+                            Global.SHOW_ZEN_UPGRADE_NOTIFICATION);
+                    if (!currentSetting.isNull()
+                            && TextUtils.equals("0", currentSetting.getValue())) {
+                        settings.insertSettingLocked(
+                                Global.SHOW_ZEN_UPGRADE_NOTIFICATION, "1",
+                                null, true, SettingsState.SYSTEM_PACKAGE_NAME);
+                    }
+
+                    currentVersion = 165;
+                }
+
                 // vXXX: Add new settings above this point.
 
                 if (currentVersion != newVersion) {
diff --git a/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml b/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml
new file mode 100644
index 0000000..eff9b36
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_dnd_suppressing_notifications.xml
@@ -0,0 +1,34 @@
+<!--
+    Copyright 2018, The Android Open Source Project
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<!-- Extends Framelayout -->
+<com.android.systemui.statusbar.DndSuppressingNotificationsView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/hidden_container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:visibility="gone">
+    <TextView
+        android:id="@+id/hidden_notifications"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="64dp"
+        android:paddingTop="28dp"
+        android:gravity="top|center_horizontal"
+        android:textColor="?attr/wallpaperTextColor"
+        android:textSize="16sp"
+        android:text="@string/dnd_suppressing_shade_text"/>
+</com.android.systemui.statusbar.DndSuppressingNotificationsView>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 697ab06..50e7b5c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -240,6 +240,8 @@
     <string name="accessibility_waiting_for_fingerprint">Waiting for fingerprint</string>
     <!-- Accessibility action of the unlock button when fingerpint is on (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_unlock_without_fingerprint">Unlock without using your fingerprint</string>
+    <!-- Content description of the Trusted Face icon for accessibility. [CHAR LIMIT=NONE] -->
+    <string name="accessibility_scanning_face">Scanning face</string>
     <!-- Click action label for accessibility for the smart reply buttons (not shown on-screen).". [CHAR LIMIT=NONE] -->
     <string name="accessibility_send_smart_reply">Send</string>
     <!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
@@ -1062,7 +1064,7 @@
     <string name="manage_notifications_text">Manage notifications</string>
 
     <!-- The text to show in the notifications shade when dnd is suppressing notifications. [CHAR LIMIT=100] -->
-    <string name="dnd_suppressing_shade_text">Do Not Disturb is hiding notifications</string>
+    <string name="dnd_suppressing_shade_text">Notifications hidden by Do Not Disturb</string>
 
     <!-- Media projection permission dialog action text. [CHAR LIMIT=60] -->
     <string name="media_projection_action_text">Start now</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java
new file mode 100644
index 0000000..db3a02d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DndSuppressingNotificationsView.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.annotation.ColorInt;
+import android.annotation.DrawableRes;
+import android.annotation.IntegerRes;
+import android.annotation.StringRes;
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.graphics.drawable.Icon;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.ExpandableViewState;
+import com.android.systemui.statusbar.stack.StackScrollState;
+
+public class DndSuppressingNotificationsView extends StackScrollerDecorView {
+
+    private TextView mText;
+    private @StringRes int mTextId = R.string.dnd_suppressing_shade_text;
+
+    public DndSuppressingNotificationsView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        mText.setText(mTextId);
+    }
+
+    @Override
+    protected View findContentView() {
+        return findViewById(R.id.hidden_container);
+    }
+
+    @Override
+    protected View findSecondaryView() {
+        return null;
+    }
+
+    public void setColor(@ColorInt int color) {
+        mText.setTextColor(color);
+    }
+
+    public void setOnContentClickListener(OnClickListener listener) {
+        mText.setOnClickListener(listener);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mText = findViewById(R.id.hidden_notifications);
+    }
+
+    @Override
+    public ExpandableViewState createNewViewState(StackScrollState stackScrollState) {
+        return new DndSuppressingViewState();
+    }
+
+    public class DndSuppressingViewState extends ExpandableViewState {
+        @Override
+        public void applyToView(View view) {
+            super.applyToView(view);
+            if (view instanceof DndSuppressingNotificationsView) {
+                DndSuppressingNotificationsView dndView = (DndSuppressingNotificationsView) view;
+                boolean visible = this.clipTopAmount <= mText.getPaddingTop() * 0.6f;
+                dndView.performVisibilityAnimation(visible && !dndView.willBeGone());
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 264f574..4b66ee5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -55,6 +55,7 @@
     private final UnlockMethodCache mUnlockMethodCache;
     private AccessibilityController mAccessibilityController;
     private boolean mHasFingerPrintIcon;
+    private boolean mHasFaceUnlockIcon;
     private int mDensity;
 
     private final Runnable mDrawOffTimeout = () -> update(true /* forceUpdate */);
@@ -130,6 +131,7 @@
         }
         int state = getState();
         boolean anyFingerprintIcon = state == STATE_FINGERPRINT || state == STATE_FINGERPRINT_ERROR;
+        mHasFaceUnlockIcon = state == STATE_FACE_UNLOCK;
         boolean useAdditionalPadding = anyFingerprintIcon;
         boolean trustHidden = anyFingerprintIcon;
         if (state != mLastState || mDeviceInteractive != mLastDeviceInteractive
@@ -179,6 +181,11 @@
             setRestingAlpha(
                     anyFingerprintIcon ? 1f : KeyguardAffordanceHelper.SWIPE_RESTING_ALPHA_AMOUNT);
             setImageDrawable(icon, false);
+            if (mHasFaceUnlockIcon) {
+                announceForAccessibility(getContext().getString(
+                    R.string.accessibility_scanning_face));
+            }
+
             mHasFingerPrintIcon = anyFingerprintIcon;
             if (animation != null && isAnim) {
                 animation.forceAnimationOnUI();
@@ -228,6 +235,11 @@
             info.addAction(unlock);
             info.setHintText(getContext().getString(
                     R.string.accessibility_waiting_for_fingerprint));
+        } else if (mHasFaceUnlockIcon){
+            //Avoid 'button' to be spoken for scanning face
+            info.setClassName(LockIcon.class.getName());
+            info.setContentDescription(getContext().getString(
+                R.string.accessibility_scanning_face));
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index b650944..8bb73da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -199,6 +199,7 @@
     private ValueAnimator mQsSizeChangeAnimator;
 
     private boolean mShowEmptyShadeView;
+    private boolean mShowDndView;
 
     private boolean mQsScrimEnabled = true;
     private boolean mLastAnnouncementWasQuickSettings;
@@ -1599,8 +1600,8 @@
         // When only empty shade view is visible in QS collapsed state, simulate that we would have
         // it in expanded QS state as well so we don't run into troubles when fading the view in/out
         // and expanding/collapsing the whole panel from/to quick settings.
-        if (mNotificationStackScroller.getNotGoneChildCount() == 0
-                && mShowEmptyShadeView) {
+        if ((mNotificationStackScroller.getNotGoneChildCount() == 0
+                && mShowEmptyShadeView) || mShowDndView) {
             notificationHeight = mNotificationStackScroller.getEmptyShadeViewHeight();
         }
         int maxQsHeight = mQsMaxExpansionHeight;
@@ -2243,13 +2244,17 @@
         return mDozing;
     }
 
+    public void showDndView(boolean dndViewVisible) {
+        mShowDndView = dndViewVisible;
+        mNotificationStackScroller.updateDndView(mShowDndView && !mQsExpanded);
+    }
+
     public void showEmptyShadeView(boolean emptyShadeViewVisible) {
         mShowEmptyShadeView = emptyShadeViewVisible;
         updateEmptyShadeView();
     }
 
     private void updateEmptyShadeView() {
-
         // Hide "No notifications" in QS.
         mNotificationStackScroller.updateEmptyShadeView(mShowEmptyShadeView && !mQsExpanded);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index ff0adb6..57a3556 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -20,6 +20,7 @@
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
+import static android.provider.Settings.Global.ZEN_MODE_OFF;
 
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
 import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
@@ -168,6 +169,7 @@
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.VolumeDialogController;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 import com.android.systemui.qs.QSFragment;
@@ -188,6 +190,7 @@
 import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CrossFadeHelper;
+import com.android.systemui.statusbar.DndSuppressingNotificationsView;
 import com.android.systemui.statusbar.DragDownHelper;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -413,7 +416,7 @@
     protected NotificationViewHierarchyManager mViewHierarchyManager;
     protected AppOpsListener mAppOpsListener;
     protected KeyguardViewMediator mKeyguardViewMediator;
-    private ZenModeController mZenController;
+    protected ZenModeController mZenController;
 
     /**
      * Helper that is responsible for showing the right toast when a disallowed activity operation
@@ -878,6 +881,7 @@
         mVisualStabilityManager.setVisibilityLocationProvider(mStackScroller);
 
         inflateEmptyShadeView();
+        inflateDndView();
         inflateFooterView();
 
         mBackdrop = mStatusBarWindow.findViewById(R.id.backdrop);
@@ -1145,6 +1149,7 @@
     protected void reevaluateStyles() {
         inflateFooterView();
         updateFooter();
+        inflateDndView();
         inflateEmptyShadeView();
         updateEmptyShadeView();
     }
@@ -1166,6 +1171,19 @@
         mStackScroller.setEmptyShadeView(mEmptyShadeView);
     }
 
+    private void inflateDndView() {
+        if (mStackScroller == null) {
+            return;
+        }
+        mDndView = (DndSuppressingNotificationsView) LayoutInflater.from(mContext).inflate(
+                R.layout.status_bar_dnd_suppressing_notifications, mStackScroller, false);
+        mDndView.setOnContentClickListener(v -> {
+            Intent intent = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
+            startActivity(intent, true, true, Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        });
+        mStackScroller.setDndView(mDndView);
+    }
+
     private void inflateFooterView() {
         if (mStackScroller == null) {
             return;
@@ -1460,9 +1478,11 @@
     @VisibleForTesting
     protected void updateFooter() {
         boolean showFooterView = mState != StatusBarState.KEYGUARD
+                && !areNotificationsHidden()
                 && mEntryManager.getNotificationData().getActiveNotifications().size() != 0
                 && !mRemoteInputManager.getController().isRemoteInputActive();
         boolean showDismissView = mClearAllEnabled && mState != StatusBarState.KEYGUARD
+                && !areNotificationsHidden()
                 && hasActiveClearableNotifications();
 
         mStackScroller.updateFooterView(showFooterView, showDismissView);
@@ -1485,10 +1505,13 @@
         return false;
     }
 
-    private void updateEmptyShadeView() {
-        boolean showEmptyShadeView =
-                mState != StatusBarState.KEYGUARD &&
-                        mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
+    @VisibleForTesting
+    protected void updateEmptyShadeView() {
+        boolean showDndView = mState != StatusBarState.KEYGUARD && areNotificationsHidden();
+        boolean showEmptyShadeView = !showDndView
+                && mState != StatusBarState.KEYGUARD
+                && mEntryManager.getNotificationData().getActiveNotifications().size() == 0;
+        mNotificationPanel.showDndView(showDndView);
         mNotificationPanel.showEmptyShadeView(showEmptyShadeView);
     }
 
@@ -4988,6 +5011,7 @@
     protected NotificationShelf mNotificationShelf;
     protected FooterView mFooterView;
     protected EmptyShadeView mEmptyShadeView;
+    protected DndSuppressingNotificationsView mDndView;
 
     protected AssistManager mAssistManager;
 
@@ -5472,6 +5496,11 @@
                     mStackScroller.getChildCount() - offsetFromEnd++);
         }
 
+        if (mDndView != null) {
+            mStackScroller.changeViewPosition(mDndView,
+                    mStackScroller.getChildCount() - offsetFromEnd++);
+        }
+
         mStackScroller.changeViewPosition(mEmptyShadeView,
                 mStackScroller.getChildCount() - offsetFromEnd++);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 1798dbc..5ca5752 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -81,6 +81,7 @@
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.statusbar.ActivatableNotificationView;
+import com.android.systemui.statusbar.DndSuppressingNotificationsView;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
@@ -236,6 +237,7 @@
     protected boolean mScrollingEnabled;
     protected FooterView mFooterView;
     protected EmptyShadeView mEmptyShadeView;
+    protected DndSuppressingNotificationsView mDndView;
     private boolean mDismissAllInProgress;
     private boolean mFadeNotificationsOnDismiss;
 
@@ -1006,7 +1008,8 @@
     private float getAppearEndPosition() {
         int appearPosition;
         int notGoneChildCount = getNotGoneChildCount();
-        if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
+        if ((mEmptyShadeView.getVisibility() == GONE && mDndView.getVisibility() == GONE)
+                && notGoneChildCount != 0) {
             if (isHeadsUpTransition()
                     || (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
                 appearPosition = getTopHeadsUpPinnedHeight();
@@ -1016,6 +1019,8 @@
                     appearPosition += mShelf.getIntrinsicHeight();
                 }
             }
+        } else if (mEmptyShadeView.getVisibility() == GONE) {
+            appearPosition = mDndView.getHeight();
         } else {
             appearPosition = mEmptyShadeView.getHeight();
         }
@@ -2608,19 +2613,6 @@
         return mShelf.getVisibility() == GONE ? 0 : mShelf.getIntrinsicHeight();
     }
 
-    public int getFirstChildIntrinsicHeight() {
-        final ExpandableView firstChild = getFirstChildNotGone();
-        int firstChildMinHeight = firstChild != null
-                ? firstChild.getIntrinsicHeight()
-                : mEmptyShadeView != null
-                        ? mEmptyShadeView.getIntrinsicHeight()
-                        : mCollapsedSize;
-        if (mOwnScrollY > 0) {
-            firstChildMinHeight = Math.max(firstChildMinHeight - mOwnScrollY, mCollapsedSize);
-        }
-        return firstChildMinHeight;
-    }
-
     public float getTopPaddingOverflow() {
         return mTopPaddingOverflow;
     }
@@ -3918,6 +3910,7 @@
         final int textColor = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColor);
         mFooterView.setTextColor(textColor);
         mEmptyShadeView.setTextColor(textColor);
+        mDndView.setColor(textColor);
     }
 
     public void goToFullShade(long delay) {
@@ -3925,6 +3918,7 @@
             mFooterView.setInvisible();
         }
         mEmptyShadeView.setInvisible();
+        mDndView.setInvisible();
         mGoToFullShadeNeedsAnimation = true;
         mGoToFullShadeDelay = delay;
         mNeedsAnimation = true;
@@ -4076,25 +4070,39 @@
         int newVisibility = visible ? VISIBLE : GONE;
 
         boolean changedVisibility = oldVisibility != newVisibility;
-        if (changedVisibility || newVisibility != GONE) {
+        if (changedVisibility) {
             if (newVisibility != GONE) {
-                int oldText = mEmptyShadeView.getTextResource();
-                int newText;
-                if (mStatusBar.areNotificationsHidden()) {
-                    newText = R.string.dnd_suppressing_shade_text;
-                } else {
-                    newText = R.string.empty_shade_text;
-                }
-                if (changedVisibility || !Objects.equals(oldText, newText)) {
-                    mEmptyShadeView.setText(newText);
-                    showFooterView(mEmptyShadeView);
-                }
+                showFooterView(mEmptyShadeView);
             } else {
                 hideFooterView(mEmptyShadeView, true);
             }
         }
     }
 
+    public void setDndView(DndSuppressingNotificationsView dndView) {
+        int index = -1;
+        if (mDndView != null) {
+            index = indexOfChild(mDndView);
+            removeView(mDndView);
+        }
+        mDndView = dndView;
+        addView(mDndView, index);
+    }
+
+    public void updateDndView(boolean visible) {
+        int oldVisibility = mDndView.willBeGone() ? GONE : mDndView.getVisibility();
+        int newVisibility = visible ? VISIBLE : GONE;
+
+        boolean changedVisibility = oldVisibility != newVisibility;
+        if (changedVisibility) {
+            if (newVisibility != GONE) {
+                showFooterView(mDndView);
+            } else {
+                hideFooterView(mDndView, true);
+            }
+        }
+    }
+
     public void updateFooterView(boolean visible, boolean showDismissView) {
         if (mFooterView == null) {
             return;
@@ -4119,10 +4127,16 @@
         } else {
             footerView.setInvisible();
         }
-        footerView.setVisibility(VISIBLE);
-        footerView.setWillBeGone(false);
-        updateContentHeight();
-        notifyHeightChangeListener(footerView);
+        Runnable onShowFinishRunnable = new Runnable() {
+            @Override
+            public void run() {
+                footerView.setVisibility(VISIBLE);
+                footerView.setWillBeGone(false);
+                updateContentHeight();
+                notifyHeightChangeListener(footerView);
+            }
+        };
+        footerView.performVisibilityAnimation(true, onShowFinishRunnable);
     }
 
     private void hideFooterView(StackScrollerDecorView footerView, boolean isButtonVisible) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 37e0005..41cf869 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -78,6 +78,7 @@
 import com.android.systemui.statusbar.ActivatableNotificationView;
 import com.android.systemui.statusbar.AppOpsListener;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.DndSuppressingNotificationsView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.FooterView;
 import com.android.systemui.statusbar.FooterViewButton;
@@ -103,6 +104,7 @@
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
 import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 import org.junit.Before;
@@ -132,6 +134,7 @@
     @Mock private ScrimController mScrimController;
     @Mock private ArrayList<Entry> mNotificationList;
     @Mock private FingerprintUnlockController mFingerprintUnlockController;
+    @Mock private ZenModeController mZenController;
     @Mock private NotificationData mNotificationData;
 
     // Mock dependencies:
@@ -163,6 +166,7 @@
         mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
         mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
         mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class));
+        mDependency.injectTestDependency(ZenModeController.class, mZenController);
 
         mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
         mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
@@ -213,7 +217,7 @@
                 mRemoteInputManager, mock(NotificationGroupManager.class),
                 mock(FalsingManager.class), mock(StatusBarWindowManager.class),
                 mock(NotificationIconAreaController.class), mock(DozeScrimController.class),
-                mock(NotificationShelf.class), mLockscreenUserManager,
+                mock(NotificationShelf.class), mLockscreenUserManager, mZenController,
                 mock(CommandQueue.class));
         mStatusBar.mContext = mContext;
         mStatusBar.mComponents = mContext.getComponents();
@@ -676,6 +680,60 @@
     }
 
     @Test
+    public void testDNDView_atEnd() {
+        // add footer
+        mStatusBar.reevaluateStyles();
+
+        // add notification
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        mStackScroller.addContainerView(row);
+
+        mStatusBar.onUpdateRowStates();
+
+        // move dnd view to end
+        verify(mStackScroller).changeViewPosition(any(FooterView.class), eq(-1 /* end */));
+        verify(mStackScroller).changeViewPosition(any(DndSuppressingNotificationsView.class),
+                eq(-2 /* end */));
+    }
+
+    @Test
+    public void updateEmptyShade_nonNotificationsDndOff() {
+        mStatusBar.setBarStateForTest(StatusBarState.SHADE);
+        when(mNotificationData.getActiveNotifications()).thenReturn(new ArrayList<>());
+        assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
+
+        mStatusBar.updateEmptyShadeView();
+        verify(mNotificationPanelView).showDndView(false);
+        verify(mNotificationPanelView).showEmptyShadeView(true);
+    }
+
+    @Test
+    public void updateEmptyShade_noNotificationsDndOn() {
+        mStatusBar.setBarStateForTest(StatusBarState.SHADE);
+        when(mNotificationData.getActiveNotifications()).thenReturn(new ArrayList<>());
+        assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
+        when(mZenController.areNotificationsHiddenInShade()).thenReturn(true);
+
+        mStatusBar.updateEmptyShadeView();
+        verify(mNotificationPanelView).showDndView(true);
+        verify(mNotificationPanelView).showEmptyShadeView(false);
+    }
+
+    @Test
+    public void updateEmptyShade_yesNotificationsDndOff() {
+        mStatusBar.setBarStateForTest(StatusBarState.SHADE);
+        ArrayList<Entry> entries = new ArrayList<>();
+        entries.add(mock(Entry.class));
+        when(mNotificationData.getActiveNotifications()).thenReturn(entries);
+        assertEquals(1, mEntryManager.getNotificationData().getActiveNotifications().size());
+        when(mZenController.areNotificationsHiddenInShade()).thenReturn(false);
+
+        mStatusBar.updateEmptyShadeView();
+        verify(mNotificationPanelView).showDndView(false);
+        verify(mNotificationPanelView).showEmptyShadeView(false);
+    }
+
+    @Test
     public void testSetState_changesIsFullScreenUserSwitcherState() {
         mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
         assertFalse(mStatusBar.isFullScreenUserSwitcherState());
@@ -721,6 +779,7 @@
                 DozeScrimController dozeScrimController,
                 NotificationShelf notificationShelf,
                 NotificationLockscreenUserManager notificationLockscreenUserManager,
+                ZenModeController zenController,
                 CommandQueue commandQueue) {
             mStatusBarKeyguardViewManager = man;
             mUnlockMethodCache = unlock;
@@ -749,6 +808,7 @@
             mDozeScrimController = dozeScrimController;
             mNotificationShelf = notificationShelf;
             mLockscreenUserManager = notificationLockscreenUserManager;
+            mZenController = zenController;
             mCommandQueue = commandQueue;
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
index eeb4209..3d17ec4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayoutTest.java
@@ -18,6 +18,7 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -34,6 +35,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.TestableDependency;
+import com.android.systemui.statusbar.DndSuppressingNotificationsView;
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.FooterView;
 import com.android.systemui.statusbar.NotificationBlockingHelperManager;
@@ -69,6 +71,7 @@
     @Mock private NotificationGroupManager mGroupManager;
     @Mock private ExpandHelper mExpandHelper;
     @Mock private EmptyShadeView mEmptyShadeView;
+    @Mock private DndSuppressingNotificationsView mDndView;
 
     @Before
     @UiThreadTest
@@ -86,6 +89,7 @@
         mStackScroller.setHeadsUpManager(mHeadsUpManager);
         mStackScroller.setGroupManager(mGroupManager);
         mStackScroller.setEmptyShadeView(mEmptyShadeView);
+        mStackScroller.setDndView(mDndView);
 
         // Stub out functionality that isn't necessary to test.
         doNothing().when(mBar)
@@ -120,40 +124,6 @@
     }
 
     @Test
-    public void updateEmptyView_dndSuppressing() {
-        when(mEmptyShadeView.willBeGone()).thenReturn(true);
-        when(mBar.areNotificationsHidden()).thenReturn(true);
-
-        mStackScroller.updateEmptyShadeView(true);
-
-        verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
-    }
-
-    @Test
-    public void updateEmptyView_dndNotSuppressing() {
-        mStackScroller.setEmptyShadeView(mEmptyShadeView);
-        when(mEmptyShadeView.willBeGone()).thenReturn(true);
-        when(mBar.areNotificationsHidden()).thenReturn(false);
-
-        mStackScroller.updateEmptyShadeView(true);
-
-        verify(mEmptyShadeView).setText(R.string.empty_shade_text);
-    }
-
-    @Test
-    public void updateEmptyView_noNotificationsToDndSuppressing() {
-        mStackScroller.setEmptyShadeView(mEmptyShadeView);
-        when(mEmptyShadeView.willBeGone()).thenReturn(true);
-        when(mBar.areNotificationsHidden()).thenReturn(false);
-        mStackScroller.updateEmptyShadeView(true);
-        verify(mEmptyShadeView).setText(R.string.empty_shade_text);
-
-        when(mBar.areNotificationsHidden()).thenReturn(true);
-        mStackScroller.updateEmptyShadeView(true);
-        verify(mEmptyShadeView).setText(R.string.dnd_suppressing_shade_text);
-    }
-
-    @Test
     @UiThreadTest
     public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
         mStackScroller.setExpandedHeight(0f);
@@ -173,7 +143,7 @@
 
         mStackScroller.updateFooterView(true, false);
 
-        verify(view).setVisibility(View.VISIBLE);
+        verify(view).performVisibilityAnimation(eq(true), any());
         verify(view).performSecondaryVisibilityAnimation(false);
     }
 
@@ -186,7 +156,7 @@
 
         mStackScroller.updateFooterView(true, true);
 
-        verify(view).setVisibility(View.VISIBLE);
+        verify(view).performVisibilityAnimation(eq(true), any());
         verify(view).performSecondaryVisibilityAnimation(true);
     }
 }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 41f413d..607db4e 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -117,10 +117,10 @@
             return (onSubscriptionsChangedListenerCallback != null);
         }
 
-        boolean canReadPhoneState() {
+        boolean canReadCallLog() {
             try {
-                return TelephonyPermissions.checkReadPhoneState(
-                        context, subId, callerPid, callerUid, callingPackage, "listen");
+                return TelephonyPermissions.checkReadCallLog(
+                        context, subId, callerPid, callerUid, callingPackage);
             } catch (SecurityException e) {
                 return false;
             }
@@ -667,8 +667,8 @@
     }
 
     private String getCallIncomingNumber(Record record, int phoneId) {
-        // Hide the number if record's process can't currently read phone state.
-        return record.canReadPhoneState() ? mCallIncomingNumber[phoneId] : "";
+        // Only reveal the incoming number if the record has read call log permission.
+        return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : "";
     }
 
     private Record add(IBinder binder) {
@@ -729,13 +729,13 @@
         }
     }
 
-    public void notifyCallState(int state, String incomingNumber) {
+    public void notifyCallState(int state, String phoneNumber) {
         if (!checkNotifyPermission("notifyCallState()")) {
             return;
         }
 
         if (VDBG) {
-            log("notifyCallState: state=" + state + " incomingNumber=" + incomingNumber);
+            log("notifyCallState: state=" + state + " phoneNumber=" + phoneNumber);
         }
 
         synchronized (mRecords) {
@@ -743,8 +743,10 @@
                 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
                         (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
                     try {
-                        String incomingNumberOrEmpty = r.canReadPhoneState() ? incomingNumber : "";
-                        r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
+                        // Ensure the listener has read call log permission; if they do not return
+                        // an empty phone number.
+                        String phoneNumberOrEmpty = r.canReadCallLog() ? phoneNumber : "";
+                        r.callback.onCallStateChanged(state, phoneNumberOrEmpty);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
                     }
@@ -755,7 +757,7 @@
 
         // Called only by Telecomm to communicate call state across different phone accounts. So
         // there is no need to add a valid subId or slotId.
-        broadcastCallStateChanged(state, incomingNumber,
+        broadcastCallStateChanged(state, phoneNumber,
                 SubscriptionManager.INVALID_PHONE_INDEX,
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
     }
@@ -1571,9 +1573,6 @@
         Intent intent = new Intent(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
         intent.putExtra(PhoneConstants.STATE_KEY,
                 PhoneConstantConversions.convertCallState(state).toString());
-        if (!TextUtils.isEmpty(incomingNumber)) {
-            intent.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
-        }
 
         // If a valid subId was specified, we should fire off a subId-specific state
         // change intent and include the subId.
@@ -1589,13 +1588,20 @@
         // Wakeup apps for the (SUBSCRIPTION_)PHONE_STATE broadcast.
         intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
 
+        Intent intentWithPhoneNumber = new Intent(intent);
+        if (!TextUtils.isEmpty(incomingNumber)) {
+            intentWithPhoneNumber.putExtra(TelephonyManager.EXTRA_INCOMING_NUMBER, incomingNumber);
+        }
         // Send broadcast twice, once for apps that have PRIVILEGED permission and once for those
         // that have the runtime one
-        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+        mContext.sendBroadcastAsUser(intentWithPhoneNumber, UserHandle.ALL,
                 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                 android.Manifest.permission.READ_PHONE_STATE,
                 AppOpsManager.OP_READ_PHONE_STATE);
+        mContext.sendBroadcastAsUserMultiplePermissions(intentWithPhoneNumber, UserHandle.ALL,
+                new String[] { android.Manifest.permission.READ_PHONE_STATE,
+                        android.Manifest.permission.READ_CALL_LOG});
     }
 
     private void broadcastDataConnectionStateChanged(int state,
diff --git a/services/core/java/com/android/server/fingerprint/ClientMonitor.java b/services/core/java/com/android/server/fingerprint/ClientMonitor.java
index 4100a9a..b935ba2 100644
--- a/services/core/java/com/android/server/fingerprint/ClientMonitor.java
+++ b/services/core/java/com/android/server/fingerprint/ClientMonitor.java
@@ -80,7 +80,7 @@
         mGroupId = groupId;
         mIsRestricted = restricted;
         mOwner = owner;
-        mSuccessVibrationEffect = getSuccessVibrationEffect(context);
+        mSuccessVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
         mErrorVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
         try {
             if (token != null) {
@@ -239,25 +239,4 @@
             vibrator.vibrate(mErrorVibrationEffect, FINGERPRINT_SONFICATION_ATTRIBUTES);
         }
     }
-
-    private static VibrationEffect getSuccessVibrationEffect(Context ctx) {
-        int[] arr = ctx.getResources().getIntArray(
-                com.android.internal.R.array.config_longPressVibePattern);
-        final long[] vibePattern;
-        if (arr == null || arr.length == 0) {
-            vibePattern = DEFAULT_SUCCESS_VIBRATION_PATTERN;
-        } else {
-            vibePattern = new long[arr.length];
-            for (int i = 0; i < arr.length; i++) {
-                vibePattern[i] = arr[i];
-            }
-        }
-        if (vibePattern.length == 1) {
-            return VibrationEffect.createOneShot(
-                    vibePattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
-        } else {
-            return VibrationEffect.createWaveform(vibePattern, -1);
-        }
-    }
-
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 32999bb..9ee28d8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3878,7 +3878,9 @@
                     for (int j = 0; j < listenerSize; j++) {
                         if (i > 0) pw.print(',');
                         final ManagedServiceInfo listener = listeners.valueAt(i);
-                        pw.print(listener.component);
+                        if (listener != null) {
+                            pw.print(listener.component);
+                        }
                     }
                 }
                 pw.println(')');
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index febce31..7f141ee 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -116,17 +116,12 @@
     private final ArrayMap<String, Record> mRecords = new ArrayMap<>(); // pkg|uid => Record
     private final ArrayMap<String, NotificationRecord> mProxyByGroupTmp = new ArrayMap<>();
     private final ArrayMap<String, Record> mRestoredWithoutUids = new ArrayMap<>(); // pkg => Record
-    private final ArrayMap<Pair<String, Integer>, Boolean> mSystemAppCache = new ArrayMap<>();
 
     private final Context mContext;
     private final RankingHandler mRankingHandler;
     private final PackageManager mPm;
     private SparseBooleanArray mBadgingEnabled;
 
-    private Signature[] mSystemSignature;
-    private String mPermissionControllerPackageName;
-    private String mServicesSystemSharedLibPackageName;
-    private String mSharedSystemSharedLibPackageName;
     private boolean mAreChannelsBypassingDnd;
     private ZenModeHelper mZenModeHelper;
 
@@ -161,7 +156,6 @@
             }
         }
 
-        getSignatures();
         updateChannelsBypassingDnd();
     }
 
@@ -623,7 +617,6 @@
         if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(channel.getId())) {
             throw new IllegalArgumentException("Reserved id");
         }
-        final boolean isSystemApp = isSystemPackage(pkg, uid);
         NotificationChannel existing = r.channels.get(channel.getId());
         // Keep most of the existing settings
         if (existing != null && fromTargetApp) {
@@ -651,7 +644,7 @@
 
             // system apps and dnd access apps can bypass dnd if the user hasn't changed any
             // fields on the channel yet
-            if (existing.getUserLockedFields() == 0 && (isSystemApp || hasDndAccess)) {
+            if (existing.getUserLockedFields() == 0 && hasDndAccess) {
                 boolean bypassDnd = channel.canBypassDnd();
                 existing.setBypassDnd(bypassDnd);
 
@@ -669,7 +662,7 @@
         }
 
         // Reset fields that apps aren't allowed to set.
-        if (fromTargetApp && !(isSystemApp || hasDndAccess)) {
+        if (fromTargetApp && !hasDndAccess) {
             channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
         }
         if (fromTargetApp) {
@@ -695,65 +688,6 @@
         channel.unlockFields(channel.getUserLockedFields());
     }
 
-    /**
-     * Determine whether a package is a "system package", in which case certain things (like
-     * bypassing DND) should be allowed.
-     */
-    private boolean isSystemPackage(String pkg, int uid) {
-        Pair<String, Integer> app = new Pair(pkg, uid);
-        if (mSystemAppCache.containsKey(app)) {
-            return mSystemAppCache.get(app);
-        }
-
-        PackageInfo pi;
-        try {
-            pi = mPm.getPackageInfoAsUser(
-                    pkg, PackageManager.GET_SIGNATURES, UserHandle.getUserId(uid));
-        } catch (NameNotFoundException e) {
-            Slog.w(TAG, "Can't find pkg", e);
-            return false;
-        }
-        boolean isSystem = (mSystemSignature[0] != null
-                && mSystemSignature[0].equals(getFirstSignature(pi)))
-                || pkg.equals(mPermissionControllerPackageName)
-                || pkg.equals(mServicesSystemSharedLibPackageName)
-                || pkg.equals(mSharedSystemSharedLibPackageName)
-                || pkg.equals(PrintManager.PRINT_SPOOLER_PACKAGE_NAME)
-                || isDeviceProvisioningPackage(pkg);
-        mSystemAppCache.put(app, isSystem);
-        return isSystem;
-    }
-
-    private Signature getFirstSignature(PackageInfo pkg) {
-        if (pkg != null && pkg.signatures != null && pkg.signatures.length > 0) {
-            return pkg.signatures[0];
-        }
-        return null;
-    }
-
-    private Signature getSystemSignature() {
-        try {
-            final PackageInfo sys = mPm.getPackageInfoAsUser(
-                    "android", PackageManager.GET_SIGNATURES, UserHandle.USER_SYSTEM);
-            return getFirstSignature(sys);
-        } catch (NameNotFoundException e) {
-        }
-        return null;
-    }
-
-    private boolean isDeviceProvisioningPackage(String packageName) {
-        String deviceProvisioningPackage = mContext.getResources().getString(
-                com.android.internal.R.string.config_deviceProvisioningPackage);
-        return deviceProvisioningPackage != null && deviceProvisioningPackage.equals(packageName);
-    }
-
-    private void getSignatures() {
-        mSystemSignature = new Signature[]{getSystemSignature()};
-        mPermissionControllerPackageName = mPm.getPermissionControllerPackageName();
-        mServicesSystemSharedLibPackageName = mPm.getServicesSystemSharedLibraryPackageName();
-        mSharedSystemSharedLibPackageName = mPm.getSharedSystemSharedLibraryPackageName();
-    }
-
     @Override
     public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel,
             boolean fromUser) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 156f702..658c7f1 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -173,18 +173,6 @@
         }
     }
 
-    public boolean shouldSuppressWhenScreenOff() {
-        synchronized (mConfig) {
-            return !mConfig.allowWhenScreenOff;
-        }
-    }
-
-    public boolean shouldSuppressWhenScreenOn() {
-        synchronized (mConfig) {
-            return !mConfig.allowWhenScreenOn;
-        }
-    }
-
     public void addCallback(Callback callback) {
         mCallbacks.add(callback);
     }
@@ -592,14 +580,12 @@
             return;
         }
         pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
-                + "messages=%b,messagesFrom=%s,"
-                + "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n",
+                + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n",
                 config.allowAlarms, config.allowMedia, config.allowSystem,
                 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
                 config.allowRepeatCallers, config.allowMessages,
                 ZenModeConfig.sourceToString(config.allowMessagesFrom),
-                config.allowEvents, config.allowReminders, config.allowWhenScreenOff,
-                config.allowWhenScreenOn);
+                config.allowEvents, config.allowReminders);
         pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
         pw.print(prefix); pw.print("  manualRule="); pw.println(config.manualRule);
         if (config.automaticRules.isEmpty()) return;
@@ -1185,7 +1171,7 @@
 
     private void showZenUpgradeNotification(int zen) {
         final boolean showNotification = mIsBootComplete
-                && zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                && zen != Global.ZEN_MODE_OFF
                 && Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0;
 
@@ -1204,17 +1190,20 @@
                 mContext.getResources().getString(R.string.global_action_settings));
         int title = R.string.zen_upgrade_notification_title;
         int content = R.string.zen_upgrade_notification_content;
+        int drawable = R.drawable.ic_zen_24dp;
         if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
                 getNotificationPolicy().suppressedVisualEffects)) {
             title = R.string.zen_upgrade_notification_visd_title;
             content = R.string.zen_upgrade_notification_visd_content;
+            drawable = R.drawable.ic_dnd_block_notifications;
         }
+
         Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
         onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
                 .setAutoCancel(true)
                 .setSmallIcon(R.drawable.ic_settings_24dp)
-                .setLargeIcon(Icon.createWithResource(mContext, R.drawable.ic_zen_24dp))
+                .setLargeIcon(Icon.createWithResource(mContext, drawable))
                 .setContentTitle(mContext.getResources().getString(title))
                 .setContentText(mContext.getResources().getString(content))
                 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
index e2ba4d5..213961c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmMockContext.java
@@ -254,6 +254,12 @@
     }
 
     @Override
+    public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+            String[] receiverPermissions) {
+        spiedContext.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions);
+    }
+
+    @Override
     public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
         spiedContext.sendBroadcast(intent, receiverPermission, options);
     }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index ac23d14..8ffec40 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2189,7 +2189,6 @@
     @Test
     public void testReadPolicyXml_readApprovedServicesFromXml() throws Exception {
         final String upgradeXml = "<notification-policy version=\"1\">"
-                + "<zen></zen>"
                 + "<ranking></ranking>"
                 + "<enabled_listeners>"
                 + "<service_listing approved=\"test\" user=\"0\" primary=\"true\" />"
@@ -2217,7 +2216,6 @@
     @Test
     public void testReadPolicyXml_readApprovedServicesFromSettings() throws Exception {
         final String preupgradeXml = "<notification-policy version=\"1\">"
-                + "<zen></zen>"
                 + "<ranking></ranking>"
                 + "</notification-policy>";
         mService.readPolicyXml(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
index 8183a74..8905950 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -1714,13 +1714,13 @@
     }
 
     @Test
-    public void testAndroidPkgCanBypassDnd_creation() {
+    public void testAndroidPkgCannotBypassDnd_creation() {
         NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
         test.setBypassDnd(true);
 
         mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false);
 
-        assertTrue(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
+        assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
                 .canBypassDnd());
     }
 
@@ -1745,7 +1745,7 @@
     }
 
     @Test
-    public void testAndroidPkgCanBypassDnd_update() throws Exception {
+    public void testAndroidPkgCannotBypassDnd_update() throws Exception {
         NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW);
         mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false);
 
@@ -1753,11 +1753,8 @@
         update.setBypassDnd(true);
         mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false);
 
-        assertTrue(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
+        assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
                 .canBypassDnd());
-
-        // setup + 1st check
-        verify(mPm, times(2)).getPackageInfoAsUser(any(), anyInt(), anyInt());
     }
 
     @Test
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 d02a983..afc1263 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -17,6 +17,9 @@
 package com.android.server.notification;
 
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
+import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertEquals;
@@ -569,8 +572,6 @@
         mZenModeHelperSpy.mConfig.allowMessages = true;
         mZenModeHelperSpy.mConfig.allowEvents = true;
         mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
-        mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
-        mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
         mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
         mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
         mZenModeHelperSpy.mConfig.manualRule.component = new ComponentName("a", "a");
@@ -593,8 +594,6 @@
         mZenModeHelperSpy.mConfig.allowMessages = true;
         mZenModeHelperSpy.mConfig.allowEvents = true;
         mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
-        mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
-        mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
         mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
         mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
         mZenModeHelperSpy.mConfig.manualRule.zenMode =
@@ -645,6 +644,115 @@
     }
 
     @Test
+    public void testMigrateSuppressedVisualEffects_oneExistsButOff() throws Exception {
+        String xml = "<zen version=\"6\" user=\"0\">\n"
+                + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+                + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+                + "visualScreenOff=\"false\" alarms=\"true\" "
+                + "media=\"true\" system=\"false\" />\n"
+                + "<disallow visualEffects=\"511\" />"
+                + "</zen>";
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.getBytes())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        assertEquals(0, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
+
+        xml = "<zen version=\"6\" user=\"0\">\n"
+                + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+                + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+                + "visualScreenOn=\"false\" alarms=\"true\" "
+                + "media=\"true\" system=\"false\" />\n"
+                + "<disallow visualEffects=\"511\" />"
+                + "</zen>";
+
+        parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.getBytes())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        assertEquals(0, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
+    }
+
+    @Test
+    public void testMigrateSuppressedVisualEffects_bothExistButOff() throws Exception {
+        String xml = "<zen version=\"6\" user=\"0\">\n"
+                + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+                + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+                + "visualScreenOff=\"false\" visualScreenOn=\"false\" alarms=\"true\" "
+                + "media=\"true\" system=\"false\" />\n"
+                + "<disallow visualEffects=\"511\" />"
+                + "</zen>";
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.getBytes())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        assertEquals(0, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
+    }
+
+    @Test
+    public void testMigrateSuppressedVisualEffects_bothExistButOn() throws Exception {
+        String xml = "<zen version=\"6\" user=\"0\">\n"
+                + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+                + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+                + "visualScreenOff=\"true\" visualScreenOn=\"true\" alarms=\"true\" "
+                + "media=\"true\" system=\"false\" />\n"
+                + "<disallow visualEffects=\"511\" />"
+                + "</zen>";
+
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.getBytes())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        assertEquals(SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
+                | SUPPRESSED_EFFECT_LIGHTS
+                | SUPPRESSED_EFFECT_PEEK,
+                mZenModeHelperSpy.mConfig.suppressedVisualEffects);
+
+        xml = "<zen version=\"6\" user=\"0\">\n"
+                + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+                + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+                + "visualScreenOff=\"false\" visualScreenOn=\"true\" alarms=\"true\" "
+                + "media=\"true\" system=\"false\" />\n"
+                + "<disallow visualEffects=\"511\" />"
+                + "</zen>";
+
+        parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.getBytes())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        assertEquals(SUPPRESSED_EFFECT_PEEK, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
+
+        xml = "<zen version=\"6\" user=\"0\">\n"
+                + "<allow calls=\"false\" repeatCallers=\"false\" messages=\"true\" "
+                + "reminders=\"false\" events=\"false\" callsFrom=\"1\" messagesFrom=\"2\" "
+                + "visualScreenOff=\"true\" visualScreenOn=\"false\" alarms=\"true\" "
+                + "media=\"true\" system=\"false\" />\n"
+                + "<disallow visualEffects=\"511\" />"
+                + "</zen>";
+
+        parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml.getBytes())), null);
+        parser.nextTag();
+        mZenModeHelperSpy.readXml(parser, false);
+
+        assertEquals(SUPPRESSED_EFFECT_FULL_SCREEN_INTENT | SUPPRESSED_EFFECT_LIGHTS,
+                mZenModeHelperSpy.mConfig.suppressedVisualEffects);
+    }
+
+    @Test
     public void testReadXmlResetDefaultRules() throws Exception {
         setupZenConfig();
 
@@ -705,16 +813,6 @@
         setupZenConfigMaintained();
     }
 
-    @Test
-    public void testPolicyReadsSuppressedEffects() {
-        mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
-        mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
-        mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
-
-        NotificationManager.Policy policy = mZenModeHelperSpy.getNotificationPolicy();
-        assertEquals(SUPPRESSED_EFFECT_BADGE, policy.suppressedVisualEffects);
-    }
-
     private void setupZenConfig() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConfig.allowAlarms = false;
@@ -725,8 +823,6 @@
         mZenModeHelperSpy.mConfig.allowMessages = true;
         mZenModeHelperSpy.mConfig.allowEvents = true;
         mZenModeHelperSpy.mConfig.allowRepeatCallers= true;
-        mZenModeHelperSpy.mConfig.allowWhenScreenOff = true;
-        mZenModeHelperSpy.mConfig.allowWhenScreenOn = true;
         mZenModeHelperSpy.mConfig.suppressedVisualEffects = SUPPRESSED_EFFECT_BADGE;
         mZenModeHelperSpy.mConfig.manualRule = new ZenModeConfig.ZenRule();
         mZenModeHelperSpy.mConfig.manualRule.zenMode =
@@ -746,8 +842,6 @@
         assertTrue(mZenModeHelperSpy.mConfig.allowMessages);
         assertTrue(mZenModeHelperSpy.mConfig.allowEvents);
         assertTrue(mZenModeHelperSpy.mConfig.allowRepeatCallers);
-        assertTrue(mZenModeHelperSpy.mConfig.allowWhenScreenOff);
-        assertTrue(mZenModeHelperSpy.mConfig.allowWhenScreenOn);
         assertEquals(SUPPRESSED_EFFECT_BADGE, mZenModeHelperSpy.mConfig.suppressedVisualEffects);
     }
 }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 88bed4e..8420165 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -453,7 +453,7 @@
      *
      * @param state call state
      * @param phoneNumber call phone number. If application does not have
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission or carrier
+     * {@link android.Manifest.permission#READ_CALL_LOG READ_CALL_LOG} permission or carrier
      * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be
      * passed as an argument.
      */
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 43ec716..512ffb1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -334,10 +334,12 @@
      *
      * <p>
      * The {@link #EXTRA_STATE} extra indicates the new call state.
-     * If the new state is RINGING, a second extra
-     * {@link #EXTRA_INCOMING_NUMBER} provides the incoming phone number as
-     * a String.
-     *
+     * If a receiving app has {@link android.Manifest.permission#READ_CALL_LOG} permission, a second
+     * extra {@link #EXTRA_INCOMING_NUMBER} provides the phone number for incoming and outoing calls
+     * as a String.  Note: If the receiving app has
+     * {@link android.Manifest.permission#READ_CALL_LOG} and
+     * {@link android.Manifest.permission#READ_PHONE_STATE} permission, it will receive the
+     * broadcast twice; one with the phone number and another without it.
      * <p class="note">
      * This was a {@link android.content.Context#sendStickyBroadcast sticky}
      * broadcast in version 1.0, but it is no longer sticky.
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index a182f2b..bbe38b7 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -15,6 +15,9 @@
  */
 package com.android.internal.telephony;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.Manifest;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -75,7 +78,7 @@
     /**
      * Check whether the app with the given pid/uid can read phone state.
      *
-    * <p>This method behaves in one of the following ways:
+     * <p>This method behaves in one of the following ways:
      * <ul>
      *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
      *       READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
@@ -132,6 +135,40 @@
     }
 
     /**
+     * Check whether the app with the given pid/uid can read the call log.
+     * @return {@code true} if the specified app has the read call log permission and AppOpp granted
+     *      to it, {@code false} otherwise.
+     */
+    public static boolean checkReadCallLog(
+            Context context, int subId, int pid, int uid, String callingPackage) {
+        return checkReadCallLog(
+                context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage);
+    }
+
+    @VisibleForTesting
+    public static boolean checkReadCallLog(
+            Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+            String callingPackage) {
+
+        if (context.checkPermission(Manifest.permission.READ_CALL_LOG, pid, uid)
+                != PERMISSION_GRANTED) {
+            // If we don't have the runtime permission, but do have carrier privileges, that
+            // suffices for being able to see the call phone numbers.
+            if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                enforceCarrierPrivilege(telephonySupplier, subId, uid, "readCallLog");
+                return true;
+            }
+            return false;
+        }
+
+        // We have READ_CALL_LOG permission, so return true as long as the AppOps bit hasn't been
+        // revoked.
+        AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        return appOps.noteOp(AppOpsManager.OP_READ_CALL_LOG, uid, callingPackage) ==
+                AppOpsManager.MODE_ALLOWED;
+    }
+
+    /**
      * Returns whether the caller can read phone numbers.
      *
      * <p>Besides apps with the ability to read phone state per {@link #checkReadPhoneState}, the
@@ -204,7 +241,7 @@
     public static void enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
             Context context, int subId, String message) {
         if (context.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) ==
-                PackageManager.PERMISSION_GRANTED) {
+                PERMISSION_GRANTED) {
             return;
         }
 
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 4dfd050..9d260eb 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -364,6 +364,13 @@
     }
 
     /** @hide */
+    @Override
+    public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+            String[] receiverPermissions) {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
     @SystemApi
     @Override
     public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index 4ca175f..6ce66f0 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -98,7 +98,7 @@
     private static final String LAUNCH_FILE = "applaunch.txt";
     private static final String TRACE_SUB_DIRECTORY = "atrace_logs";
     private static final String DEFAULT_TRACE_CATEGORIES =
-            "sched,freq,gfx,view,dalvik,webview,input,wm,disk,am,wm,binder_driver,hal";
+            "sched,freq,gfx,view,dalvik,webview,input,wm,disk,am,wm,binder_driver,hal,ss";
     private static final String DEFAULT_TRACE_BUFFER_SIZE = "20000";
     private static final String DEFAULT_TRACE_DUMP_INTERVAL = "10";
     private static final String TRIAL_LAUNCH = "TRIAL_LAUNCH";
diff --git a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
index 2166240..25bd7c0 100644
--- a/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
+++ b/tests/utils/testutils/java/com/android/internal/util/test/BroadcastInterceptingContext.java
@@ -175,6 +175,12 @@
     }
 
     @Override
+    public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
+            String[] receiverPermissions) {
+        sendBroadcast(intent);
+    }
+
+    @Override
     public void sendBroadcastAsUser(Intent intent, UserHandle user) {
         sendBroadcast(intent);
     }