Merge "Merge "Remove android.icu.... classes from light grey list" am: c6b17ad431 am: 1519c387e7 am: f82d01d16f"
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 56e6aea..64eae0c 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1462,6 +1462,7 @@
         private @UserSentiment int mUserSentiment = USER_SENTIMENT_NEUTRAL;
         private boolean mHidden;
         private boolean mAudiblyAlerted;
+        private boolean mNoisy;
         private ArrayList<Notification.Action> mSmartActions;
         private ArrayList<CharSequence> mSmartReplies;
 
@@ -1636,6 +1637,11 @@
             return mAudiblyAlerted;
         }
 
+        /** @hide */
+        public boolean isNoisy() {
+            return mNoisy;
+        }
+
         /**
          * @hide
          */
@@ -1646,7 +1652,8 @@
                 NotificationChannel channel, ArrayList<String> overridePeople,
                 ArrayList<SnoozeCriterion> snoozeCriteria, boolean showBadge,
                 int userSentiment, boolean hidden, boolean audiblyAlerted,
-                ArrayList<Notification.Action> smartActions, ArrayList<CharSequence> smartReplies) {
+                boolean noisy, ArrayList<Notification.Action> smartActions,
+                ArrayList<CharSequence> smartReplies) {
             mKey = key;
             mRank = rank;
             mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -1663,6 +1670,7 @@
             mUserSentiment = userSentiment;
             mHidden = hidden;
             mAudiblyAlerted = audiblyAlerted;
+            mNoisy = noisy;
             mSmartActions = smartActions;
             mSmartReplies = smartReplies;
         }
@@ -1715,6 +1723,7 @@
         private ArrayMap<String, Integer> mUserSentiment;
         private ArrayMap<String, Boolean> mHidden;
         private ArrayMap<String, Boolean> mAudiblyAlerted;
+        private ArrayMap<String, Boolean> mNoisy;
         private ArrayMap<String, ArrayList<Notification.Action>> mSmartActions;
         private ArrayMap<String, ArrayList<CharSequence>> mSmartReplies;
 
@@ -1746,7 +1755,8 @@
                     getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key),
                     getChannel(key), getOverridePeople(key), getSnoozeCriteria(key),
                     getShowBadge(key), getUserSentiment(key), getHidden(key),
-                    getAudiblyAlerted(key), getSmartActions(key), getSmartReplies(key));
+                    getAudiblyAlerted(key), getNoisy(key), getSmartActions(key),
+                    getSmartReplies(key));
             return rank >= 0;
         }
 
@@ -1894,6 +1904,16 @@
             return audiblyAlerted == null ? false : audiblyAlerted.booleanValue();
         }
 
