Merge "Show system notifications when DnD is enabled" into tm-dev
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 4fc347a..aedbd1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -158,13 +158,6 @@
     private long initializationTime = -1;
 
     /**
-     * Whether or not this row represents a system notification. Note that if this is
-     * {@code null}, that means we were either unable to retrieve the info or have yet to
-     * retrieve the info.
-     */
-    public Boolean mIsSystemNotification;
-
-    /**
      * Has the user sent a reply through this Notification.
      */
     private boolean hasSentReply;
@@ -777,12 +770,28 @@
         if (mSbn.getNotification().isMediaNotification()) {
             return true;
         }
-        if (mIsSystemNotification != null && mIsSystemNotification) {
+        if (!isBlockable()) {
             return true;
         }
         return false;
     }
 
+    /**
+     * Returns whether this row is considered blockable (i.e. it's not a system notif
+     * or is not in an allowList).
+     */
+    public boolean isBlockable() {
+        if (getChannel() == null) {
+            return false;
+        }
+        if (getChannel().isImportanceLockedByCriticalDeviceFunction()
+                && !getChannel().isBlockable()) {
+            return false;
+        }
+
+        return true;
+    }
+
     private boolean shouldSuppressVisualEffect(int effect) {
         if (isExemptFromDndVisualSuppression()) {
             return false;
@@ -858,15 +867,6 @@
     }
 
     /**
-     * Whether or not this row represents a system notification. Note that if this is
-     * {@code null}, that means we were either unable to retrieve the info or have yet to
-     * retrieve the info.
-     */
-    public Boolean isSystemNotification() {
-        return mIsSystemNotification;
-    }
-
-    /**
      * Set this notification to be sensitive.
      *
      * @param sensitive true if the content of this notification is sensitive right now
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 7c206eb..eb496ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -513,16 +513,10 @@
      * or is in an allowList).
      */
     public boolean getIsNonblockable() {
-        if (mEntry == null || mEntry.getChannel() == null) {
-            Log.w(TAG, "missing entry or channel");
+        if (mEntry == null) {
             return true;
         }
-        if (mEntry.getChannel().isImportanceLockedByCriticalDeviceFunction()
-                && !mEntry.getChannel().isBlockable()) {
-            return true;
-        }
-
-        return false;
+        return !mEntry.isBlockable();
     }
 
     private boolean isConversation() {
@@ -1669,6 +1663,11 @@
         }
     }
 
+    @VisibleForTesting
+    protected void setEntry(NotificationEntry entry) {
+        mEntry = entry;
+    }
+
     private final Runnable mExpireRecentlyAlertedFlag = () -> applyAudiblyAlertedRecently(false);
 
     private void applyAudiblyAlertedRecently(boolean audiblyAlertedRecently) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
index 5804ad4..769143d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationEntryTest.java
@@ -29,6 +29,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
 import android.app.ActivityManager;
@@ -57,6 +58,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 
 import java.util.ArrayList;
 
@@ -72,6 +74,7 @@
     private int mId;
 
     private NotificationEntry mEntry;
+    private NotificationChannel mChannel = Mockito.mock(NotificationChannel.class);
     private final FakeSystemClock mClock = new FakeSystemClock();
 
     @Before
@@ -85,10 +88,13 @@
                 .setPkg(TEST_PACKAGE_NAME)
                 .setOpPkg(TEST_PACKAGE_NAME)
                 .setUid(TEST_UID)
+                .setChannel(mChannel)
                 .setId(mId++)
                 .setNotification(n.build())
                 .setUser(new UserHandle(ActivityManager.getCurrentUser()))
                 .build();
+
+        doReturn(false).when(mChannel).isBlockable();
     }
 
     @Test
@@ -100,6 +106,44 @@
     }
 
     @Test
