Merge "Reset initalization state of notif entries" into rvc-dev

This commit is contained in:
TreeHugger Robot
2020-05-17 16:39:04 +00:00
committed by Android (Google) Code Review
6 changed files with 78 additions and 6 deletions

View File

@@ -186,8 +186,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
boolean groupChangesAllowed =
mVisualStabilityManager.areGroupChangesAllowed() // user isn't looking at notifs
|| !ent.hasFinishedInitialization() // notif recently added
|| !mListContainer.containsView(ent.getRow()); // notif recently unfiltered
|| !ent.hasFinishedInitialization(); // notif recently added
NotificationEntry parent = mGroupManager.getGroupSummary(ent.getSbn());
if (!groupChangesAllowed) {

View File

@@ -151,6 +151,8 @@ public final class NotificationEntry extends ListEntry {
public CharSequence headsUpStatusBarText;
public CharSequence headsUpStatusBarTextPublic;
// indicates when this entry's view was first attached to a window
// this value will reset when the view is completely removed from the shade (ie: filtered out)
private long initializationTime = -1;
/**
@@ -473,8 +475,8 @@ public final class NotificationEntry extends ListEntry {
}
public boolean hasFinishedInitialization() {
return initializationTime == -1
|| SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
return initializationTime != -1
&& SystemClock.elapsedRealtime() > initializationTime + INITIALIZATION_DELAY;
}
public int getContrastedColor(Context context, boolean isLowPriority,
@@ -565,6 +567,10 @@ public final class NotificationEntry extends ListEntry {
return false;
}
public void resetInitializationTime() {
initializationTime = -1;
}
public void setInitializationTime(long time) {
if (initializationTime == -1) {
initializationTime = time;

View File

@@ -134,13 +134,22 @@ open class NotificationRankingManager @Inject constructor(
): List<NotificationEntry> {
logger.logFilterAndSort(reason)
val filtered = entries.asSequence()
.filterNot(notifFilter::shouldFilterOut)
.filterNot(this::filter)
.sortedWith(rankingComparator)
.toList()
entries.forEach { it.bucket = getBucketForEntry(it) }
return filtered
}
private fun filter(entry: NotificationEntry): Boolean {
val filtered = notifFilter.shouldFilterOut(entry)
if (filtered) {
// notification is removed from the list, so we reset its initialization time
entry.resetInitializationTime()
}
return filtered
}
@PriorityBucket
private fun getBucketForEntry(entry: NotificationEntry): Int {
val isHeadsUp = entry.isRowHeadsUp

View File

@@ -713,6 +713,10 @@ public class ShadeListBuilder implements Dumpable {
private boolean applyFilters(NotificationEntry entry, long now, List<NotifFilter> filters) {
final NotifFilter filter = findRejectingFilter(entry, now, filters);
entry.getAttachState().setExcludingFilter(filter);
if (filter != null) {
// notification is removed from the list, so we reset its initialization time
entry.resetInitializationTime();
}
return filter != null;
}

View File

@@ -21,6 +21,7 @@ import android.app.NotificationChannel
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.app.NotificationManager.IMPORTANCE_LOW
import android.os.SystemClock
import android.service.notification.NotificationListenerService.RankingMap
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
@@ -58,17 +59,19 @@ class NotificationRankingManagerTest : SysuiTestCase() {
private lateinit var personNotificationIdentifier: PeopleNotificationIdentifier
private lateinit var rankingManager: TestableNotificationRankingManager
private lateinit var sectionsManager: NotificationSectionsFeatureManager
private lateinit var notificationFilter: NotificationFilter
@Before
fun setup() {
personNotificationIdentifier =
mock(PeopleNotificationIdentifier::class.java)
sectionsManager = mock(NotificationSectionsFeatureManager::class.java)
notificationFilter = mock(NotificationFilter::class.java)
rankingManager = TestableNotificationRankingManager(
lazyMedia,
mock(NotificationGroupManager::class.java),
mock(HeadsUpManager::class.java),
mock(NotificationFilter::class.java),
notificationFilter,
mock(NotificationEntryManagerLogger::class.java),
sectionsManager,
personNotificationIdentifier,
@@ -324,6 +327,32 @@ class NotificationRankingManagerTest : SysuiTestCase() {
assertEquals(e.bucket, BUCKET_SILENT)
}
@Test
fun testFilter_resetsInitalizationTime() {
// GIVEN an entry that was initialized 1 second ago
val notif = Notification.Builder(mContext, "test") .build()
val e = NotificationEntryBuilder()
.setPkg("pkg")
.setOpPkg("pkg")
.setTag("tag")
.setNotification(notif)
.setUser(mContext.user)
.setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
.setOverrideGroupKey("")
.build()
e.setInitializationTime(SystemClock.elapsedRealtime() - 1000)
assertEquals(true, e.hasFinishedInitialization())
// WHEN we update ranking and filter out the notification entry
whenever(notificationFilter.shouldFilterOut(e)).thenReturn(true)
rankingManager.updateRanking(RankingMap(arrayOf(e.ranking)), listOf(e), "test")
// THEN the initialization time for the entry is reset
assertEquals(false, e.hasFinishedInitialization())
}
internal class TestableNotificationRankingManager(
mediaManager: Lazy<NotificationMediaManager>,
groupManager: NotificationGroupManager,

View File

@@ -19,8 +19,10 @@ package com.android.systemui.statusbar.notification.collection;
import static com.android.systemui.statusbar.notification.collection.ListDumper.dumpTree;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -33,6 +35,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.os.SystemClock;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.ArrayMap;
@@ -474,6 +477,28 @@ public class ShadeListBuilderTest extends SysuiTestCase {
assertEquals(filter1, mEntrySet.get(0).getExcludingFilter());
}
@Test
public void testFilter_resetsInitalizationTime() {
// GIVEN a NotifFilter that filters out a specific package
NotifFilter filter1 = spy(new PackageFilter(PACKAGE_1));
mListBuilder.addFinalizeFilter(filter1);
// GIVEN a notification that was initialized 1 second ago that will be filtered out
final NotificationEntry entry = new NotificationEntryBuilder()
.setPkg(PACKAGE_1)
.setId(nextId(PACKAGE_1))
.setRank(nextRank())
.build();
entry.setInitializationTime(SystemClock.elapsedRealtime() - 1000);
assertTrue(entry.hasFinishedInitialization());
// WHEN the pipeline is kicked off
mReadyForBuildListener.onBuildList(Arrays.asList(entry));
// THEN the entry's initialization time is reset
assertFalse(entry.hasFinishedInitialization());
}
@Test
public void testNotifFiltersCanBePreempted() {
// GIVEN two notif filters