+        private boolean getNoisy(String key) {
+            synchronized (this) {
+                if (mNoisy == null) {
+                    buildNoisyLocked();
+                }
+            }
+            Boolean noisy = mNoisy.get(key);
+            return noisy == null ? false : noisy.booleanValue();
+        }
+
         private ArrayList<Notification.Action> getSmartActions(String key) {
             synchronized (this) {
                 if (mSmartActions == null) {
@@ -2034,6 +2054,11 @@
         }
 
         // Locked by 'this'
+        private void buildNoisyLocked() {
+            mNoisy = buildBooleanMapFromBundle(mRankingUpdate.getNoisy());
+        }
+
+        // Locked by 'this'
         private void buildSmartActions() {
             Bundle smartActions = mRankingUpdate.getSmartActions();
             mSmartActions = new ArrayMap<>(smartActions.size());
diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java
index b561bfd..f80df93 100644
--- a/core/java/android/service/notification/NotificationRankingUpdate.java
+++ b/core/java/android/service/notification/NotificationRankingUpdate.java
@@ -40,13 +40,14 @@
     private final Bundle mSmartActions;
     private final Bundle mSmartReplies;
     private final Bundle mAudiblyAlerted;
+    private final Bundle mNoisy;
 
     public NotificationRankingUpdate(String[] keys, String[] interceptedKeys,
             Bundle visibilityOverrides, Bundle suppressedVisualEffects,
             int[] importance, Bundle explanation, Bundle overrideGroupKeys,
             Bundle channels, Bundle overridePeople, Bundle snoozeCriteria,
             Bundle showBadge, Bundle userSentiment, Bundle hidden, Bundle smartActions,
-            Bundle smartReplies, Bundle audiblyAlerted) {
+            Bundle smartReplies, Bundle audiblyAlerted, Bundle noisy) {
         mKeys = keys;
         mInterceptedKeys = interceptedKeys;
         mVisibilityOverrides = visibilityOverrides;
@@ -63,6 +64,7 @@
         mSmartActions = smartActions;
         mSmartReplies = smartReplies;
         mAudiblyAlerted = audiblyAlerted;
+        mNoisy = noisy;
     }
 
     public NotificationRankingUpdate(Parcel in) {
@@ -83,6 +85,7 @@
         mSmartActions = in.readBundle();
         mSmartReplies = in.readBundle();
         mAudiblyAlerted = in.readBundle();
+        mNoisy = in.readBundle();
     }
 
     @Override
@@ -108,6 +111,7 @@
         out.writeBundle(mSmartActions);
         out.writeBundle(mSmartReplies);
         out.writeBundle(mAudiblyAlerted);
+        out.writeBundle(mNoisy);
     }
 
     public static final Parcelable.Creator<NotificationRankingUpdate> CREATOR
@@ -184,4 +188,8 @@
     public Bundle getAudiblyAlerted() {
         return mAudiblyAlerted;
     }
+
+    public Bundle getNoisy() {
+        return mNoisy;
+    }
 }
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index f138685..c86ebe7 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -152,6 +152,13 @@
                 android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
                 style="@style/TextAppearance.NotificationInfo.Button" />
             <TextView
+                android:id="@+id/toggle_silent"
+                android:text="@string/inline_silent_button_silent"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+                style="@style/TextAppearance.NotificationInfo.Button" />
+            <TextView
                 android:id="@+id/keep"
                 android:minWidth="48dp"
                 android:text="@string/inline_keep_button"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 6f5d657..50454fc 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1540,6 +1540,12 @@
     <!-- Notification inline controls: Shown when a channel's notifications are minimized -->
     <string name="notification_channel_minimized">These notifications will be minimized</string>
 
+    <!-- Notification inline controls: Shown when a channel's notifications are silenced [CHAR_LIMIT=100] -->
+    <string name="notification_channel_silenced">These notifications will be shown silently</string>
+
+    <!-- Notification inline controls: Shown when a channel's notifications are set to alert [CHAR_LIMIT=100] -->
+    <string name="notification_channel_unsilenced">These notifications will alert you</string>
+
     <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
     <string name="inline_blocking_helper">You usually dismiss these notifications.
     \nKeep showing them?</string>
@@ -1556,6 +1562,12 @@
     <!-- Notification inline controls: minimize notifications button -->
     <string name="inline_minimize_button">Minimize</string>
 
+    <!-- Notification inline controls: show notifications silently button [CHAR_LIMIT=25] -->
+    <string name="inline_silent_button_silent">Show silently</string>
+
+    <!-- Notification inline controls: show and alert button [CHAR_LIMIT=25] -->
+    <string name="inline_silent_button_alert">Show and alert</string>
+
     <!-- Notification Inline controls: continue receiving notifications prompt, app level -->
     <string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
index b84b77c..f7c07f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationData.java
@@ -102,6 +102,8 @@
         public StatusBarNotification notification;
         public NotificationChannel channel;
         public boolean audiblyAlerted;
+        public boolean noisy;
+        public int importance;
         public StatusBarIconView icon;
         public StatusBarIconView expandedIcon;
         public ExpandableNotificationRow row; // the outer expanded view
@@ -155,6 +157,8 @@
         public void populateFromRanking(@NonNull Ranking ranking) {
             channel = ranking.getChannel();
             audiblyAlerted = ranking.audiblyAlerted();
+            noisy = ranking.isNoisy();
+            importance = ranking.getImportance();
             snoozeCriteria = ranking.getSnoozeCriteria();
             userSentiment = ranking.getUserSentiment();
             smartActions = ranking.getSmartActions() == null
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
index 28c07a3..43b5503 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationCounters.java
@@ -30,6 +30,9 @@
     /** Counter tag for when the user hits 'stop notifications' in the blocking helper. */
     public static final String BLOCKING_HELPER_STOP_NOTIFICATIONS =
             "blocking_helper_stop_notifications";
+    /** Counter tag for when the user hits 'show silently' in the blocking helper. */
+    public static final String BLOCKING_HELPER_TOGGLE_SILENT =
+            "blocking_helper_toggle_silent";
     /** Counter tag for when the user hits 'keep showing' in the blocking helper. */
     public static final String BLOCKING_HELPER_KEEP_SHOWING =
             "blocking_helper_keep_showing";
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
index 0a197da..fbe9c5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGuts.java
@@ -23,7 +23,6 @@
 import android.graphics.Canvas;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
-import androidx.annotation.Nullable;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.View;
@@ -31,6 +30,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.FrameLayout;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
@@ -98,6 +99,11 @@
          * Return whether something changed and needs to be saved, possibly requiring a bouncer.
          */
         boolean shouldBeSaved();
+
+        /**
+         * Called when the guts view has finished its close animation.
+         */
+        default void onFinishedClosing() {}
     }
 
     public interface OnGutsClosedListener {
@@ -304,7 +310,7 @@
                         x, y, r, 0);
                 a.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
                 a.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-                a.addListener(new AnimateCloseListener(this /* view */));
+                a.addListener(new AnimateCloseListener(this /* view */, mGutsContent));
                 a.start();
             } else {
                 // Fade in the blocking helper.
@@ -312,11 +318,12 @@
                         .alpha(0f)
                         .setDuration(StackStateAnimator.ANIMATION_DURATION_BLOCKING_HELPER_FADE)
                         .setInterpolator(Interpolators.ALPHA_OUT)
-                        .setListener(new AnimateCloseListener(this /* view */))
+                        .setListener(new AnimateCloseListener(this, /* view */mGutsContent))
                         .start();
             }
         } else {
             Log.w(TAG, "Failed to animate guts close");
+            mGutsContent.onFinishedClosing();
         }
     }
 