+    public void testBlockableEntryWhenCritical() {
+        doReturn(true).when(mChannel).isBlockable();
+
+        assertTrue(mEntry.isBlockable());
+    }
+
+
+    @Test
+    public void testBlockableEntryWhenCriticalAndChannelNotBlockable() {
+        doReturn(true).when(mChannel).isBlockable();
+        doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+
+        assertTrue(mEntry.isBlockable());
+    }
+
+    @Test
+    public void testNonBlockableEntryWhenCriticalAndChannelNotBlockable() {
+        doReturn(false).when(mChannel).isBlockable();
+        doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+
+        assertFalse(mEntry.isBlockable());
+    }
+
+    @Test
+    public void testBlockableWhenEntryHasNoChannel() {
+        StatusBarNotification sbn = new SbnBuilder().build();
+        Ranking ranking = new RankingBuilder()
+                .setChannel(null)
+                .setKey(sbn.getKey())
+                .build();
+
+        NotificationEntry entry =
+                new NotificationEntry(sbn, ranking, mClock.uptimeMillis());
+
+        assertFalse(entry.isBlockable());
+    }
+
+    @Test
     public void testIsExemptFromDndVisualSuppression_media() {
         Notification.Builder n = new Notification.Builder(mContext, "")
                 .setStyle(new Notification.MediaStyle()
@@ -117,7 +161,8 @@
 
     @Test
     public void testIsExemptFromDndVisualSuppression_system() {
-        mEntry.mIsSystemNotification = true;
+        doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
+        doReturn(false).when(mChannel).isBlockable();
 
         assertTrue(mEntry.isExemptFromDndVisualSuppression());
         assertFalse(mEntry.shouldSuppressAmbient());
@@ -128,7 +173,7 @@
         NotificationEntry entry = new NotificationEntryBuilder()
                 .setUid(UID_NORMAL)
                 .build();
-        entry.mIsSystemNotification = true;
+        doReturn(true).when(mChannel).isImportanceLockedByCriticalDeviceFunction();
         modifyRanking(entry).setSuppressedVisualEffects(SUPPRESSED_EFFECT_AMBIENT).build();
 
         modifySbn(entry)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index f4d8405..15c1cb7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
 
@@ -30,6 +31,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.testing.AndroidTestingRunner;
 
@@ -185,7 +187,7 @@
 
         // WHEN it's not dozing (showing the notification list)
         when(mStatusBarStateController.isDozing()).thenReturn(false);
-
+        
         // THEN filter out the notification
         assertTrue(mCapturedDozingFilter.shouldFilterOut(mEntry, 0));
     }
@@ -277,6 +279,7 @@
 
     private RankingBuilder getRankingForUnfilteredNotif() {
         return new RankingBuilder(mEntry.getRanking())
+                .setChannel(new NotificationChannel("id", null, IMPORTANCE_DEFAULT))
                 .setSuppressedVisualEffects(0)
                 .setSuspended(false);
     }
@@ -292,7 +295,7 @@
         mEntry.setRanking(new RankingBuilder(mEntry.getRanking())
                 .setImportance(ambient
                         ? NotificationManager.IMPORTANCE_MIN
-                        : NotificationManager.IMPORTANCE_DEFAULT)
+                        : IMPORTANCE_DEFAULT)
                 .build());
         assertEquals(ambient, mEntry.getRanking().isAmbient());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
index 8a2dc26..90627cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptStateProviderImplTest.java
@@ -36,6 +36,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
@@ -529,6 +530,7 @@
                 .setPkg("a")
                 .setOpPkg("a")
                 .setTag("a")
+                .setChannel(new NotificationChannel("a", null, importance))
                 .setNotification(n)
                 .setImportance(importance)
                 .build();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index c36737c..b1bf971 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -58,6 +58,7 @@
 import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
 import com.android.systemui.statusbar.notification.FeedbackIcon;
 import com.android.systemui.statusbar.notification.row.ExpandableView.OnHeightChangedListener;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
 
 import org.junit.Assert;
@@ -65,6 +66,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mockito;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
 
@@ -412,27 +414,15 @@
     public void testGetIsNonblockable() throws Exception {
         ExpandableNotificationRow row =
                 mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
-
-        assertFalse(row.getIsNonblockable());
-    }
-
-    @Test
-    public void testGetIsNonblockable_criticalDeviceFunction() throws Exception {
-        ExpandableNotificationRow row =
-                mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
-        row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
-        row.getEntry().getChannel().setBlockable(false);
+        row.setEntry(null);
 
         assertTrue(row.getIsNonblockable());
-    }
 
-    @Test
-    public void testGetIsNonblockable_criticalDeviceFunction_butBlockable() throws Exception {
-        ExpandableNotificationRow row =
-                mNotificationTestHelper.createRow(mNotificationTestHelper.createNotification());
-        row.getEntry().getChannel().setImportanceLockedByCriticalDeviceFunction(true);
-        row.getEntry().getChannel().setBlockable(true);
+        NotificationEntry entry = mock(NotificationEntry.class);
 
+        Mockito.doReturn(false, true).when(entry).isBlockable();
+        row.setEntry(entry);
+        assertTrue(row.getIsNonblockable());
         assertFalse(row.getIsNonblockable());
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 16f934b..2faff0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -39,6 +39,7 @@
 
 import android.app.IWallpaperManager;
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.WallpaperManager;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
@@ -718,6 +719,7 @@
                 .setPkg("a")
                 .setOpPkg("a")
                 .setTag("a")
+                .setChannel(new NotificationChannel("id", null, IMPORTANCE_HIGH))
                 .setNotification(n)
                 .setImportance(IMPORTANCE_HIGH)
                 .setSuppressedVisualEffects(SUPPRESSED_EFFECT_PEEK)