Merge "Fix some issues in notification bucketing" into qt-dev
am: 634c095610
Change-Id: Id58d5e55da409020533882a2c5df4027d96eaff1
This commit is contained in:
@@ -25,6 +25,7 @@ import android.service.notification.NotificationListenerService.RankingMap;
|
||||
import android.service.notification.SnoozeCriterion;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.systemui.Dependency;
|
||||
@@ -69,7 +70,8 @@ public class NotificationData {
|
||||
mHeadsUpManager = headsUpManager;
|
||||
}
|
||||
|
||||
private final Comparator<NotificationEntry> mRankingComparator =
|
||||
@VisibleForTesting
|
||||
protected final Comparator<NotificationEntry> mRankingComparator =
|
||||
new Comparator<NotificationEntry>() {
|
||||
private final Ranking mRankingA = new Ranking();
|
||||
private final Ranking mRankingB = new Ranking();
|
||||
@@ -120,6 +122,8 @@ public class NotificationData {
|
||||
} else if (aSystemMax != bSystemMax) {
|
||||
// Upsort PRIORITY_MAX system notifications
|
||||
return aSystemMax ? -1 : 1;
|
||||
} else if (a.isHighPriority() != b.isHighPriority()) {
|
||||
return -1 * Boolean.compare(a.isHighPriority(), b.isHighPriority());
|
||||
} else if (aRank != bRank) {
|
||||
return aRank - bRank;
|
||||
} else {
|
||||
@@ -231,17 +235,14 @@ public class NotificationData {
|
||||
|
||||
/**
|
||||
* Returns true if this notification should be displayed in the high-priority notifications
|
||||
* section (and on the lockscreen and status bar).
|
||||
* section
|
||||
*/
|
||||
public boolean isHighPriority(StatusBarNotification statusBarNotification) {
|
||||
if (mRankingMap != null) {
|
||||
getRanking(statusBarNotification.getKey(), mTmpRanking);
|
||||
if (mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
|
||||
|| isImportantOngoing(statusBarNotification.getNotification())
|
||||
|| statusBarNotification.getNotification().hasMediaSession()
|
||||
|| hasPerson(statusBarNotification.getNotification())
|
||||
|| hasStyle(statusBarNotification.getNotification(),
|
||||
Notification.MessagingStyle.class)) {
|
||||
|| hasHighPriorityCharacteristics(
|
||||
mTmpRanking.getChannel(), statusBarNotification)) {
|
||||
return true;
|
||||
}
|
||||
if (mGroupManager.isSummaryOfGroup(statusBarNotification)) {
|
||||
@@ -257,6 +258,25 @@ public class NotificationData {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasHighPriorityCharacteristics(NotificationChannel channel,
|
||||
StatusBarNotification statusBarNotification) {
|
||||
|
||||
if (isImportantOngoing(statusBarNotification.getNotification())
|
||||
|| statusBarNotification.getNotification().hasMediaSession()
|
||||
|| hasPerson(statusBarNotification.getNotification())
|
||||
|| hasStyle(statusBarNotification.getNotification(),
|
||||
Notification.MessagingStyle.class)) {
|
||||
// Users who have long pressed and demoted to silent should not see the notification
|
||||
// in the top section
|
||||
if (channel != null && channel.hasUserSetImportance()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isImportantOngoing(Notification notification) {
|
||||
return notification.isForegroundService()
|
||||
&& mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_LOW;
|
||||
|
||||
@@ -28,6 +28,7 @@ import static android.app.NotificationManager.IMPORTANCE_MIN;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_CHANNEL;
|
||||
import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_IMPORTANCE;
|
||||
import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_RANK;
|
||||
import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_VIS_EFFECTS;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
@@ -61,16 +62,12 @@ import android.testing.TestableLooper;
|
||||
import android.testing.TestableLooper.RunWithLooper;
|
||||
import android.util.ArraySet;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.ForegroundServiceController;
|
||||
import com.android.systemui.InitController;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.statusbar.NotificationTestHelper;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationData;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupManager;
|
||||
import com.android.systemui.statusbar.phone.ShadeController;
|
||||
@@ -83,7 +80,11 @@ import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@@ -137,7 +138,9 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testChannelSetWhenAdded() {
|
||||
mNotificationData.rankingOverrides.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
|
||||
Bundle override = new Bundle();
|
||||
override.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
|
||||
mNotificationData.rankingOverrides.put(mRow.getEntry().key, override);
|
||||
mNotificationData.add(mRow.getEntry());
|
||||
assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().channel);
|
||||
}
|
||||
@@ -229,7 +232,9 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
n.flags = Notification.FLAG_FOREGROUND_SERVICE;
|
||||
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
|
||||
mNotificationData.add(entry);
|
||||
mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_VIS_EFFECTS, 255);
|
||||
mNotificationData.rankingOverrides.put(entry.key, override);
|
||||
|
||||
assertTrue(entry.isExemptFromDndVisualSuppression());
|
||||
assertFalse(entry.shouldSuppressAmbient());
|
||||
@@ -245,7 +250,9 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
when(mMockStatusBarNotification.getNotification()).thenReturn(n);
|
||||
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
|
||||
mNotificationData.add(entry);
|
||||
mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_VIS_EFFECTS, 255);
|
||||
mNotificationData.rankingOverrides.put(entry.key, override);
|
||||
|
||||
assertTrue(entry.isExemptFromDndVisualSuppression());
|
||||
assertFalse(entry.shouldSuppressAmbient());
|
||||
@@ -257,7 +264,9 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
|
||||
entry.mIsSystemNotification = true;
|
||||
mNotificationData.add(entry);
|
||||
mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_VIS_EFFECTS, 255);
|
||||
mNotificationData.rankingOverrides.put(entry.key, override);
|
||||
|
||||
assertTrue(entry.isExemptFromDndVisualSuppression());
|
||||
assertFalse(entry.shouldSuppressAmbient());
|
||||
@@ -268,8 +277,9 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
initStatusBarNotification(false);
|
||||
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
|
||||
entry.mIsSystemNotification = true;
|
||||
mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS,
|
||||
NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_VIS_EFFECTS, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
|
||||
mNotificationData.rankingOverrides.put(entry.key, override);
|
||||
mNotificationData.add(entry);
|
||||
|
||||
when(mMockStatusBarNotification.getNotification()).thenReturn(
|
||||
@@ -395,11 +405,13 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
Notification notification = mock(Notification.class);
|
||||
when(notification.isForegroundService()).thenReturn(true);
|
||||
|
||||
mNotificationData.rankingOverrides.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_MIN);
|
||||
|
||||
StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
|
||||
notification, mContext.getUser(), "", 0);
|
||||
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_MIN);
|
||||
mNotificationData.rankingOverrides.put(sbn.getKey(), override);
|
||||
|
||||
assertFalse(mNotificationData.isHighPriority(sbn));
|
||||
}
|
||||
|
||||
@@ -408,12 +420,112 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
Notification notification = mock(Notification.class);
|
||||
when(notification.isForegroundService()).thenReturn(true);
|
||||
|
||||
mNotificationData.rankingOverrides.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
|
||||
StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
|
||||
notification, mContext.getUser(), "", 0);
|
||||
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
|
||||
mNotificationData.rankingOverrides.put(sbn.getKey(), override);
|
||||
|
||||
assertTrue(mNotificationData.isHighPriority(sbn));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void userChangeTrumpsHighPriorityCharacteristics() {
|
||||
Person person = new Person.Builder()
|
||||
.setName("name")
|
||||
.setKey("abc")
|
||||
.setUri("uri")
|
||||
.setBot(true)
|
||||
.build();
|
||||
|
||||
Notification notification = new Notification.Builder(mContext, "test")
|
||||
.addPerson(person)
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
|
||||
.build();
|
||||
|
||||
StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
|
||||
notification, mContext.getUser(), "", 0);
|
||||
|
||||
assertTrue(mNotificationData.isHighPriority(sbn));
|
||||
NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
|
||||
channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
|
||||
Bundle override = new Bundle();
|
||||
override.putParcelable(OVERRIDE_CHANNEL, channel);
|
||||
mNotificationData.rankingOverrides.put(sbn.getKey(), override);
|
||||
|
||||
assertFalse(mNotificationData.isHighPriority(sbn));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSort_highPriorityTrumpsNMSRank() {
|
||||
// NMS rank says A and then B. But A is not high priority and B is, so B should sort in
|
||||
// front
|
||||
Notification aN = new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.build();
|
||||
StatusBarNotification aSbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
|
||||
aN, mContext.getUser(), "", 0);
|
||||
NotificationEntry a = new NotificationEntry(aSbn);
|
||||
a.setRow(mock(ExpandableNotificationRow.class));
|
||||
a.setIsHighPriority(false);
|
||||
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
|
||||
override.putInt(OVERRIDE_RANK, 1);
|
||||
mNotificationData.rankingOverrides.put(a.key, override);
|
||||
|
||||
Notification bN = new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.build();
|
||||
StatusBarNotification bSbn = new StatusBarNotification("pkg2", "pkg2", 0, "tag", 0, 0,
|
||||
bN, mContext.getUser(), "", 0);
|
||||
NotificationEntry b = new NotificationEntry(bSbn);
|
||||
b.setIsHighPriority(true);
|
||||
b.setRow(mock(ExpandableNotificationRow.class));
|
||||
|
||||
Bundle bOverride = new Bundle();
|
||||
bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
|
||||
bOverride.putInt(OVERRIDE_RANK, 2);
|
||||
mNotificationData.rankingOverrides.put(b.key, bOverride);
|
||||
|
||||
assertEquals(1, mNotificationData.mRankingComparator.compare(a, b));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSort_samePriorityUsesNMSRank() {
|
||||
// NMS rank says A and then B. But A is not high priority and B is, so B should sort in
|
||||
// front
|
||||
Notification aN = new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.build();
|
||||
StatusBarNotification aSbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
|
||||
aN, mContext.getUser(), "", 0);
|
||||
NotificationEntry a = new NotificationEntry(aSbn);
|
||||
a.setRow(mock(ExpandableNotificationRow.class));
|
||||
a.setIsHighPriority(false);
|
||||
|
||||
Bundle override = new Bundle();
|
||||
override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
|
||||
override.putInt(OVERRIDE_RANK, 1);
|
||||
mNotificationData.rankingOverrides.put(a.key, override);
|
||||
|
||||
Notification bN = new Notification.Builder(mContext, "test")
|
||||
.setStyle(new Notification.MessagingStyle(""))
|
||||
.build();
|
||||
StatusBarNotification bSbn = new StatusBarNotification("pkg2", "pkg2", 0, "tag", 0, 0,
|
||||
bN, mContext.getUser(), "", 0);
|
||||
NotificationEntry b = new NotificationEntry(bSbn);
|
||||
b.setRow(mock(ExpandableNotificationRow.class));
|
||||
b.setIsHighPriority(false);
|
||||
|
||||
Bundle bOverride = new Bundle();
|
||||
bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
|
||||
bOverride.putInt(OVERRIDE_RANK, 2);
|
||||
mNotificationData.rankingOverrides.put(b.key, bOverride);
|
||||
|
||||
assertEquals(-1, mNotificationData.mRankingComparator.compare(a, b));
|
||||
}
|
||||
|
||||
private void initStatusBarNotification(boolean allowDuringSetup) {
|
||||
@@ -449,7 +561,7 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
public static final String OVERRIDE_SMART_REPLIES = "sr";
|
||||
public static final String OVERRIDE_BUBBLE = "cb";
|
||||
|
||||
public Bundle rankingOverrides = new Bundle();
|
||||
public Map<String, Bundle> rankingOverrides = new HashMap<>();
|
||||
|
||||
@Override
|
||||
protected boolean getRanking(String key, Ranking outRanking) {
|
||||
@@ -475,40 +587,41 @@ public class NotificationDataTest extends SysuiTestCase {
|
||||
currentReplies.addAll(outRanking.getSmartReplies());
|
||||
}
|
||||
|
||||
outRanking.populate(key,
|
||||
rankingOverrides.getInt(OVERRIDE_RANK, outRanking.getRank()),
|
||||
rankingOverrides.getBoolean(OVERRIDE_DND,
|
||||
outRanking.matchesInterruptionFilter()),
|
||||
rankingOverrides.getInt(OVERRIDE_VIS_OVERRIDE,
|
||||
outRanking.getVisibilityOverride()),
|
||||
rankingOverrides.getInt(OVERRIDE_VIS_EFFECTS,
|
||||
outRanking.getSuppressedVisualEffects()),
|
||||
rankingOverrides.getInt(OVERRIDE_IMPORTANCE, outRanking.getImportance()),
|
||||
rankingOverrides.getCharSequence(OVERRIDE_IMP_EXP,
|
||||
outRanking.getImportanceExplanation()),
|
||||
rankingOverrides.getString(OVERRIDE_GROUP, outRanking.getOverrideGroupKey()),
|
||||
rankingOverrides.containsKey(OVERRIDE_CHANNEL)
|
||||
? (NotificationChannel) rankingOverrides.getParcelable(OVERRIDE_CHANNEL)
|
||||
: outRanking.getChannel(),
|
||||
rankingOverrides.containsKey(OVERRIDE_PEOPLE)
|
||||
? rankingOverrides.getStringArrayList(OVERRIDE_PEOPLE)
|
||||
: currentAdditionalPeople,
|
||||
rankingOverrides.containsKey(OVERRIDE_SNOOZE_CRITERIA)
|
||||
? rankingOverrides.getParcelableArrayList(OVERRIDE_SNOOZE_CRITERIA)
|
||||
: currentSnooze,
|
||||
rankingOverrides.getBoolean(OVERRIDE_BADGE, outRanking.canShowBadge()),
|
||||
rankingOverrides.getInt(OVERRIDE_USER_SENTIMENT, outRanking.getUserSentiment()),
|
||||
rankingOverrides.getBoolean(OVERRIDE_HIDDEN, outRanking.isSuspended()),
|
||||
rankingOverrides.getLong(OVERRIDE_LAST_ALERTED,
|
||||
outRanking.getLastAudiblyAlertedMillis()),
|
||||
rankingOverrides.getBoolean(OVERRIDE_NOISY, outRanking.isNoisy()),
|
||||
rankingOverrides.containsKey(OVERRIDE_SMART_ACTIONS)
|
||||
? rankingOverrides.getParcelableArrayList(OVERRIDE_SMART_ACTIONS)
|
||||
: currentActions,
|
||||
rankingOverrides.containsKey(OVERRIDE_SMART_REPLIES)
|
||||
? rankingOverrides.getCharSequenceArrayList(OVERRIDE_SMART_REPLIES)
|
||||
: currentReplies,
|
||||
rankingOverrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()));
|
||||
if (rankingOverrides.get(key) != null) {
|
||||
Bundle overrides = rankingOverrides.get(key);
|
||||
outRanking.populate(key,
|
||||
overrides.getInt(OVERRIDE_RANK, outRanking.getRank()),
|
||||
overrides.getBoolean(OVERRIDE_DND, outRanking.matchesInterruptionFilter()),
|
||||
overrides.getInt(OVERRIDE_VIS_OVERRIDE, outRanking.getVisibilityOverride()),
|
||||
overrides.getInt(OVERRIDE_VIS_EFFECTS,
|
||||
outRanking.getSuppressedVisualEffects()),
|
||||
overrides.getInt(OVERRIDE_IMPORTANCE, outRanking.getImportance()),
|
||||
overrides.getCharSequence(OVERRIDE_IMP_EXP,
|
||||
outRanking.getImportanceExplanation()),
|
||||
overrides.getString(OVERRIDE_GROUP, outRanking.getOverrideGroupKey()),
|
||||
overrides.containsKey(OVERRIDE_CHANNEL)
|
||||
? (NotificationChannel) overrides.getParcelable(OVERRIDE_CHANNEL)
|
||||
: outRanking.getChannel(),
|
||||
overrides.containsKey(OVERRIDE_PEOPLE)
|
||||
? overrides.getStringArrayList(OVERRIDE_PEOPLE)
|
||||
: currentAdditionalPeople,
|
||||
overrides.containsKey(OVERRIDE_SNOOZE_CRITERIA)
|
||||
? overrides.getParcelableArrayList(OVERRIDE_SNOOZE_CRITERIA)
|
||||
: currentSnooze,
|
||||
overrides.getBoolean(OVERRIDE_BADGE, outRanking.canShowBadge()),
|
||||
overrides.getInt(OVERRIDE_USER_SENTIMENT, outRanking.getUserSentiment()),
|
||||
overrides.getBoolean(OVERRIDE_HIDDEN, outRanking.isSuspended()),
|
||||
overrides.getLong(OVERRIDE_LAST_ALERTED,
|
||||
outRanking.getLastAudiblyAlertedMillis()),
|
||||
overrides.getBoolean(OVERRIDE_NOISY, outRanking.isNoisy()),
|
||||
overrides.containsKey(OVERRIDE_SMART_ACTIONS)
|
||||
? overrides.getParcelableArrayList(OVERRIDE_SMART_ACTIONS)
|
||||
: currentActions,
|
||||
overrides.containsKey(OVERRIDE_SMART_REPLIES)
|
||||
? overrides.getCharSequenceArrayList(OVERRIDE_SMART_REPLIES)
|
||||
: currentReplies,
|
||||
overrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user