@@ -414,15 +421,18 @@
     /** Listener for animations executed in {@link #animateClose(int, int, boolean)}. */
     private static class AnimateCloseListener extends AnimatorListenerAdapter {
         final View mView;
+        private final GutsContent mGutsContent;
 
-        private AnimateCloseListener(View view) {
+        private AnimateCloseListener(View view, GutsContent gutsContent) {
             mView = view;
+            mGutsContent = gutsContent;
         }
 
         @Override
         public void onAnimationEnd(Animator animation) {
             super.onAnimationEnd(animation);
             mView.setVisibility(View.GONE);
+            mGutsContent.onFinishedClosing();
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 2499952..b838c9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -28,7 +28,6 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.net.Uri;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
@@ -46,15 +45,13 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotificationData;
 import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -298,7 +295,9 @@
                 mDeviceProvisionedController.isDeviceProvisioned(),
                 row.getIsNonblockable(),
                 isForBlockingHelper,
-                row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
+                row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
+                row.getEntry().noisy,
+                row.getEntry().importance);
 
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 903c272..522da4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -16,13 +16,18 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
+import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.app.INotificationManager;
 import android.app.Notification;
@@ -54,6 +59,7 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.logging.NotificationCounters;
 
 import java.util.List;
@@ -65,6 +71,17 @@
 public class NotificationInfo extends LinearLayout implements NotificationGuts.GutsContent {
     private static final String TAG = "InfoGuts";
 
+    @IntDef(prefix = { "SWAP_CONTENT_" }, value = {
+            SWAP_CONTENT_UNDO,
+            SWAP_CONTENT_TOGGLE_SILENT,
+            SWAP_CONTENT_BLOCK,
+    })
+    @interface SwapContentAction {}
+
+    private static final int SWAP_CONTENT_UNDO = 0;
+    private static final int SWAP_CONTENT_TOGGLE_SILENT = 1;
+    private static final int SWAP_CONTENT_BLOCK = 2;
+
     private INotificationManager mINotificationManager;
     private PackageManager mPm;
     private MetricsLogger mMetricsLogger;
@@ -74,7 +91,8 @@
     private int mAppUid;
     private int mNumUniqueChannelsInRow;
     private NotificationChannel mSingleNotificationChannel;
-    private int mStartingUserImportance;
+    private int mStartingChannelImportance;
+    private int mStartingChannelOrNotificationImportance;
     private int mChosenImportance;
     private boolean mIsSingleDefaultChannel;
     private boolean mIsNonblockable;
@@ -82,6 +100,7 @@
     private AnimatorSet mExpandAnimation;
     private boolean mIsForeground;
     private boolean mIsDeviceProvisioned;
+    private boolean mIsNoisy;
 
     private CheckSaveListener mCheckSaveListener;
     private OnSettingsClickListener mOnSettingsClickListener;
@@ -102,10 +121,22 @@
         closeControls(v);
     };
 
+    private OnClickListener mOnToggleSilent = v -> {
+        Runnable saveImportance = () -> {
+            mExitReason = NotificationCounters.BLOCKING_HELPER_TOGGLE_SILENT;
+            swapContent(SWAP_CONTENT_TOGGLE_SILENT);
+        };
+        if (mCheckSaveListener != null) {
+            mCheckSaveListener.checkSave(saveImportance, mSbn);
+        } else {
+            saveImportance.run();
+        }
+    };
+
     private OnClickListener mOnStopOrMinimizeNotifications = v -> {
         Runnable saveImportance = () -> {
             mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
-            swapContent(false);
+            swapContent(SWAP_CONTENT_BLOCK);
         };
         if (mCheckSaveListener != null) {
             mCheckSaveListener.checkSave(saveImportance, mSbn);
@@ -118,7 +149,7 @@
         // Reset exit counter that we'll log and record an undo event separately (not an exit event)
         mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
         logBlockingHelperCounter(NotificationCounters.BLOCKING_HELPER_UNDO);
-        swapContent(true);
+        swapContent(SWAP_CONTENT_UNDO);
     };
 
     public NotificationInfo(Context context, AttributeSet attrs) {
@@ -152,12 +183,15 @@
             final OnSettingsClickListener onSettingsClick,
             final OnAppSettingsClickListener onAppSettingsClick,
             boolean isDeviceProvisioned,
-            boolean isNonblockable)
+            boolean isNonblockable,
+            boolean isNoisy,
+            int importance)
             throws RemoteException {
         bindNotification(pm, iNotificationManager, pkg, notificationChannel,
                 numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
                 onAppSettingsClick, isDeviceProvisioned, isNonblockable,
-                false /* isBlockingHelper */, false /* isUserSentimentNegative */);
+                false /* isBlockingHelper */, false /* isUserSentimentNegative */, isNoisy,
+                importance);
     }
 
     public void bindNotification(
@@ -173,7 +207,9 @@
             boolean isDeviceProvisioned,
             boolean isNonblockable,
             boolean isForBlockingHelper,
-            boolean isUserSentimentNegative)
+            boolean isUserSentimentNegative,
+            boolean isNoisy,
+            int importance)
             throws RemoteException {
         mINotificationManager = iNotificationManager;
         mMetricsLogger = Dependency.get(MetricsLogger.class);
@@ -186,7 +222,10 @@
         mCheckSaveListener = checkSaveListener;
         mOnSettingsClickListener = onSettingsClick;
         mSingleNotificationChannel = notificationChannel;
-        mStartingUserImportance = mChosenImportance = mSingleNotificationChannel.getImportance();
+        int channelImportance = mSingleNotificationChannel.getImportance();
+        mStartingChannelImportance = mChosenImportance = channelImportance;
+        mStartingChannelOrNotificationImportance =
+                channelImportance == IMPORTANCE_UNSPECIFIED ? importance : channelImportance;
         mNegativeUserSentiment = isUserSentimentNegative;
         mIsNonblockable = isNonblockable;
         mIsForeground =
@@ -194,6 +233,7 @@
         mIsForBlockingHelper = isForBlockingHelper;
         mAppUid = mSbn.getUid();
         mIsDeviceProvisioned = isDeviceProvisioned;
+        mIsNoisy = isNoisy;
 
         int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
                 pkg, mAppUid, false /* includeDeleted */);
