summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt123
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt215
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLoggerTest.kt98
7 files changed, 385 insertions, 143 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 68bf69a3ea9d..2887f975d46c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -88,9 +88,9 @@ import com.android.systemui.statusbar.notification.collection.notifcollection.En
import com.android.systemui.statusbar.notification.collection.notifcollection.EntryUpdatedEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.InitEntryEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionInconsistencyTracker;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
-import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLoggerKt;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifEvent;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
@@ -112,7 +112,6 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Queue;
-import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -151,6 +150,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private final Executor mBgExecutor;
private final LogBufferEulogizer mEulogizer;
private final DumpManager mDumpManager;
+ private final NotifCollectionInconsistencyTracker mInconsistencyTracker;
private final Map<String, NotificationEntry> mNotificationSet = new ArrayMap<>();
private final Collection<NotificationEntry> mReadOnlyNotificationSet =
@@ -162,7 +162,6 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private final List<NotifLifetimeExtender> mLifetimeExtenders = new ArrayList<>();
private final List<NotifDismissInterceptor> mDismissInterceptors = new ArrayList<>();
- private Set<String> mNotificationsWithoutRankings = Collections.emptySet();
private Queue<NotifEvent> mEventQueue = new ArrayDeque<>();
@@ -188,6 +187,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
mBgExecutor = bgExecutor;
mEulogizer = logBufferEulogizer;
mDumpManager = dumpManager;
+ mInconsistencyTracker = new NotifCollectionInconsistencyTracker(mLogger);
}
/** Initializes the NotifCollection and registers it to receive notification events. */
@@ -199,6 +199,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
mAttached = true;
mDumpManager.registerDumpable(TAG, this);
groupCoalescer.setNotificationHandler(mNotifHandler);
+ mInconsistencyTracker.attach(mNotificationSet::keySet, groupCoalescer::getCoalescedKeySet);
}
/**
@@ -598,14 +599,9 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
}
}
}
- NotifCollectionLoggerKt.maybeLogInconsistentRankings(
- mLogger,
- mNotificationsWithoutRankings,
- currentEntriesWithoutRankings,
- rankingMap
- );
- mNotificationsWithoutRankings = currentEntriesWithoutRankings == null
- ? Collections.emptySet() : currentEntriesWithoutRankings.keySet();
+
+ mInconsistencyTracker.logNewMissingNotifications(rankingMap);
+ mInconsistencyTracker.logNewInconsistentRankings(currentEntriesWithoutRankings, rankingMap);
if (currentEntriesWithoutRankings != null && mNotifPipelineFlags.removeUnrankedNotifs()) {
for (NotificationEntry entry : currentEntriesWithoutRankings.values()) {
entry.mCancellationReason = REASON_UNKNOWN;
@@ -864,10 +860,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
true,
"\t\t"));
- pw.println("\n\tmNotificationsWithoutRankings: " + mNotificationsWithoutRankings.size());
- for (String key : mNotificationsWithoutRankings) {
- pw.println("\t * : " + key);
- }
+ mInconsistencyTracker.dump(pw);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
index 98f2167ebfa6..96b35428b3ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescer.java
@@ -39,9 +39,11 @@ import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.inject.Inject;
@@ -118,6 +120,11 @@ public class GroupCoalescer implements Dumpable, PipelineDumpable {
mHandler = handler;
}
+ /** @return the set of notification keys currently in the coalescer */
+ public Set<String> getCoalescedKeySet() {
+ return Collections.unmodifiableSet(mCoalescedEvents.keySet());
+ }
+
private final NotificationHandler mListener = new NotificationHandler() {
@Override
public void onNotificationPosted(StatusBarNotification sbn, RankingMap rankingMap) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt
new file mode 100644
index 000000000000..8bce5b011d0c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import android.service.notification.NotificationListenerService.RankingMap
+import android.util.ArrayMap
+import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import java.io.PrintWriter
+
+class NotifCollectionInconsistencyTracker(val logger: NotifCollectionLogger) {
+ fun attach(
+ collectedKeySetAccessor: () -> Set<String>,
+ coalescedKeySetAccessor: () -> Set<String>,
+ ) {
+ if (attached) {
+ throw RuntimeException("attach() called twice")
+ }
+ attached = true
+ this.collectedKeySetAccessor = collectedKeySetAccessor
+ this.coalescedKeySetAccessor = coalescedKeySetAccessor
+ }
+
+ fun logNewMissingNotifications(rankingMap: RankingMap) {
+ val currentCollectedKeys = collectedKeySetAccessor()
+ val currentCoalescedKeys = coalescedKeySetAccessor()
+ val newMissingNotifications = rankingMap.orderedKeys.asSequence()
+ .filter { it !in currentCollectedKeys }
+ .filter { it !in currentCoalescedKeys }
+ .toSet()
+ maybeLogMissingNotifications(missingNotifications, newMissingNotifications)
+ missingNotifications = newMissingNotifications
+ }
+
+ @VisibleForTesting
+ fun maybeLogMissingNotifications(
+ oldMissingKeys: Set<String>,
+ newMissingKeys: Set<String>,
+ ) {
+ if (oldMissingKeys.isEmpty() && newMissingKeys.isEmpty()) return
+ if (oldMissingKeys == newMissingKeys) return
+ (oldMissingKeys - newMissingKeys).sorted().let { justFound ->
+ if (justFound.isNotEmpty()) {
+ logger.logFoundNotifications(justFound, newMissingKeys.size)
+ }
+ }
+ (newMissingKeys - oldMissingKeys).sorted().let { goneMissing ->
+ if (goneMissing.isNotEmpty()) {
+ logger.logMissingNotifications(goneMissing, newMissingKeys.size)
+ }
+ }
+ }
+
+ fun logNewInconsistentRankings(
+ currentEntriesWithoutRankings: ArrayMap<String, NotificationEntry>?,
+ rankingMap: RankingMap,
+ ) {
+ maybeLogInconsistentRankings(
+ notificationsWithoutRankings,
+ currentEntriesWithoutRankings ?: emptyMap(),
+ rankingMap
+ )
+ notificationsWithoutRankings = currentEntriesWithoutRankings?.keys ?: emptySet()
+ }
+
+ @VisibleForTesting
+ fun maybeLogInconsistentRankings(
+ oldKeysWithoutRankings: Set<String>,
+ newEntriesWithoutRankings: Map<String, NotificationEntry>,
+ rankingMap: RankingMap,
+ ) {
+ if (oldKeysWithoutRankings.isEmpty() && newEntriesWithoutRankings.isEmpty()) return
+ if (oldKeysWithoutRankings == newEntriesWithoutRankings.keys) return
+ val newlyConsistent: List<String> = oldKeysWithoutRankings
+ .mapNotNull { key ->
+ key.takeIf { key !in newEntriesWithoutRankings }
+ .takeIf { key in rankingMap.orderedKeys }
+ }.sorted()
+ if (newlyConsistent.isNotEmpty()) {
+ val totalInconsistent: Int = newEntriesWithoutRankings.size
+ logger.logRecoveredRankings(newlyConsistent, totalInconsistent)
+ }
+ val newlyInconsistent: List<NotificationEntry> = newEntriesWithoutRankings
+ .mapNotNull { (key, entry) ->
+ entry.takeIf { key !in oldKeysWithoutRankings }
+ }.sortedBy { it.key }
+ if (newlyInconsistent.isNotEmpty()) {
+ val totalInconsistent: Int = newEntriesWithoutRankings.size
+ logger.logMissingRankings(newlyInconsistent, totalInconsistent, rankingMap)
+ }
+ }
+
+ fun dump(pw: PrintWriter) {
+ pw.println("notificationsWithoutRankings: ${notificationsWithoutRankings.size}")
+ for (key in notificationsWithoutRankings) {
+ pw.println("\t * : $key")
+ }
+ pw.println("missingNotifications: ${missingNotifications.size}")
+ for (key in missingNotifications) {
+ pw.println("\t * : $key")
+ }
+ }
+
+ private var attached: Boolean = false
+ private lateinit var collectedKeySetAccessor: (() -> Set<String>)
+ private lateinit var coalescedKeySetAccessor: (() -> Set<String>)
+ private var notificationsWithoutRankings = emptySet<String>()
+ private var missingNotifications = emptySet<String>()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index ebcac6b6afb3..aa27e1e407f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -215,8 +215,9 @@ class NotifCollectionLogger @Inject constructor(
})
}
- fun logRecoveredRankings(newlyConsistentKeys: List<String>) {
+ fun logRecoveredRankings(newlyConsistentKeys: List<String>, totalInconsistent: Int) {
buffer.log(TAG, INFO, {
+ int1 = totalInconsistent
int1 = newlyConsistentKeys.size
str1 = newlyConsistentKeys.joinToString { logKey(it) ?: "null" }
}, {
@@ -224,6 +225,32 @@ class NotifCollectionLogger @Inject constructor(
})
}
+ fun logMissingNotifications(
+ newlyMissingKeys: List<String>,
+ totalMissing: Int,
+ ) {
+ buffer.log(TAG, WARNING, {
+ int1 = totalMissing
+ int2 = newlyMissingKeys.size
+ str1 = newlyMissingKeys.joinToString { logKey(it) ?: "null" }
+ }, {
+ "Collection missing $int1 entries in ranking update. Just lost $int2: $str1"
+ })
+ }
+
+ fun logFoundNotifications(
+ newlyFoundKeys: List<String>,
+ totalMissing: Int,
+ ) {
+ buffer.log(TAG, INFO, {
+ int1 = totalMissing
+ int2 = newlyFoundKeys.size
+ str1 = newlyFoundKeys.joinToString { logKey(it) ?: "null" }
+ }, {
+ "Collection missing $int1 entries in ranking update. Just found $int2: $str1"
+ })
+ }
+
fun logRemoteExceptionOnNotificationClear(entry: NotificationEntry, e: RemoteException) {
buffer.log(TAG, WTF, {
str1 = entry.logKey
@@ -362,29 +389,4 @@ class NotifCollectionLogger @Inject constructor(
}
}
-fun maybeLogInconsistentRankings(
- logger: NotifCollectionLogger,
- oldKeysWithoutRankings: Set<String>,
- newEntriesWithoutRankings: Map<String, NotificationEntry>?,
- rankingMap: RankingMap
-) {
- if (oldKeysWithoutRankings.isEmpty() && newEntriesWithoutRankings == null) return
- val newlyConsistent: List<String> = oldKeysWithoutRankings
- .mapNotNull { key ->
- key.takeIf { key !in (newEntriesWithoutRankings ?: emptyMap()) }
- .takeIf { key in rankingMap.orderedKeys }
- }.sorted()
- if (newlyConsistent.isNotEmpty()) {
- logger.logRecoveredRankings(newlyConsistent)
- }
- val newlyInconsistent: List<NotificationEntry> = newEntriesWithoutRankings
- ?.mapNotNull { (key, entry) ->
- entry.takeIf { key !in oldKeysWithoutRankings }
- }?.sortedBy { it.key } ?: emptyList()
- if (newlyInconsistent.isNotEmpty()) {
- val totalInconsistent: Int = newEntriesWithoutRankings?.size ?: 0
- logger.logMissingRankings(newlyInconsistent, totalInconsistent, rankingMap)
- }
-}
-
private const val TAG = "NotifCollection"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 4df99be9efd1..851517e1e35b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -1518,7 +1518,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any());
- verify(mLogger, never()).logRecoveredRankings(any());
+ verify(mLogger, never()).logRecoveredRankings(any(), anyInt());
clearInvocations(mCollectionListener, mLogger);
// WHEN a ranking update includes key1 again
@@ -1530,7 +1530,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger, never()).logMissingRankings(any(), anyInt(), any());
- verify(mLogger).logRecoveredRankings(eq(List.of(key1)));
+ verify(mLogger).logRecoveredRankings(eq(List.of(key1)), eq(0));
}
@Test
@@ -1556,7 +1556,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger).logMissingRankings(eq(List.of(entry1)), eq(1), any());
- verify(mLogger, never()).logRecoveredRankings(any());
+ verify(mLogger, never()).logRecoveredRankings(any(), anyInt());
clearInvocations(mCollectionListener, mLogger);
// WHEN a ranking update includes key1 again
@@ -1568,7 +1568,7 @@ public class NotifCollectionTest extends SysuiTestCase {
verify(mCollectionListener).onRankingApplied();
verifyNoMoreInteractions(mCollectionListener);
verify(mLogger, never()).logMissingRankings(any(), anyInt(), any());
- verify(mLogger).logRecoveredRankings(eq(List.of(key1)));
+ verify(mLogger).logRecoveredRankings(eq(List.of(key1)), eq(0));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
new file mode 100644
index 000000000000..6eb391a631f3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.notifcollection
+
+import android.service.notification.NotificationListenerService.RankingMap
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotifCollectionInconsistencyTrackerTest : SysuiTestCase() {
+ private val logger: NotifCollectionLogger = mock()
+ private val entry1: NotificationEntry = NotificationEntryBuilder().setId(1).build()
+ private val entry2: NotificationEntry = NotificationEntryBuilder().setId(2).build()
+ private val collectionSet = mutableSetOf<String>()
+ private val coalescedSet = mutableSetOf<String>()
+ private lateinit var inconsistencyTracker: NotifCollectionInconsistencyTracker
+
+ private fun mapOfEntries(vararg entries: NotificationEntry): Map<String, NotificationEntry> =
+ entries.associateBy { it.key }
+
+ private fun rankingMapOf(vararg entries: NotificationEntry): RankingMap =
+ RankingMap(entries.map { it.ranking }.toTypedArray())
+
+ @Before
+ fun setUp() {
+ inconsistencyTracker = NotifCollectionInconsistencyTracker(logger)
+ inconsistencyTracker.attach({ collectionSet }, { coalescedSet })
+ collectionSet.clear()
+ coalescedSet.clear()
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_logsNewlyInconsistentRanking() {
+ val rankingMap = rankingMapOf(entry1)
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = emptySet(),
+ newEntriesWithoutRankings = mapOfEntries(entry2),
+ rankingMap = rankingMap
+ )
+ verify(logger).logMissingRankings(
+ newlyInconsistentEntries = eq(listOf(entry2)),
+ totalInconsistent = eq(1),
+ rankingMap = eq(rankingMap),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_doesNotLogAlreadyInconsistentRanking() {
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = setOf(entry2.key),
+ newEntriesWithoutRankings = mapOfEntries(entry2),
+ rankingMap = rankingMapOf(entry1)
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_logsWhenRankingIsAdded() {
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = setOf(entry2.key),
+ newEntriesWithoutRankings = mapOfEntries(),
+ rankingMap = rankingMapOf(entry1, entry2)
+ )
+ verify(logger).logRecoveredRankings(
+ newlyConsistentKeys = eq(listOf(entry2.key)),
+ totalInconsistent = eq(0),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogInconsistentRankings_doesNotLogsWhenEntryIsRemoved() {
+ inconsistencyTracker.maybeLogInconsistentRankings(
+ oldKeysWithoutRankings = setOf(entry2.key),
+ newEntriesWithoutRankings = mapOfEntries(),
+ rankingMap = rankingMapOf(entry1)
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsNewlyMissingNotifications() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a"),
+ newMissingKeys = setOf("a", "b"),
+ )
+ verify(logger).logMissingNotifications(
+ newlyMissingKeys = eq(listOf("b")),
+ totalMissing = eq(2),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsNoLongerMissingNotifications() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a", "b"),
+ newMissingKeys = setOf("a"),
+ )
+ verify(logger).logFoundNotifications(
+ newlyFoundKeys = eq(listOf("b")),
+ totalMissing = eq(1),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsBothAtOnce() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a"),
+ newMissingKeys = setOf("b"),
+ )
+ verify(logger).logFoundNotifications(
+ newlyFoundKeys = eq(listOf("a")),
+ totalMissing = eq(1),
+ )
+ verify(logger).logMissingNotifications(
+ newlyMissingKeys = eq(listOf("b")),
+ totalMissing = eq(1),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun maybeLogMissingNotifications_logsNothingWhenNoChange() {
+ inconsistencyTracker.maybeLogMissingNotifications(
+ oldMissingKeys = setOf("a"),
+ newMissingKeys = setOf("a"),
+ )
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun logNewMissingNotifications_doesNotLogForConsistentSets() {
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
+ verifyNoMoreInteractions(logger)
+
+ collectionSet.add(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.add(entry2.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.add(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.remove(entry1.key)
+ collectionSet.remove(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.remove(entry2.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
+ verifyNoMoreInteractions(logger)
+ }
+
+ @Test
+ fun logNewMissingNotifications_logsAsExpected() {
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf())
+ verifyNoMoreInteractions(logger)
+
+ collectionSet.add(entry1.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verify(logger).logMissingNotifications(
+ newlyMissingKeys = eq(listOf(entry2.key)),
+ totalMissing = eq(1),
+ )
+ verifyNoMoreInteractions(logger)
+ clearInvocations(logger)
+
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verifyNoMoreInteractions(logger)
+
+ coalescedSet.add(entry2.key)
+ inconsistencyTracker.logNewMissingNotifications(rankingMapOf(entry1, entry2))
+ verify(logger).logFoundNotifications(
+ newlyFoundKeys = eq(listOf(entry2.key)),
+ totalMissing = eq(0),
+ )
+ verifyNoMoreInteractions(logger)
+ clearInvocations(logger)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLoggerTest.kt
deleted file mode 100644
index 6c07174bce65..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLoggerTest.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.systemui.statusbar.notification.collection.notifcollection
-
-import android.service.notification.NotificationListenerService.RankingMap
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper.RunWithLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.mockito.mock
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyNoMoreInteractions
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@RunWithLooper
-class NotifCollectionLoggerTest : SysuiTestCase() {
- private val logger: NotifCollectionLogger = mock()
- private val entry1: NotificationEntry = NotificationEntryBuilder().setId(1).build()
- private val entry2: NotificationEntry = NotificationEntryBuilder().setId(2).build()
-
- private fun mapOfEntries(vararg entries: NotificationEntry): Map<String, NotificationEntry> =
- entries.associateBy { it.key }
-
- private fun rankingMapOf(vararg entries: NotificationEntry): RankingMap =
- RankingMap(entries.map { it.ranking }.toTypedArray())
-
- @Test
- fun testMaybeLogInconsistentRankings_logsNewlyInconsistentRanking() {
- val rankingMap = rankingMapOf(entry1)
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = emptySet(),
- newEntriesWithoutRankings = mapOfEntries(entry2),
- rankingMap = rankingMap
- )
- verify(logger).logMissingRankings(
- newlyInconsistentEntries = eq(listOf(entry2)),
- totalInconsistent = eq(1),
- rankingMap = eq(rankingMap),
- )
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testMaybeLogInconsistentRankings_doesNotLogAlreadyInconsistentRanking() {
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = setOf(entry2.key),
- newEntriesWithoutRankings = mapOfEntries(entry2),
- rankingMap = rankingMapOf(entry1)
- )
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testMaybeLogInconsistentRankings_logsWhenRankingIsAdded() {
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = setOf(entry2.key),
- newEntriesWithoutRankings = mapOfEntries(),
- rankingMap = rankingMapOf(entry1, entry2)
- )
- verify(logger).logRecoveredRankings(
- newlyConsistentKeys = eq(listOf(entry2.key)),
- )
- verifyNoMoreInteractions(logger)
- }
-
- @Test
- fun testMaybeLogInconsistentRankings_doesNotLogsWhenEntryIsRemoved() {
- maybeLogInconsistentRankings(
- logger = logger,
- oldKeysWithoutRankings = setOf(entry2.key),
- newEntriesWithoutRankings = mapOfEntries(),
- rankingMap = rankingMapOf(entry1)
- )
- verifyNoMoreInteractions(logger)
- }
-}