@@ -306,7 +346,8 @@
     }
 
     private boolean hasImportanceChanged() {
-        return mSingleNotificationChannel != null && mStartingUserImportance != mChosenImportance;
+        return mSingleNotificationChannel != null
+                && mStartingChannelImportance != mChosenImportance;
     }
 
     private void saveImportance() {
@@ -320,34 +361,46 @@
      */
     private void updateImportance() {
         MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
-                mChosenImportance - mStartingUserImportance);
+                mChosenImportance - mStartingChannelImportance);
 
         Handler bgHandler = new Handler(Dependency.get(Dependency.BG_LOOPER));
         bgHandler.post(new UpdateImportanceRunnable(mINotificationManager, mPackageName, mAppUid,
                 mNumUniqueChannelsInRow == 1 ? mSingleNotificationChannel : null,
-                mStartingUserImportance, mChosenImportance));
+                mStartingChannelImportance, mChosenImportance));
     }
 
     private void bindButtons() {
         // Set up stay-in-notification actions
         View block =  findViewById(R.id.block);
         TextView keep = findViewById(R.id.keep);
+        TextView silent = findViewById(R.id.toggle_silent);
         View minimize = findViewById(R.id.minimize);
 
         findViewById(R.id.undo).setOnClickListener(mOnUndo);
         block.setOnClickListener(mOnStopOrMinimizeNotifications);
         keep.setOnClickListener(mOnKeepShowing);
+        silent.setOnClickListener(mOnToggleSilent);
         minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
 
         if (mIsNonblockable) {
             keep.setText(android.R.string.ok);
             block.setVisibility(GONE);
+            silent.setVisibility(GONE);
             minimize.setVisibility(GONE);
         } else if (mIsForeground) {
             block.setVisibility(GONE);
+            silent.setVisibility(GONE);
             minimize.setVisibility(VISIBLE);
-        } else if (!mIsForeground) {
+        } else {
             block.setVisibility(VISIBLE);
+            boolean showToggleSilent = mIsNoisy
+                    && NotificationUtils.useNewInterruptionModel(mContext);
+            silent.setVisibility(showToggleSilent ? VISIBLE : GONE);
+            boolean isCurrentlyAlerting =
+                    mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT;
+            silent.setText(isCurrentlyAlerting
+                    ? R.string.inline_silent_button_silent
+                    : R.string.inline_silent_button_alert);
             minimize.setVisibility(GONE);
         }
 
@@ -368,7 +421,7 @@
         }
     }
 
-    private void swapContent(boolean showPrompt) {
+    private void swapContent(@SwapContentAction int action) {
         if (mExpandAnimation != null) {
             mExpandAnimation.cancel();
         }
@@ -378,26 +431,43 @@
         TextView confirmationText = findViewById(R.id.confirmation_text);
         View header = findViewById(R.id.header);
 
-        if (showPrompt) {
-            mChosenImportance = mStartingUserImportance;
-        } else if (mIsForeground) {
-            mChosenImportance = IMPORTANCE_MIN;
-            confirmationText.setText(R.string.notification_channel_minimized);
-        } else {
-            mChosenImportance = IMPORTANCE_NONE;
-            confirmationText.setText(R.string.notification_channel_disabled);
+        switch (action) {
+            case SWAP_CONTENT_UNDO:
+                mChosenImportance = mStartingChannelImportance;
+                break;
+            case SWAP_CONTENT_TOGGLE_SILENT:
+                if (mStartingChannelOrNotificationImportance >= IMPORTANCE_DEFAULT) {
+                    mChosenImportance = IMPORTANCE_LOW;
+                    confirmationText.setText(R.string.notification_channel_silenced);
+                } else {
+                    mChosenImportance = IMPORTANCE_HIGH;
+                    confirmationText.setText(R.string.notification_channel_unsilenced);
+                }
+                break;
+            case SWAP_CONTENT_BLOCK:
+                if (mIsForeground) {
+                    mChosenImportance = IMPORTANCE_MIN;
+                    confirmationText.setText(R.string.notification_channel_minimized);
+                } else {
+                    mChosenImportance = IMPORTANCE_NONE;
+                    confirmationText.setText(R.string.notification_channel_disabled);
+                }
+                break;
+            default:
+                throw new IllegalArgumentException();
         }
 
+        boolean isUndo = action == SWAP_CONTENT_UNDO;
         ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
-                prompt.getAlpha(), showPrompt ? 1f : 0f);
-        promptAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
+                prompt.getAlpha(), isUndo ? 1f : 0f);
+        promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
         ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
-                confirmation.getAlpha(), showPrompt ? 0f : 1f);
-        confirmAnim.setInterpolator(showPrompt ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
+                confirmation.getAlpha(), isUndo ? 0f : 1f);
+        confirmAnim.setInterpolator(isUndo ? Interpolators.ALPHA_OUT : Interpolators.ALPHA_IN);
 
-        prompt.setVisibility(showPrompt ? VISIBLE : GONE);
-        confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
-        header.setVisibility(showPrompt ? VISIBLE : GONE);
+        prompt.setVisibility(isUndo ? VISIBLE : GONE);
+        confirmation.setVisibility(isUndo ? GONE : VISIBLE);
+        header.setVisibility(isUndo ? VISIBLE : GONE);
 
         mExpandAnimation = new AnimatorSet();
         mExpandAnimation.playTogether(promptAnim, confirmAnim);
@@ -413,8 +483,8 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 if (!cancelled) {
-                    prompt.setVisibility(showPrompt ? VISIBLE : GONE);
-                    confirmation.setVisibility(showPrompt ? GONE : VISIBLE);
+                    prompt.setVisibility(isUndo ? VISIBLE : GONE);
+                    confirmation.setVisibility(isUndo ? GONE : VISIBLE);
                 }
             }
         });
@@ -428,6 +498,25 @@
     }
 
     @Override
+    public void onFinishedClosing() {
+        mStartingChannelImportance = mChosenImportance;
+        if (mChosenImportance != IMPORTANCE_UNSPECIFIED) {
+            mStartingChannelOrNotificationImportance = mChosenImportance;
+        }
+        mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
+
+        View prompt = findViewById(R.id.prompt);
+        ViewGroup confirmation = findViewById(R.id.confirmation);
+        View header = findViewById(R.id.header);
+        prompt.setVisibility(VISIBLE);
+        prompt.setAlpha(1f);
+        confirmation.setVisibility(GONE);
+        confirmation.setAlpha(1f);
+        header.setVisibility(VISIBLE);
+        header.setAlpha(1f);
+    }
+
+    @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         if (mGutsContainer != null &&
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index c3bf16e..a315bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1124,7 +1124,7 @@
      */
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getExpandTranslationStart() {
-        return -mTopPadding + getMinExpansionHeight();
+        return -mTopPadding + getMinExpansionHeight() - mShelf.getIntrinsicHeight();
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
index 0251f64..8e6bfe3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationDataTest.java
@@ -437,15 +437,15 @@
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
                         outRanking.canShowBadge(), outRanking.getUserSentiment(), true,
-                        false, null, null);
+                        false, false, null, null);
             } else if (key.equals(TEST_EXEMPT_DND_VISUAL_SUPPRESSION_KEY)) {
                 outRanking.populate(key, outRanking.getRank(),
                         outRanking.matchesInterruptionFilter(),
                         outRanking.getVisibilityOverride(), 255,
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), outRanking.getChannel(), null, null,
-                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true, false, null,
-                        null);
+                        outRanking.canShowBadge(), outRanking.getUserSentiment(), true, false,
+                        false, null, null);
             } else {
                 outRanking.populate(key, outRanking.getRank(),
                         outRanking.matchesInterruptionFilter(),
@@ -453,8 +453,7 @@
                         outRanking.getImportance(), outRanking.getImportanceExplanation(),
                         outRanking.getOverrideGroupKey(), NOTIFICATION_CHANNEL, null, null,
                         outRanking.canShowBadge(), outRanking.getUserSentiment(), false, false,
-                        null,
-                        null);
+                        false, null, null);
             }
             return true;
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 9c68e7d..9f8a5cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -167,7 +167,7 @@
                     0,
                     NotificationManager.IMPORTANCE_DEFAULT,
                     null, null,
-                    null, null, null, true, sentiment, false, false, null, null);
+                    null, null, null, true, sentiment, false, false, false, null, null);
             return true;
         }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
     }
@@ -186,7 +186,7 @@
                     null, null,
                     null, null, null, true,
                     NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false, false,
-                    smartActions, null);
+                    false, smartActions, null);
             return true;
         }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index ee35449..626726d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -19,8 +19,10 @@
 import static android.app.AppOpsManager.OP_CAMERA;
 import static android.app.AppOpsManager.OP_RECORD_AUDIO;
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.service.notification.NotificationListenerService.Ranking
+        .USER_SENTIMENT_NEGATIVE;
 
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
@@ -34,15 +36,14 @@
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.app.INotificationManager;
 import android.app.Notification;
 import android.app.NotificationChannel;
-import android.app.NotificationManager;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -57,11 +58,12 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationData;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
+import com.android.systemui.statusbar.notification.NotificationData;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+        .OnSettingsClickListener;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
@@ -71,8 +73,8 @@
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
-import org.mockito.junit.MockitoRule;
 import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 /**
  * Tests for {@link NotificationGutsManager}.
@@ -84,7 +86,7 @@
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
 
     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
-            TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
+            TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
     private TestableLooper mTestableLooper;
     private Handler mHandler;
     private NotificationTestHelper mHelper;
@@ -297,7 +299,9 @@
                 eq(false),
                 eq(false),
                 eq(true) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(0));
     }
 
     @Test
@@ -324,7 +328,69 @@
                 eq(false),
                 eq(false),
                 eq(false) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(0));
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_noisy() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(true);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        row.getEntry().noisy = true;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(false),
+                eq(false),
+                eq(true) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */,
+                eq(true) /*isNoisy */,
+                eq(0));
+    }
+
+    @Test
+    public void testInitializeNotificationInfoView_importance() throws Exception {
+        NotificationInfo notificationInfoView = mock(NotificationInfo.class);
+        ExpandableNotificationRow row = spy(mHelper.createRow());
+        row.setBlockingHelperShowing(true);
+        row.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+        row.getEntry().importance = IMPORTANCE_DEFAULT;
+        when(row.getIsNonblockable()).thenReturn(false);
+        StatusBarNotification statusBarNotification = row.getStatusBarNotification();
+
+        mGutsManager.initializeNotificationInfo(row, notificationInfoView);
+
+        verify(notificationInfoView).bindNotification(
+                any(PackageManager.class),
+                any(INotificationManager.class),
+                eq(statusBarNotification.getPackageName()),
+                any(NotificationChannel.class),
+                anyInt(),
+                eq(statusBarNotification),
+                any(NotificationInfo.CheckSaveListener.class),
+                any(NotificationInfo.OnSettingsClickListener.class),
+                any(NotificationInfo.OnAppSettingsClickListener.class),
+                eq(false),
+                eq(false),
+                eq(true) /* isForBlockingHelper */,
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(IMPORTANCE_DEFAULT));
     }
 
     @Test
@@ -352,7 +418,9 @@
                 eq(true),
                 eq(false),
                 eq(false) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */);
+                eq(true) /* isUserSentimentNegative */,
+                eq(false) /*isNoisy */,
+                eq(0));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index ca968a8..3744196 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -17,11 +17,14 @@
 package com.android.systemui.statusbar.notification.row;
 
 import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
+import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
@@ -56,6 +59,7 @@
 import android.graphics.drawable.Drawable;
 import android.os.IBinder;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -72,6 +76,7 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -150,6 +155,15 @@
                 IMPORTANCE_LOW);
         mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
                 new Notification(), UserHandle.CURRENT, null, 0);
+
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, 1);
+    }
+
+    @After
+    public void tearDown() {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
     }
 
     // TODO: if tests are taking too long replace this with something that makes the animation
@@ -172,7 +186,8 @@
     public void testBindNotification_SetsTextApplicationName() throws Exception {
         when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
         assertTrue(textView.getText().toString().contains("App Name"));
         assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
@@ -184,7 +199,8 @@
         when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
                 .thenReturn(iconDrawable);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
         assertEquals(iconDrawable, iconView.getDrawable());
     }
@@ -192,7 +208,8 @@
     @Test
     public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(GONE, groupNameView.getVisibility());
         final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
@@ -208,7 +225,8 @@
                 eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
                 .thenReturn(notificationChannelGroup);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
         assertEquals(View.VISIBLE, groupNameView.getVisibility());
         assertEquals("Test Group Name", groupNameView.getText());
@@ -219,7 +237,8 @@
     @Test
     public void testBindNotification_SetsTextChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(TEST_CHANNEL_NAME, textView.getText());
     }
@@ -228,7 +247,7 @@
     public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
-                false);
+                false, false, IMPORTANCE_DEFAULT);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(GONE, textView.getVisibility());
     }
@@ -241,7 +260,7 @@
                 eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, true,
-                false);
+                false, false, IMPORTANCE_DEFAULT);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(VISIBLE, textView.getVisibility());
     }
@@ -249,7 +268,8 @@
     @Test
     public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
         final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(VISIBLE, textView.getVisibility());
     }
@@ -257,18 +277,71 @@
     @Test
     public void testBindNotification_BlockButton() throws Exception {
        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+               TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+               false, IMPORTANCE_DEFAULT);
         final View block = mNotificationInfo.findViewById(R.id.block);
+        final View toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
         final View minimize = mNotificationInfo.findViewById(R.id.minimize);
         assertEquals(VISIBLE, block.getVisibility());
+        assertEquals(GONE, toggleSilent.getVisibility());
         assertEquals(GONE, minimize.getVisibility());
     }
 
     @Test
+    public void testBindNotification_SilenceButton() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+    }
+
+    @Test
+    public void testBindNotification_UnSilenceButton() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_LOW);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+    }
+
+    @Test
+    public void testBindNotification_SilenceButton_ChannelImportanceUnspecified() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_silent), toggleSilent.getText());
+    }
+
+    @Test
+    public void testBindNotification_UnSilenceButton_ChannelImportanceUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_LOW);
+        final TextView toggleSilent = mNotificationInfo.findViewById(R.id.toggle_silent);
+        assertEquals(VISIBLE, toggleSilent.getVisibility());
+        assertEquals(
+                mContext.getString(R.string.inline_silent_button_alert), toggleSilent.getText());
+    }
+
+    @Test
     public void testBindNotification_MinButton() throws Exception {
         mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final View block = mNotificationInfo.findViewById(R.id.block);
         final View minimize = mNotificationInfo.findViewById(R.id.minimize);
         assertEquals(GONE, block.getVisibility());
@@ -283,7 +356,7 @@
                 (View v, NotificationChannel c, int appUid) -> {
                     assertEquals(mNotificationChannel, c);
                     latch.countDown();
-                }, null, true, false);
+                }, null, true, false, false, IMPORTANCE_DEFAULT);
 
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         settingsButton.performClick();
@@ -294,7 +367,8 @@
     @Test
     public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -306,7 +380,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
                 (View v, NotificationChannel c, int appUid) -> {
                     assertEquals(mNotificationChannel, c);
-                }, null, false, false);
+                }, null, false, false, false, IMPORTANCE_DEFAULT);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertTrue(settingsButton.getVisibility() != View.VISIBLE);
     }
@@ -314,11 +388,12 @@
     @Test
     public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
                 (View v, NotificationChannel c, int appUid) -> {
-                }, null, true, false);
+                }, null, true, false, false, IMPORTANCE_DEFAULT);
         final View settingsButton = mNotificationInfo.findViewById(R.id.info);
         assertEquals(View.VISIBLE, settingsButton.getVisibility());
     }
@@ -326,7 +401,8 @@
     @Test
     public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
         verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
     }
@@ -335,7 +411,7 @@
     public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
-                true, true);
+                true, true, false, IMPORTANCE_DEFAULT);
         mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
         verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
     }
@@ -348,7 +424,7 @@
                 (View v, NotificationChannel c, int appUid) -> {
                     assertEquals(null, c);
                     latch.countDown();
-                }, null, true, true);
+                }, null, true, true, false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.info).performClick();
         // Verify that listener was triggered.
@@ -361,7 +437,7 @@
             throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true, true);
+                null, true, true, false, IMPORTANCE_DEFAULT);
         final TextView channelNameView =
                 mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(GONE, channelNameView.getVisibility());
@@ -372,7 +448,7 @@
     public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true, true);
+                null, true, true, false, IMPORTANCE_DEFAULT);
         final TextView blockView = mNotificationInfo.findViewById(R.id.block);
         assertEquals(GONE, blockView.getVisibility());
     }
@@ -381,7 +457,7 @@
     public void testbindNotification_BlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
-                true, true);
+                true, true, false, IMPORTANCE_DEFAULT);
         final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
         assertEquals(View.VISIBLE, view.getVisibility());
         assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
@@ -390,7 +466,8 @@
     @Test
     public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
         final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
         assertEquals(View.VISIBLE, view.getVisibility());
         assertEquals(mContext.getString(R.string.notification_unblockable_desc),
@@ -400,7 +477,8 @@
     @Test
     public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
@@ -410,7 +488,8 @@
     public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -423,7 +502,8 @@
             throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         mTestableLooper.processAllMessages();
@@ -432,11 +512,40 @@
     }
 
     @Test
+    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedSilenced()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
+    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedUnSilenced()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        mTestableLooper.processAllMessages();
+        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), any());
+    }
+
+    @Test
     public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
             throws Exception {
         int originalImportance = mNotificationChannel.getImportance();
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.handleCloseControls(true, false);
         mTestableLooper.processAllMessages();
@@ -450,7 +559,8 @@
             throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -468,7 +578,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                true, false /* isNonblockable */);
+                true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -489,7 +599,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
                 10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */ ,
-                true, false /* isNonblockable */);
+                true, false /* isNonblockable */, false, /* isNoisy */IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -510,7 +620,7 @@
                 null /* onSettingsClick */, null /* onAppSettingsClick */ ,
                 true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
 
         NotificationGuts guts = spy(new NotificationGuts(mContext, null));
         when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -538,7 +648,7 @@
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */ , true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
 
         NotificationGuts guts = spy(new NotificationGuts(mContext, null));
         when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -566,7 +676,8 @@
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */ ,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true, true /* isUserSentimentNegative */);
+                true, true /* isUserSentimentNegative */, false, /* isNoisy */
+                IMPORTANCE_DEFAULT);
 
         mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
 
@@ -585,7 +696,7 @@
                 null /* onSettingsClick */, null /* onAppSettingsClick */,
                 true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */, false, /* isNoisy */IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -607,7 +718,8 @@
                 false /* isNonblockable */,
                 true /* isForBlockingHelper */,
                 true,
-                false /* isUserSentimentNegative */);
+                false /* isUserSentimentNegative */,
+                false, /* isNoisy */IMPORTANCE_DEFAULT);
         NotificationGuts guts = mock(NotificationGuts.class);
         doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
         mNotificationInfo.setGutsParent(guts);
@@ -621,7 +733,8 @@
     public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
 
@@ -634,7 +747,8 @@
     public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -666,7 +780,8 @@
                 true /*provisioned */,
                 false /* isNonblockable */,
                 true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */);
+                true /* isUserSentimentNegative */,
+                false, /* isNoisy */IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -687,7 +802,8 @@
     public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
 
@@ -701,7 +817,8 @@
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -721,7 +838,8 @@
     public void testKeepUpdatesNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.handleCloseControls(true, false);
 
@@ -738,7 +856,8 @@
     public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -759,7 +878,8 @@
     public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -777,10 +897,97 @@
     }
 
     @Test
+    public void testSilenceCallsUpdateNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testUnSilenceCallsUpdateNotificationChannel() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                true, IMPORTANCE_DEFAULT);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance());
+    }
+
+    @Test
+    public void testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()
+            throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
+                false, IMPORTANCE_LOW);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue((updated.getValue().getUserLockedFields()
+                & USER_LOCKED_IMPORTANCE) != 0);
+        assertEquals(IMPORTANCE_HIGH, updated.getValue().getImportance());
+    }
+
+    @Test
     public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -795,7 +1002,8 @@
     public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -812,7 +1020,7 @@
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
                 (Runnable saveImportance, StatusBarNotification sbn) -> {
-                }, null, null, true, true);
+                }, null, null, true, true, false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -830,7 +1038,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
                 (Runnable saveImportance, StatusBarNotification sbn) -> {
                     saveImportance.run();
-                }, null, null, true, false);
+                }, null, null, true, false, false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         mTestableLooper.processAllMessages();
@@ -866,7 +1074,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
                 (View v, Intent intent) -> {
                     latch.countDown();
-                }, true, false);
+                }, true, false, false, IMPORTANCE_DEFAULT);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(View.VISIBLE, settingsLink.getVisibility());
         settingsLink.performClick();
@@ -894,7 +1102,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
                 (View v, Intent intent) -> {
                     latch.countDown();
-                }, true, false);
+                }, true, false, false, IMPORTANCE_DEFAULT);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(View.VISIBLE, settingsLink.getVisibility());
         settingsLink.performClick();
@@ -913,7 +1121,7 @@
 
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
-                null, true, false);
+                null, true, false, false, IMPORTANCE_DEFAULT);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(GONE, settingsLink.getVisibility());
     }
@@ -933,7 +1141,8 @@
                 0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
 
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, true, false,
+                false, IMPORTANCE_DEFAULT);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(GONE, settingsLink.getVisibility());
     }
@@ -956,7 +1165,7 @@
 
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
-                true, true);
+                true, true, false, IMPORTANCE_DEFAULT);
         final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
         assertEquals(GONE, settingsLink.getVisibility());
     }
@@ -972,7 +1181,8 @@
         mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.minimize).performClick();
         waitForUndoButton();
@@ -984,7 +1194,8 @@
     public void testUndoText_block() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -993,10 +1204,39 @@
     }
 
     @Test
+    public void testUndoText_silence() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                true, IMPORTANCE_DEFAULT);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+        assertEquals(mContext.getString(R.string.notification_channel_silenced),
+                confirmationText.getText());
+    }
+
+    @Test
+    public void testUndoText_unsilence() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_LOW);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                true, IMPORTANCE_DEFAULT);
+
+        mNotificationInfo.findViewById(R.id.toggle_silent).performClick();
+        waitForUndoButton();
+        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
+        assertEquals(mContext.getString(R.string.notification_channel_unsilenced),
+                confirmationText.getText());
+    }
+
+    @Test
     public void testNoHeaderOnConfirmation() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
@@ -1007,7 +1247,8 @@
     public void testHeaderOnUndo() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                false, IMPORTANCE_DEFAULT);
 
         mNotificationInfo.findViewById(R.id.block).performClick();
         waitForUndoButton();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f87a5f7..b404c41 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -6564,6 +6564,7 @@
         Bundle smartActions = new Bundle();
         Bundle smartReplies = new Bundle();
         Bundle audiblyAlerted = new Bundle();
+        Bundle noisy = new Bundle();
         for (int i = 0; i < N; i++) {
             NotificationRecord record = mNotificationList.get(i);
             if (!isVisibleToListener(record.sbn, info)) {
@@ -6594,6 +6595,7 @@
             smartActions.putParcelableArrayList(key, record.getSmartActions());
             smartReplies.putCharSequenceArrayList(key, record.getSmartReplies());
             audiblyAlerted.putBoolean(key, record.getAudiblyAlerted());
+            noisy.putBoolean(key, record.getSound() != null || record.getVibration() != null);
         }
         final int M = keys.size();
         String[] keysAr = keys.toArray(new String[M]);
@@ -6605,7 +6607,7 @@
         return new NotificationRankingUpdate(keysAr, interceptedKeysAr, visibilityOverrides,
                 suppressedVisualEffects, importanceAr, explanation, overrideGroupKeys,
                 channels, overridePeople, snoozeCriteria, showBadge, userSentiment, hidden,
-                smartActions, smartReplies, audiblyAlerted);
+                smartActions, smartReplies, audiblyAlerted, noisy);
     }
 
     boolean hasCompanionDevice(ManagedServiceInfo info) {
diff --git a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
index e62e07d..6b7634d 100644
--- a/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobSetTest.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.os.Build;
 import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -47,6 +48,7 @@
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
+@Presubmit
 public class JobSetTest {
     private static final String TAG = JobSetTest.class.getSimpleName();
     private static final int SECONDARY_USER_ID_1 = 12;
@@ -64,6 +66,7 @@
         final PackageManagerInternal pm = mock(PackageManagerInternal.class);
         when(pm.getPackageTargetSdkVersion(anyString()))
                 .thenReturn(Build.VERSION_CODES.CUR_DEVELOPMENT);
+        LocalServices.removeServiceForTest(PackageManagerInternal.class);
         LocalServices.addService(PackageManagerInternal.class, pm);
         assumeFalse("Test cannot run in user " + mContext.getUserId(),
                 mContext.getUserId() == SECONDARY_USER_ID_1
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
index 0d7b584..bcba15d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenerServiceTest.java
@@ -114,6 +114,7 @@
         Bundle smartActions = new Bundle();
         Bundle smartReplies = new Bundle();
         Bundle audiblyAlerted = new Bundle();
+        Bundle noisy = new Bundle();
 
         for (int i = 0; i < mKeys.length; i++) {
             String key = mKeys[i];
@@ -134,12 +135,13 @@
             smartActions.putParcelableArrayList(key, getSmartActions(key, i));
             smartReplies.putCharSequenceArrayList(key, getSmartReplies(key, i));
             audiblyAlerted.putBoolean(key, audiblyAlerted(i));
+            noisy.putBoolean(key, getNoisy(i));
         }
         NotificationRankingUpdate update = new NotificationRankingUpdate(mKeys,
                 interceptedKeys.toArray(new String[0]), visibilityOverrides,
                 suppressedVisualEffects, importance, explanation, overrideGroupKeys,
                 channels, overridePeople, snoozeCriteria, showBadge, userSentiment, mHidden,
-                smartActions, smartReplies, audiblyAlerted);
+                smartActions, smartReplies, audiblyAlerted, noisy);
         return update;
     }
 
@@ -195,6 +197,10 @@
         return index < 2;
     }
 
+    private boolean getNoisy(int index) {
+        return index < 1;
+    }
+
     private ArrayList<String> getPeople(String key, int index) {
         ArrayList<String> people = new ArrayList<>();
         for (int i = 0; i < index; i++) {