summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff DeCew <jeffdq@google.com> 2021-12-09 14:41:25 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-12-09 14:41:25 +0000
commit1ce5b9c15f4bd059ec7bcb6d0653cf81729e843c (patch)
tree50d00c872afe16e3240ebd4d039eec7cf6fe4e4c
parentae53d729cc178af8f846c9783f9921f28fc27818 (diff)
parent955525fe52540a53b85298570d354d1cfb60f01b (diff)
Merge "Remove access to pipeline outputs from NotifPipeline."
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStore.kt51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt137
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt59
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationVisibilityProvider.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/NotificationVisibilityProviderImpl.kt (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProviderImpl.kt)22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt167
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt105
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt83
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt116
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java62
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java3
27 files changed, 824 insertions, 305 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 0389a7b01c72..f500d39032ba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -45,6 +45,7 @@ import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.NotificationUiAdjustment;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationRanker;
@@ -107,6 +108,7 @@ public class NotificationEntryManager implements
private final LeakDetector mLeakDetector;
private final ForegroundServiceDismissalFeatureController mFgsFeatureController;
private final IStatusBarService mStatusBarService;
+ private final NotifLiveDataStoreImpl mNotifLiveDataStore;
private final DumpManager mDumpManager;
private final Set<NotificationEntry> mAllNotifications = new ArraySet<>();
@@ -154,6 +156,7 @@ public class NotificationEntryManager implements
LeakDetector leakDetector,
ForegroundServiceDismissalFeatureController fgsFeatureController,
IStatusBarService statusBarService,
+ NotifLiveDataStoreImpl notifLiveDataStore,
DumpManager dumpManager
) {
mLogger = logger;
@@ -164,6 +167,7 @@ public class NotificationEntryManager implements
mLeakDetector = leakDetector;
mFgsFeatureController = fgsFeatureController;
mStatusBarService = statusBarService;
+ mNotifLiveDataStore = notifLiveDataStore;
mDumpManager = dumpManager;
}
@@ -725,9 +729,10 @@ public class NotificationEntryManager implements
return;
}
reapplyFilterAndSort(reason);
- if (mPresenter != null && !mNotifPipelineFlags.isNewPipelineEnabled()) {
+ if (mPresenter != null) {
mPresenter.updateNotificationViews(reason);
}
+ mNotifLiveDataStore.setActiveNotifList(getVisibleNotifications());
}
public void updateNotificationRanking(RankingMap rankingMap) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStore.kt
new file mode 100644
index 000000000000..ef006279142c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStore.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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
+
+import androidx.lifecycle.Observer
+
+/**
+ * An object which provides pieces of information about the notification shade.
+ *
+ * Note that individual fields of this object are updated together before synchronous observers are
+ * notified, so synchronous observers of two fields can be assured that they will see consistent
+ * results: e.g. if [hasActiveNotifs] is false then [activeNotifList] will be empty, and vice versa.
+ *
+ * This interface is read-only.
+ */
+interface NotifLiveDataStore {
+ val hasActiveNotifs: NotifLiveData<Boolean>
+ val activeNotifCount: NotifLiveData<Int>
+ val activeNotifList: NotifLiveData<List<NotificationEntry>>
+}
+
+/**
+ * An individual value which can be accessed directly, or observed for changes either synchronously
+ * or asynchronously.
+ *
+ * This interface is read-only.
+ */
+interface NotifLiveData<T> {
+ /** Access the current value */
+ val value: T
+ /** Add an observer which will be invoked synchronously when the value is changed. */
+ fun addSyncObserver(observer: Observer<T>)
+ /** Add an observer which will be invoked asynchronously after the value has changed */
+ fun addAsyncObserver(observer: Observer<T>)
+ /** Remove an observer previously added with [addSyncObserver] or [addAsyncObserver]. */
+ fun removeObserver(observer: Observer<T>)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
new file mode 100644
index 000000000000..8aa6b81eede0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2021 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
+
+import androidx.lifecycle.Observer
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.util.Assert
+import com.android.systemui.util.ListenerSet
+import com.android.systemui.util.isNotEmpty
+import com.android.systemui.util.traceSection
+import java.util.Collections.unmodifiableList
+import java.util.concurrent.Executor
+import java.util.concurrent.atomic.AtomicReference
+import javax.inject.Inject
+
+/** Writeable implementation of [NotifLiveDataStore] */
+@SysUISingleton
+class NotifLiveDataStoreImpl @Inject constructor(
+ @Main private val mainExecutor: Executor
+) : NotifLiveDataStore {
+ private val hasActiveNotifsPrivate = NotifLiveDataImpl(
+ name = "hasActiveNotifs",
+ initialValue = false,
+ mainExecutor
+ )
+ private val activeNotifCountPrivate = NotifLiveDataImpl(
+ name = "activeNotifCount",
+ initialValue = 0,
+ mainExecutor
+ )
+ private val activeNotifListPrivate = NotifLiveDataImpl(
+ name = "activeNotifList",
+ initialValue = listOf<NotificationEntry>(),
+ mainExecutor
+ )
+
+ override val hasActiveNotifs: NotifLiveData<Boolean> = hasActiveNotifsPrivate
+ override val activeNotifCount: NotifLiveData<Int> = activeNotifCountPrivate
+ override val activeNotifList: NotifLiveData<List<NotificationEntry>> = activeNotifListPrivate
+
+ /** Set the latest flattened list of notification entries. */
+ fun setActiveNotifList(flatEntryList: List<NotificationEntry>) {
+ traceSection("NotifLiveDataStore.setActiveNotifList") {
+ Assert.isMainThread()
+ val unmodifiableCopy = unmodifiableList(flatEntryList.toList())
+ // This ensures we set all values before dispatching to any observers
+ listOf(
+ activeNotifListPrivate.setValueAndProvideDispatcher(unmodifiableCopy),
+ activeNotifCountPrivate.setValueAndProvideDispatcher(unmodifiableCopy.size),
+ hasActiveNotifsPrivate.setValueAndProvideDispatcher(unmodifiableCopy.isNotEmpty())
+ ).forEach { dispatcher -> dispatcher.invoke() }
+ }
+ }
+}
+
+/** Read-write implementation of [NotifLiveData] */
+class NotifLiveDataImpl<T>(
+ private val name: String,
+ initialValue: T,
+ @Main private val mainExecutor: Executor
+) : NotifLiveData<T> {
+ private val syncObservers = ListenerSet<Observer<T>>()
+ private val asyncObservers = ListenerSet<Observer<T>>()
+ private val atomicValue = AtomicReference(initialValue)
+ private var lastAsyncValue: T? = null
+
+ private fun dispatchToAsyncObservers() {
+ val value = atomicValue.get()
+ if (lastAsyncValue != value) {
+ lastAsyncValue = value
+ traceSection("NotifLiveData($name).dispatchToAsyncObservers") {
+ asyncObservers.forEach { it.onChanged(value) }
+ }
+ }
+ }
+
+ /**
+ * Access or set the current value.
+ *
+ * When setting, sync observers will be dispatched synchronously, and a task will be posted to
+ * dispatch the value to async observers.
+ */
+ override var value: T
+ get() = atomicValue.get()
+ set(value) = setValueAndProvideDispatcher(value).invoke()
+
+ /**
+ * Set the value, and return a function that when invoked will dispatch to the observers.
+ *
+ * This is intended to allow multiple instances with related data to be updated together and
+ * have their dispatchers invoked after all data has been updated.
+ */
+ fun setValueAndProvideDispatcher(value: T): () -> Unit {
+ val oldValue = atomicValue.getAndSet(value)
+ if (oldValue != value) {
+ return {
+ if (syncObservers.isNotEmpty()) {
+ traceSection("NotifLiveData($name).dispatchToSyncObservers") {
+ syncObservers.forEach { it.onChanged(value) }
+ }
+ }
+ if (asyncObservers.isNotEmpty()) {
+ mainExecutor.execute(::dispatchToAsyncObservers)
+ }
+ }
+ }
+ return {}
+ }
+
+ override fun addSyncObserver(observer: Observer<T>) {
+ syncObservers.addIfAbsent(observer)
+ }
+
+ override fun addAsyncObserver(observer: Observer<T>) {
+ asyncObservers.addIfAbsent(observer)
+ }
+
+ override fun removeObserver(observer: Observer<T>) {
+ syncObservers.remove(observer)
+ asyncObservers.remove(observer)
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
index 6fbed9a8d3b4..5ada7a82f8fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
@@ -245,36 +245,4 @@ class NotifPipeline @Inject constructor(
fun getInternalNotifUpdater(name: String?): InternalNotifUpdater {
return mNotifCollection.getInternalNotifUpdater(name)
}
-
- /**
- * Returns a read-only view in to the current shade list, i.e. the list of notifications that
- * are currently present in the shade.
- * @throws IllegalStateException if called during pipeline execution.
- */
- val shadeList: List<ListEntry>
- get() = mShadeListBuilder.shadeList
-
- /**
- * Constructs a flattened representation of the notification tree, where each group will have
- * the summary (if present) followed by the children.
- * @throws IllegalStateException if called during pipeline execution.
- */
- fun getFlatShadeList(): List<NotificationEntry> = shadeList.flatMap { entry ->
- when (entry) {
- is NotificationEntry -> sequenceOf(entry)
- is GroupEntry -> sequenceOf(entry.summary).filterNotNull() + entry.children
- else -> throw RuntimeException("Unexpected entry $entry")
- }
- }
-
- /**
- * Returns the number of notifications currently shown in the shade. This includes all
- * children and summary notifications.
- * @throws IllegalStateException if called during pipeline execution.
- */
- fun getShadeListCount(): Int = shadeList.sumOf { entry ->
- // include the summary in the count
- if (entry is GroupEntry) 1 + entry.children.size
- else 1
- }
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
new file mode 100644
index 000000000000..8e307ecd896d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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.coordinator
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.render.requireSummary
+import javax.inject.Inject
+
+/**
+ * A small coordinator which updates the notif stack (the view layer which holds notifications)
+ * with high-level data after the stack is populated with the final entries.
+ */
+@CoordinatorScope
+class DataStoreCoordinator @Inject internal constructor(
+ private val notifLiveDataStoreImpl: NotifLiveDataStoreImpl
+) : Coordinator {
+
+ override fun attach(pipeline: NotifPipeline) {
+ pipeline.addOnAfterRenderListListener { entries, _ -> onAfterRenderList(entries) }
+ }
+
+ fun onAfterRenderList(entries: List<ListEntry>) {
+ val flatEntryList = flattenedEntryList(entries)
+ notifLiveDataStoreImpl.setActiveNotifList(flatEntryList)
+ }
+
+ private fun flattenedEntryList(entries: List<ListEntry>) =
+ mutableListOf<NotificationEntry>().also { list ->
+ entries.forEach { entry ->
+ when (entry) {
+ is NotificationEntry -> list.add(entry)
+ is GroupEntry -> {
+ list.add(entry.requireSummary)
+ list.addAll(entry.children)
+ }
+ else -> error("Unexpected entry $entry")
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index a16b565d488c..02649bad33d3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -35,6 +35,7 @@ interface NotifCoordinators : Coordinator, Dumpable
class NotifCoordinatorsImpl @Inject constructor(
dumpManager: DumpManager,
notifPipelineFlags: NotifPipelineFlags,
+ dataStoreCoordinator: DataStoreCoordinator,
hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
keyguardCoordinator: KeyguardCoordinator,
@@ -44,10 +45,11 @@ class NotifCoordinatorsImpl @Inject constructor(
bubbleCoordinator: BubbleCoordinator,
headsUpCoordinator: HeadsUpCoordinator,
gutsCoordinator: GutsCoordinator,
+ communalCoordinator: CommunalCoordinator,
conversationCoordinator: ConversationCoordinator,
- preparationCoordinator: PreparationCoordinator,
groupCountCoordinator: GroupCountCoordinator,
mediaCoordinator: MediaCoordinator,
+ preparationCoordinator: PreparationCoordinator,
remoteInputCoordinator: RemoteInputCoordinator,
rowAppearanceCoordinator: RowAppearanceCoordinator,
stackCoordinator: StackCoordinator,
@@ -55,7 +57,6 @@ class NotifCoordinatorsImpl @Inject constructor(
smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
viewConfigCoordinator: ViewConfigCoordinator,
visualStabilityCoordinator: VisualStabilityCoordinator,
- communalCoordinator: CommunalCoordinator,
sensitiveContentCoordinator: SensitiveContentCoordinator
) : NotifCoordinators {
@@ -67,6 +68,16 @@ class NotifCoordinatorsImpl @Inject constructor(
*/
init {
dumpManager.registerDumpable(TAG, this)
+
+ // TODO(b/208866714): formalize the system by which some coordinators may be required by the
+ // pipeline, such as this DataStoreCoordinator which cannot be removed, as it's a critical
+ // glue between the pipeline and parts of SystemUI which depend on pipeline output via the
+ // NotifLiveDataStore.
+ if (notifPipelineFlags.isNewPipelineEnabled()) {
+ mCoordinators.add(dataStoreCoordinator)
+ }
+
+ // Attach normal coordinators.
mCoordinators.add(hideLocallyDismissedNotifsCoordinator)
mCoordinators.add(hideNotifsForOtherUsersCoordinator)
mCoordinators.add(keyguardCoordinator)
@@ -74,6 +85,7 @@ class NotifCoordinatorsImpl @Inject constructor(
mCoordinators.add(appOpsCoordinator)
mCoordinators.add(deviceProvisionedCoordinator)
mCoordinators.add(bubbleCoordinator)
+ mCoordinators.add(communalCoordinator)
mCoordinators.add(conversationCoordinator)
mCoordinators.add(groupCountCoordinator)
mCoordinators.add(mediaCoordinator)
@@ -83,7 +95,6 @@ class NotifCoordinatorsImpl @Inject constructor(
mCoordinators.add(shadeEventCoordinator)
mCoordinators.add(viewConfigCoordinator)
mCoordinators.add(visualStabilityCoordinator)
- mCoordinators.add(communalCoordinator)
mCoordinators.add(sensitiveContentCoordinator)
if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
mCoordinators.add(smartspaceDedupingCoordinator)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
index 38f11fc88b72..c6a8a69cfb0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -19,8 +19,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
-import com.android.systemui.statusbar.notification.collection.render.NotifStats
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
+import com.android.systemui.statusbar.notification.collection.render.NotifStats
import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
import com.android.systemui.statusbar.phone.NotificationIconAreaController
import javax.inject.Inject
@@ -49,10 +49,12 @@ class StackCoordinator @Inject internal constructor(
var hasNonClearableSilentNotifs = false
var hasClearableSilentNotifs = false
entries.forEach {
- val isSilent = it.section!!.bucket == BUCKET_SILENT
+ val section = checkNotNull(it.section) { "Null section for ${it.key}" }
+ val entry = checkNotNull(it.representativeEntry) { "Null notif entry for ${it.key}" }
+ val isSilent = section.bucket == BUCKET_SILENT
// NOTE: NotificationEntry.isClearable will internally check group children to ensure
// the group itself definitively clearable.
- val isClearable = it.representativeEntry!!.isClearable
+ val isClearable = entry.isClearable
when {
isSilent && isClearable -> hasClearableSilentNotifs = true
isSilent && !isClearable -> hasNonClearableSilentNotifs = true
@@ -60,13 +62,12 @@ class StackCoordinator @Inject internal constructor(
!isSilent && !isClearable -> hasNonClearableAlertingNotifs = true
}
}
- val stats = NotifStats(
+ return NotifStats(
numActiveNotifs = entries.size,
hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs,
hasClearableAlertingNotifs = hasClearableAlertingNotifs,
hasNonClearableSilentNotifs = hasNonClearableSilentNotifs,
hasClearableSilentNotifs = hasClearableSilentNotifs
)
- return stats
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationVisibilityProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationVisibilityProvider.kt
deleted file mode 100644
index 5c70f32dfd25..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationVisibilityProvider.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2021 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.legacy
-
-import com.android.internal.statusbar.NotificationVisibility
-import com.android.systemui.statusbar.notification.NotificationEntryManager
-import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider
-import com.android.systemui.statusbar.notification.logging.NotificationLogger
-import javax.inject.Inject
-
-/** Legacy pipeline implementation for getting [NotificationVisibility]. */
-class LegacyNotificationVisibilityProvider @Inject constructor(
- private val notifEntryManager: NotificationEntryManager
-) : NotificationVisibilityProvider {
- override fun obtain(entry: NotificationEntry, visible: Boolean): NotificationVisibility {
- val count: Int = notifEntryManager.activeNotificationsCount
- val rank = entry.ranking.rank
- val hasRow = entry.row != null
- val location = NotificationLogger.getNotificationLocation(entry)
- return NotificationVisibility.obtain(entry.key, rank, count, visible && hasRow, location)
- }
-
- override fun obtain(key: String, visible: Boolean): NotificationVisibility {
- val entry: NotificationEntry? = notifEntryManager.getActiveNotificationUnfiltered(key)
- val count: Int = notifEntryManager.activeNotificationsCount
- val rank = entry?.ranking?.rank ?: -1
- val hasRow = entry?.row != null
- val location = NotificationLogger.getNotificationLocation(entry)
- return NotificationVisibility.obtain(key, rank, count, visible && hasRow, location)
- }
-
- override fun getLocation(key: String): NotificationVisibility.NotificationLocation =
- NotificationLogger.getNotificationLocation(
- notifEntryManager.getActiveNotificationUnfiltered(key))
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/NotificationVisibilityProviderImpl.kt
index 51de08d539b6..6a1e36f4f469 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/NotificationVisibilityProviderImpl.kt
@@ -14,20 +14,24 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification.collection.render
+package com.android.systemui.statusbar.notification.collection.provider
import com.android.internal.statusbar.NotificationVisibility
-import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
+import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider
import com.android.systemui.statusbar.notification.logging.NotificationLogger
import javax.inject.Inject
-/** New pipeline implementation for getting [NotificationVisibility]. */
+/** pipeline-agnostic implementation for getting [NotificationVisibility]. */
class NotificationVisibilityProviderImpl @Inject constructor(
- private val notifPipeline: NotifPipeline
+ private val notifDataStore: NotifLiveDataStore,
+ private val notifCollection: CommonNotifCollection
) : NotificationVisibilityProvider {
+
override fun obtain(entry: NotificationEntry, visible: Boolean): NotificationVisibility {
- val count: Int = notifPipeline.getShadeListCount()
+ val count: Int = getCount()
val rank = entry.ranking.rank
val hasRow = entry.row != null
val location = NotificationLogger.getNotificationLocation(entry)
@@ -35,9 +39,11 @@ class NotificationVisibilityProviderImpl @Inject constructor(
}
override fun obtain(key: String, visible: Boolean): NotificationVisibility =
- notifPipeline.getEntry(key)?.let { return obtain(it, visible) }
- ?: NotificationVisibility.obtain(key, -1, notifPipeline.getShadeListCount(), false)
+ notifCollection.getEntry(key)?.let { return obtain(it, visible) }
+ ?: NotificationVisibility.obtain(key, -1, getCount(), false)
override fun getLocation(key: String): NotificationVisibility.NotificationLocation =
- NotificationLogger.getNotificationLocation(notifPipeline.getEntry(key))
+ NotificationLogger.getNotificationLocation(notifCollection.getEntry(key))
+
+ private fun getCount() = notifDataStore.activeNotifCount.value
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index d25a2d30fb4d..f1cba34158d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -44,6 +44,8 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.coordinator.ShadeEventCoordinator;
import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator;
@@ -52,12 +54,12 @@ import com.android.systemui.statusbar.notification.collection.inflation.NotifInf
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl;
import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationPresenterExtensions;
-import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationVisibilityProvider;
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.provider.NotificationVisibilityProviderImpl;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -65,7 +67,6 @@ import com.android.systemui.statusbar.notification.collection.render.GroupMember
import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
-import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProviderImpl;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl;
import com.android.systemui.statusbar.notification.init.NotificationsControllerStub;
@@ -122,6 +123,7 @@ public interface NotificationsModule {
LeakDetector leakDetector,
ForegroundServiceDismissalFeatureController fgsFeatureController,
IStatusBarService statusBarService,
+ NotifLiveDataStoreImpl notifLiveDataStore,
DumpManager dumpManager) {
return new NotificationEntryManager(
logger,
@@ -132,6 +134,7 @@ public interface NotificationsModule {
leakDetector,
fgsFeatureController,
statusBarService,
+ notifLiveDataStore,
dumpManager);
}
@@ -212,6 +215,7 @@ public interface NotificationsModule {
NotificationListener notificationListener,
@UiBackground Executor uiBgExecutor,
NotifPipelineFlags notifPipelineFlags,
+ NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
@@ -222,6 +226,7 @@ public interface NotificationsModule {
notificationListener,
uiBgExecutor,
notifPipelineFlags,
+ notifLiveDataStore,
visibilityProvider,
entryManager,
notifPipeline,
@@ -290,16 +295,10 @@ public interface NotificationsModule {
/**
* Provide the object which can be used to obtain NotificationVisibility objects.
*/
- @Provides
+ @Binds
@SysUISingleton
- static NotificationVisibilityProvider provideNotificationVisibilityProvider(
- NotifPipelineFlags notifPipelineFlags,
- Lazy<NotificationVisibilityProviderImpl> newProvider,
- Lazy<LegacyNotificationVisibilityProvider> legacyProvider) {
- return notifPipelineFlags.isNewPipelineEnabled()
- ? newProvider.get()
- : legacyProvider.get();
- }
+ NotificationVisibilityProvider provideNotificationVisibilityProvider(
+ NotificationVisibilityProviderImpl newProvider);
/**
* Provide the active implementation for presenting notifications.
@@ -356,4 +355,8 @@ public interface NotificationsModule {
/** */
@Binds
NotifInflater bindNotifInflater(NotifInflaterImpl notifInflaterImpl);
+
+ /** */
+ @Binds
+ NotifLiveDataStore bindNotifLiveDataStore(NotifLiveDataStoreImpl notifLiveDataStoreImpl);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 212c342eb8f1..84f09558e022 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -28,12 +28,14 @@ import com.android.systemui.statusbar.notification.NotificationActivityStarter
import com.android.systemui.statusbar.notification.NotificationClicker
import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.NotificationListController
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy
+import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.interruption.HeadsUpController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
@@ -64,9 +66,11 @@ class NotificationsControllerImpl @Inject constructor(
private val notificationListener: NotificationListener,
private val entryManager: NotificationEntryManager,
private val legacyRanker: NotificationRankingManager,
+ private val commonNotifCollection: Lazy<CommonNotifCollection>,
private val notifPipeline: Lazy<NotifPipeline>,
+ private val notifLiveDataStore: NotifLiveDataStore,
private val targetSdkResolver: TargetSdkResolver,
- private val newNotifPipeline: Lazy<NotifPipelineInitializer>,
+ private val newNotifPipelineInitializer: Lazy<NotifPipelineInitializer>,
private val notifBindPipelineInitializer: NotifBindPipelineInitializer,
private val deviceProvisionedController: DeviceProvisionedController,
private val notificationRowBinder: NotificationRowBinderImpl,
@@ -111,7 +115,7 @@ class NotificationsControllerImpl @Inject constructor(
animatedImageNotificationManager.bind()
if (INITIALIZE_NEW_PIPELINE) {
- newNotifPipeline.get().initialize(
+ newNotifPipelineInitializer.get().initialize(
notificationListener,
notificationRowBinder,
listContainer,
@@ -155,14 +159,10 @@ class NotificationsControllerImpl @Inject constructor(
}
override fun resetUserExpandedStates() {
- if (notifPipelineFlags.isNewPipelineEnabled()) {
- for (entry in notifPipeline.get().allNotifs) {
- entry.resetUserExpansion()
- }
- } else {
- for (entry in entryManager.visibleNotifications) {
- entry.resetUserExpansion()
- }
+ // TODO: this is a view thing that should be done through the views, but that means doing it
+ // both when this event is fired and any time a row is attached.
+ for (entry in commonNotifCollection.get().allNotifs) {
+ entry.resetUserExpansion()
}
}
@@ -177,11 +177,7 @@ class NotificationsControllerImpl @Inject constructor(
}
override fun getActiveNotificationsCount(): Int =
- if (notifPipelineFlags.isNewPipelineEnabled()) {
- notifPipeline.get().getShadeListCount()
- } else {
- entryManager.activeNotificationsCount
- }
+ notifLiveDataStore.activeNotifCount.value
companion object {
// NOTE: The new pipeline is always active, even if the old pipeline is *rendering*.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 52488da29162..9e8200b063fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -42,6 +42,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
@@ -76,7 +77,7 @@ public class NotificationLogger implements StateListener {
// Dependencies:
private final NotificationListenerService mNotificationListener;
private final Executor mUiBgExecutor;
- private final NotifPipelineFlags mNotifPipelineFlags;
+ private final NotifLiveDataStore mNotifLiveDataStore;
private final NotificationVisibilityProvider mVisibilityProvider;
private final NotificationEntryManager mEntryManager;
private final NotifPipeline mNotifPipeline;
@@ -179,11 +180,7 @@ public class NotificationLogger implements StateListener {
};
private List<NotificationEntry> getVisibleNotifications() {
- if (mNotifPipelineFlags.isNewPipelineEnabled()) {
- return mNotifPipeline.getFlatShadeList();
- } else {
- return mEntryManager.getVisibleNotifications();
- }
+ return mNotifLiveDataStore.getActiveNotifList().getValue();
}
/**
@@ -223,6 +220,7 @@ public class NotificationLogger implements StateListener {
public NotificationLogger(NotificationListener notificationListener,
@UiBackground Executor uiBgExecutor,
NotifPipelineFlags notifPipelineFlags,
+ NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
@@ -231,7 +229,7 @@ public class NotificationLogger implements StateListener {
NotificationPanelLogger notificationPanelLogger) {
mNotificationListener = notificationListener;
mUiBgExecutor = uiBgExecutor;
- mNotifPipelineFlags = notifPipelineFlags;
+ mNotifLiveDataStore = notifLiveDataStore;
mVisibilityProvider = visibilityProvider;
mEntryManager = entryManager;
mNotifPipeline = notifPipeline;
@@ -242,7 +240,7 @@ public class NotificationLogger implements StateListener {
// Not expected to be destroyed, don't need to unsubscribe
statusBarStateController.addCallback(this);
- if (mNotifPipelineFlags.isNewPipelineEnabled()) {
+ if (notifPipelineFlags.isNewPipelineEnabled()) {
registerNewPipelineListener();
} else {
registerLegacyListener();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
index c09cca1f0e42..c61510cce10e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
@@ -22,7 +22,6 @@ import static com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFrag
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.annotation.Nullable;
import android.view.InsetsVisibilities;
import android.view.View;
import android.view.WindowInsetsController.Appearance;
@@ -30,13 +29,12 @@ import android.view.WindowInsetsController.Behavior;
import android.view.WindowManager;
import android.view.animation.AccelerateInterpolator;
+import androidx.lifecycle.Observer;
+
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.view.AppearanceRegion;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
import com.android.systemui.util.ViewController;
@@ -44,20 +42,21 @@ import javax.inject.Inject;
import javax.inject.Named;
/**
- * Apps can request a low profile mode {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}
+ * Apps can request a low profile mode {@link View#SYSTEM_UI_FLAG_LOW_PROFILE}
* where status bar and navigation icons dim. In this mode, a notification dot appears
* where the notification icons would appear if they would be shown outside of this mode.
*
* This controller shows and hides the notification dot in the status bar to indicate
- * whether there are notifications when the device is in {@link View.SYSTEM_UI_FLAG_LOW_PROFILE}.
+ * whether there are notifications when the device is in {@link View#SYSTEM_UI_FLAG_LOW_PROFILE}.
*/
@StatusBarFragmentScope
public class LightsOutNotifController extends ViewController<View> {
private final CommandQueue mCommandQueue;
- private final NotificationEntryManager mEntryManager;
+ private final NotifLiveDataStore mNotifDataStore;
private final WindowManager mWindowManager;
+ private final Observer<Boolean> mObserver = hasNotifs -> updateLightsOutView();
- /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int) */
+ /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
@VisibleForTesting @Appearance int mAppearance;
private int mDisplayId;
@@ -66,18 +65,18 @@ public class LightsOutNotifController extends ViewController<View> {
LightsOutNotifController(
@Named(LIGHTS_OUT_NOTIF_VIEW) View lightsOutNotifView,
WindowManager windowManager,
- NotificationEntryManager entryManager,
+ NotifLiveDataStore notifDataStore,
CommandQueue commandQueue) {
super(lightsOutNotifView);
mWindowManager = windowManager;
- mEntryManager = entryManager;
+ mNotifDataStore = notifDataStore;
mCommandQueue = commandQueue;
}
@Override
protected void onViewDetached() {
- mEntryManager.removeNotificationEntryListener(mEntryListener);
+ mNotifDataStore.getHasActiveNotifs().removeObserver(mObserver);
mCommandQueue.removeCallback(mCallback);
}
@@ -87,14 +86,14 @@ public class LightsOutNotifController extends ViewController<View> {
mView.setAlpha(0f);
mDisplayId = mWindowManager.getDefaultDisplay().getDisplayId();
- mEntryManager.addNotificationEntryListener(mEntryListener);
+ mNotifDataStore.getHasActiveNotifs().addSyncObserver(mObserver);
mCommandQueue.addCallback(mCallback);
updateLightsOutView();
}
private boolean hasActiveNotifications() {
- return mEntryManager.hasActiveNotifications();
+ return mNotifDataStore.getHasActiveNotifs().getValue();
}
@VisibleForTesting
@@ -153,23 +152,4 @@ public class LightsOutNotifController extends ViewController<View> {
updateLightsOutView();
}
};
-
- private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
- // Cares about notifications post-filtering
- @Override
- public void onNotificationAdded(NotificationEntry entry) {
- updateLightsOutView();
- }
-
- @Override
- public void onPostEntryUpdated(NotificationEntry entry) {
- updateLightsOutView();
- }
-
- @Override
- public void onEntryRemoved(@Nullable NotificationEntry entry,
- NotificationVisibility visibility, boolean removedByUser, int reason) {
- updateLightsOutView();
- }
- };
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 863ce5758f9e..ff86d74a86eb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -660,14 +660,6 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
// --------------------- NotificationEntryManager/NotifPipeline methods ------------------------
- private int getVisibleNotificationsCount() {
- if (mNotifPipelineFlags.isNewPipelineEnabled()) {
- return mNotifPipeline.getShadeListCount();
- } else {
- return mEntryManager.getActiveNotificationsCount();
- }
- }
-
/**
* Public builder for {@link StatusBarNotificationActivityStarter}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt b/packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
index 0f4193e94196..4f20067dc0ed 100644
--- a/packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
@@ -39,9 +39,17 @@ class ListenerSet<E> : Iterable<E> {
fun remove(element: E): Boolean = listeners.remove(element)
/**
+ * Determine if the listener set is empty
+ */
+ fun isEmpty(): Boolean = listeners.isEmpty()
+
+ /**
* Returns an iterator over the listeners currently in the set. Note that to ensure
* [ConcurrentModificationException] is never thrown, this iterator will not reflect changes
* made to the set after the iterator is constructed.
*/
override fun iterator(): Iterator<E> = listeners.iterator()
}
+
+/** Extension to match Collection which is implemented to only be (easily) accessible in kotlin */
+fun <T> ListenerSet<T>.isNotEmpty(): Boolean = !isEmpty()
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 f62de5159f54..dc83c0d08291 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
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.NotificationRemoveInterceptor;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreMocksKt;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
@@ -201,6 +202,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mLeakDetector,
mock(ForegroundServiceDismissalFeatureController.class),
mock(IStatusBarService.class),
+ NotifLiveDataStoreMocksKt.createNotifLiveDataStoreImplMock(),
mock(DumpManager.class)
);
mEntryManager.initialize(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java
index 2971c05487c6..b45d78d5502d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryBuilder.java
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.notification.collection;
import androidx.annotation.Nullable;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
+
import java.util.ArrayList;
import java.util.List;
@@ -28,6 +30,7 @@ public class GroupEntryBuilder {
private String mKey = "test_group_key";
private long mCreationTime = 0;
@Nullable private GroupEntry mParent = GroupEntry.ROOT_ENTRY;
+ private NotifSection mNotifSection;
private NotificationEntry mSummary = null;
private List<NotificationEntry> mChildren = new ArrayList<>();
@@ -35,6 +38,7 @@ public class GroupEntryBuilder {
public GroupEntry build() {
GroupEntry ge = new GroupEntry(mKey, mCreationTime);
ge.setParent(mParent);
+ ge.getAttachState().setSection(mNotifSection);
ge.setSummary(mSummary);
mSummary.setParent(ge);
@@ -61,6 +65,11 @@ public class GroupEntryBuilder {
return this;
}
+ public GroupEntryBuilder setSection(@Nullable NotifSection section) {
+ mNotifSection = section;
+ return this;
+ }
+
public GroupEntryBuilder setSummary(
NotificationEntry summary) {
mSummary = summary;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
new file mode 100644
index 000000000000..892575ab6c71
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2021 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
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.lifecycle.Observer
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.eq
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotifLiveDataImplTest : SysuiTestCase() {
+
+ private val executor = FakeExecutor(FakeSystemClock())
+ private val liveDataImpl: NotifLiveDataImpl<Int> = NotifLiveDataImpl("tst", 9, executor)
+ private val syncObserver: Observer<Int> = mock()
+ private val asyncObserver: Observer<Int> = mock()
+
+ @Before
+ fun setup() {
+ allowTestableLooperAsMainThread()
+ liveDataImpl.addSyncObserver(syncObserver)
+ liveDataImpl.addAsyncObserver(asyncObserver)
+ }
+
+ @Test
+ fun testGetInitialValue() {
+ assertThat(liveDataImpl.value).isEqualTo(9)
+ }
+
+ @Test
+ fun testGetModifiedValue() {
+ liveDataImpl.value = 13
+ assertThat(liveDataImpl.value).isEqualTo(13)
+ }
+
+ @Test
+ fun testGetsModifiedValueFromWithinSyncObserver() {
+ liveDataImpl.addSyncObserver { intVal ->
+ assertThat(intVal).isEqualTo(13)
+ assertThat(liveDataImpl.value).isEqualTo(13)
+ }
+ liveDataImpl.value = 13
+ }
+
+ @Test
+ fun testDoesNotAlertsRemovedObservers() {
+ liveDataImpl.removeObserver(syncObserver)
+ liveDataImpl.removeObserver(asyncObserver)
+
+ liveDataImpl.value = 13
+
+ // There should be no runnables on the executor
+ assertThat(executor.runAllReady()).isEqualTo(0)
+
+ // And observers should not be called
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+ }
+
+ @Test
+ fun testDoesNotAsyncObserversRemovedSinceChange() {
+ liveDataImpl.value = 13
+ liveDataImpl.removeObserver(asyncObserver)
+
+ // There should be a runnable that will get executed...
+ assertThat(executor.runAllReady()).isEqualTo(1)
+
+ // ...but async observers should not be called
+ verifyNoMoreInteractions(asyncObserver)
+ }
+
+ @Test
+ fun testAlertsObservers() {
+ liveDataImpl.value = 13
+
+ // Verify that the synchronous observer is called immediately
+ verify(syncObserver).onChanged(eq(13))
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+
+ // Verify that the asynchronous observer is called when the executor runs
+ assertThat(executor.runAllReady()).isEqualTo(1)
+ verify(asyncObserver).onChanged(eq(13))
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+ }
+
+ @Test
+ fun testAlertsObserversFromDispatcher() {
+ // GIVEN that we use setValueAndProvideDispatcher()
+ val dispatcher = liveDataImpl.setValueAndProvideDispatcher(13)
+
+ // VERIFY that nothing is done before the dispatcher is called
+ assertThat(executor.numPending()).isEqualTo(0)
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+
+ // WHEN the dispatcher is invoked...
+ dispatcher.invoke()
+
+ // Verify that the synchronous observer is called immediately
+ verify(syncObserver).onChanged(eq(13))
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+
+ // Verify that the asynchronous observer is called when the executor runs
+ assertThat(executor.runAllReady()).isEqualTo(1)
+ verify(asyncObserver).onChanged(eq(13))
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+ }
+
+ @Test
+ fun testSkipsAllObserversIfValueDidNotChange() {
+ liveDataImpl.value = 9
+ // Does not add a runnable
+ assertThat(executor.runAllReady()).isEqualTo(0)
+ // Setting the current value does not call synchronous observers
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+ }
+
+ @Test
+ fun testSkipsAsyncObserversWhenValueTogglesBack() {
+ liveDataImpl.value = 13
+ liveDataImpl.value = 11
+ liveDataImpl.value = 9
+
+ // Synchronous observers will receive every change event immediately
+ inOrder(syncObserver).apply {
+ verify(syncObserver).onChanged(eq(13))
+ verify(syncObserver).onChanged(eq(11))
+ verify(syncObserver).onChanged(eq(9))
+ }
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+
+ // Running the first runnable on the queue will just emit the most recent value
+ assertThat(executor.runNextReady()).isTrue()
+ verify(asyncObserver).onChanged(eq(9))
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+
+ // Running the next 2 runnable will have no effect
+ assertThat(executor.runAllReady()).isEqualTo(2)
+ verifyNoMoreInteractions(syncObserver, asyncObserver)
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
new file mode 100644
index 000000000000..9c8ac5cded9e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2021 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
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.lang.UnsupportedOperationException
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotifLiveDataStoreImplTest : SysuiTestCase() {
+
+ private val executor = FakeExecutor(FakeSystemClock())
+ private val liveDataStoreImpl = NotifLiveDataStoreImpl(executor)
+
+ @Before
+ fun setup() {
+ allowTestableLooperAsMainThread()
+ }
+
+ @Test
+ fun testAllObserversSeeConsistentValues() {
+ val entry1 = NotificationEntryBuilder().setId(1).build()
+ val entry2 = NotificationEntryBuilder().setId(2).build()
+ val observer: (Any) -> Unit = {
+ assertThat(liveDataStoreImpl.hasActiveNotifs.value).isEqualTo(true)
+ assertThat(liveDataStoreImpl.activeNotifCount.value).isEqualTo(2)
+ assertThat(liveDataStoreImpl.activeNotifList.value).isEqualTo(listOf(entry1, entry2))
+ }
+ liveDataStoreImpl.hasActiveNotifs.addSyncObserver(observer)
+ liveDataStoreImpl.hasActiveNotifs.addAsyncObserver(observer)
+ liveDataStoreImpl.activeNotifCount.addSyncObserver(observer)
+ liveDataStoreImpl.activeNotifCount.addAsyncObserver(observer)
+ liveDataStoreImpl.activeNotifList.addSyncObserver(observer)
+ liveDataStoreImpl.activeNotifList.addAsyncObserver(observer)
+ liveDataStoreImpl.setActiveNotifList(listOf(entry1, entry2))
+ executor.runAllReady()
+ }
+
+ @Test
+ fun testOriginalListIsCopied() {
+ val entry1 = NotificationEntryBuilder().setId(1).build()
+ val entry2 = NotificationEntryBuilder().setId(2).build()
+ val mutableInputList = mutableListOf(entry1, entry2)
+ val observer: (Any) -> Unit = {
+ mutableInputList.clear()
+ assertThat(liveDataStoreImpl.hasActiveNotifs.value).isEqualTo(true)
+ assertThat(liveDataStoreImpl.activeNotifCount.value).isEqualTo(2)
+ assertThat(liveDataStoreImpl.activeNotifList.value).isEqualTo(listOf(entry1, entry2))
+ }
+ liveDataStoreImpl.hasActiveNotifs.addSyncObserver(observer)
+ liveDataStoreImpl.hasActiveNotifs.addAsyncObserver(observer)
+ liveDataStoreImpl.activeNotifCount.addSyncObserver(observer)
+ liveDataStoreImpl.activeNotifCount.addAsyncObserver(observer)
+ liveDataStoreImpl.activeNotifList.addSyncObserver(observer)
+ liveDataStoreImpl.activeNotifList.addAsyncObserver(observer)
+ liveDataStoreImpl.setActiveNotifList(mutableInputList)
+ executor.runAllReady()
+ }
+
+ @Test
+ fun testProvidedListIsUnmodifiable() {
+ val entry1 = NotificationEntryBuilder().setId(1).build()
+ val entry2 = NotificationEntryBuilder().setId(2).build()
+ val observer: (List<NotificationEntry>) -> Unit = { providedValue ->
+ val provided = providedValue as MutableList<NotificationEntry>
+ Assert.assertThrows(UnsupportedOperationException::class.java) {
+ provided.clear()
+ }
+ val current = liveDataStoreImpl.activeNotifList.value as MutableList<NotificationEntry>
+ Assert.assertThrows(UnsupportedOperationException::class.java) {
+ current.clear()
+ }
+ assertThat(liveDataStoreImpl.activeNotifList.value).isEqualTo(listOf(entry1, entry2))
+ }
+ liveDataStoreImpl.activeNotifList.addSyncObserver(observer)
+ liveDataStoreImpl.activeNotifList.addAsyncObserver(observer)
+ liveDataStoreImpl.setActiveNotifList(mutableListOf(entry1, entry2))
+ executor.runAllReady()
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt
new file mode 100644
index 000000000000..6e81c69045ce
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreMocks.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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
+
+import com.android.systemui.util.mockito.mock
+import org.mockito.Mockito.`when` as whenever
+
+/** Creates a mock which returns mocks for the NotifLiveDataImpl fields. */
+fun createNotifLiveDataStoreImplMock(): NotifLiveDataStoreImpl {
+ val dataStoreImpl: NotifLiveDataStoreImpl = mock()
+ whenever(dataStoreImpl.hasActiveNotifs).thenReturn(mock())
+ whenever(dataStoreImpl.activeNotifCount).thenReturn(mock())
+ whenever(dataStoreImpl.activeNotifList).thenReturn(mock())
+ return dataStoreImpl
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt
deleted file mode 100644
index 287f50c4202a..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2019 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
-
-import android.testing.AndroidTestingRunner
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.statusbar.notification.collection.render.RenderStageManager
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.MockitoAnnotations
-import org.mockito.Mockito.`when` as whenever
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-class NotifPipelineTest : SysuiTestCase() {
-
- @Mock private lateinit var notifCollection: NotifCollection
- @Mock private lateinit var shadeListBuilder: ShadeListBuilder
- @Mock private lateinit var renderStageManager: RenderStageManager
- private lateinit var notifPipeline: NotifPipeline
-
- @Before
- fun setup() {
- MockitoAnnotations.initMocks(this)
- notifPipeline = NotifPipeline(notifCollection, shadeListBuilder, renderStageManager)
- whenever(shadeListBuilder.shadeList).thenReturn(listOf(
- NotificationEntryBuilder().setPkg("foo").setId(1).build(),
- NotificationEntryBuilder().setPkg("foo").setId(2).build(),
- group(
- NotificationEntryBuilder().setPkg("bar").setId(1).build(),
- NotificationEntryBuilder().setPkg("bar").setId(2).build(),
- NotificationEntryBuilder().setPkg("bar").setId(3).build(),
- NotificationEntryBuilder().setPkg("bar").setId(4).build()
- ),
- NotificationEntryBuilder().setPkg("baz").setId(1).build()
- ))
- }
-
- private fun group(summary: NotificationEntry, vararg children: NotificationEntry): GroupEntry {
- return GroupEntry(summary.key, summary.creationTime).also { group ->
- group.summary = summary
- for (it in children) {
- group.addChild(it)
- }
- }
- }
-
- @Test
- fun testGetShadeListCount() {
- assertThat(notifPipeline.getShadeListCount()).isEqualTo(7)
- }
-
- @Test
- fun testGetFlatShadeList() {
- assertThat(notifPipeline.getFlatShadeList().map { it.key }).containsExactly(
- "0|foo|1|null|0",
- "0|foo|2|null|0",
- "0|bar|1|null|0",
- "0|bar|2|null|0",
- "0|bar|3|null|0",
- "0|bar|4|null|0",
- "0|baz|1|null|0"
- ).inOrder()
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
new file mode 100644
index 000000000000..59fc591e4d06
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2021 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.coordinator
+
+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.GroupEntryBuilder
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreImpl
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations.initMocks
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class DataStoreCoordinatorTest : SysuiTestCase() {
+ private lateinit var coordinator: DataStoreCoordinator
+ private lateinit var afterRenderListListener: OnAfterRenderListListener
+
+ private lateinit var entry: NotificationEntry
+
+ @Mock private lateinit var pipeline: NotifPipeline
+ @Mock private lateinit var notifLiveDataStoreImpl: NotifLiveDataStoreImpl
+ @Mock private lateinit var stackController: NotifStackController
+ @Mock private lateinit var section: NotifSection
+
+ @Before
+ fun setUp() {
+ initMocks(this)
+ entry = NotificationEntryBuilder().setSection(section).build()
+ coordinator = DataStoreCoordinator(notifLiveDataStoreImpl)
+ coordinator.attach(pipeline)
+ afterRenderListListener = withArgCaptor {
+ verify(pipeline).addOnAfterRenderListListener(capture())
+ }
+ }
+
+ @Test
+ fun testUpdateDataStore_withOneEntry() {
+ afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+ verify(notifLiveDataStoreImpl).setActiveNotifList(eq(listOf(entry)))
+ verifyNoMoreInteractions(notifLiveDataStoreImpl)
+ }
+
+ @Test
+ fun testUpdateDataStore_withGroups() {
+ afterRenderListListener.onAfterRenderList(
+ listOf(
+ notificationEntry("foo", 1),
+ notificationEntry("foo", 2),
+ GroupEntryBuilder().setSummary(
+ notificationEntry("bar", 1)
+ ).setChildren(
+ listOf(
+ notificationEntry("bar", 2),
+ notificationEntry("bar", 3),
+ notificationEntry("bar", 4)
+ )
+ ).setSection(section).build(),
+ notificationEntry("baz", 1)
+ ),
+ stackController
+ )
+ val list: List<NotificationEntry> = withArgCaptor {
+ verify(notifLiveDataStoreImpl).setActiveNotifList(capture())
+ }
+ assertThat(list.map { it.key }).containsExactly(
+ "0|foo|1|null|0",
+ "0|foo|2|null|0",
+ "0|bar|1|null|0",
+ "0|bar|2|null|0",
+ "0|bar|3|null|0",
+ "0|bar|4|null|0",
+ "0|baz|1|null|0"
+ ).inOrder()
+ verifyNoMoreInteractions(notifLiveDataStoreImpl)
+ }
+
+ private fun notificationEntry(pkg: String, id: Int) =
+ NotificationEntryBuilder().setPkg(pkg).setId(id).setSection(section).build()
+
+ @Test
+ fun testUpdateDataStore_withZeroEntries_whenNewPipelineEnabled() {
+ afterRenderListListener.onAfterRenderList(listOf(), stackController)
+ verify(notifLiveDataStoreImpl).setActiveNotifList(eq(listOf()))
+ verifyNoMoreInteractions(notifLiveDataStoreImpl)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java
index 395aec392021..2dfb9fc674ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java
@@ -46,6 +46,8 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifLiveData;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -65,6 +67,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
@@ -82,6 +85,8 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
// Dependency mocks:
@Mock private NotifPipelineFlags mNotifPipelineFlags;
+ @Mock private NotifLiveDataStore mNotifLiveDataStore;
+ @Mock private NotifLiveData<List<NotificationEntry>> mActiveNotifList;
@Mock private NotificationVisibilityProvider mVisibilityProvider;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotifPipeline mNotifPipeline;
@@ -97,6 +102,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ when(mNotifLiveDataStore.getActiveNotifList()).thenReturn(mActiveNotifList);
mEntry = new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
@@ -112,6 +118,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
mListener,
mUiBgExecutor,
mNotifPipelineFlags,
+ mNotifLiveDataStore,
mVisibilityProvider,
mEntryManager,
mNotifPipeline,
@@ -145,7 +152,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
any(NotificationVisibility[].class));
when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
- when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
mUiBgExecutor.runAllReady();
@@ -167,7 +174,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
public void testStoppingNotificationLoggingReportsCurrentNotifications()
throws Exception {
when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
- when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
mUiBgExecutor.runAllReady();
@@ -196,7 +203,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
@Test
public void testLogPanelShownOnWake() {
- when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
setStateAsleep();
mLogger.onDozingChanged(false); // Wake to lockscreen
assertEquals(1, mNotificationPanelLoggerFake.getCalls().size());
@@ -212,7 +219,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
@Test
public void testLogPanelShownOnShadePull() {
- when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(mEntry));
setStateAwake();
// Now expand panel
mLogger.onPanelExpandedChanged(true);
@@ -240,7 +247,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
.build();
entry.setRow(mRow);
- when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(entry));
+ when(mActiveNotifList.getValue()).thenReturn(Lists.newArrayList(entry));
setStateAsleep();
mLogger.onDozingChanged(false); // Wake to lockscreen
assertEquals(1, mNotificationPanelLoggerFake.getCalls().size());
@@ -254,6 +261,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
TestableNotificationLogger(NotificationListener notificationListener,
Executor uiBgExecutor,
NotifPipelineFlags notifPipelineFlags,
+ NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
@@ -264,6 +272,7 @@ public class NotificationLoggerLegacyTest extends SysuiTestCase {
notificationListener,
uiBgExecutor,
notifPipelineFlags,
+ notifLiveDataStore,
visibilityProvider,
entryManager,
notifPipeline,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index 3a9b29799988..4d861f96a943 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -46,6 +46,8 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifLiveData;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -65,6 +67,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
+import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
@@ -82,6 +85,8 @@ public class NotificationLoggerTest extends SysuiTestCase {
// Dependency mocks:
@Mock private NotifPipelineFlags mNotifPipelineFlags;
+ @Mock private NotifLiveDataStore mNotifLiveDataStore;
+ @Mock private NotifLiveData<List<NotificationEntry>> mActiveNotifEntries;
@Mock private NotificationVisibilityProvider mVisibilityProvider;
@Mock private NotificationEntryManager mEntryManager;
@Mock private NotifPipeline mNotifPipeline;
@@ -98,6 +103,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(true);
+ when(mNotifLiveDataStore.getActiveNotifList()).thenReturn(mActiveNotifEntries);
mEntry = new NotificationEntryBuilder()
.setPkg(TEST_PACKAGE_NAME)
@@ -113,6 +119,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
mListener,
mUiBgExecutor,
mNotifPipelineFlags,
+ mNotifLiveDataStore,
mVisibilityProvider,
mEntryManager,
mNotifPipeline,
@@ -146,7 +153,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
any(NotificationVisibility[].class));
when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
- when(mNotifPipeline.getFlatShadeList()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifEntries.getValue()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
mUiBgExecutor.runAllReady();
@@ -168,7 +175,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
public void testStoppingNotificationLoggingReportsCurrentNotifications()
throws Exception {
when(mListContainer.isInVisibleLocation(any())).thenReturn(true);
- when(mNotifPipeline.getFlatShadeList()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifEntries.getValue()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
mUiBgExecutor.runAllReady();
@@ -197,7 +204,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
@Test
public void testLogPanelShownOnWake() {
- when(mNotifPipeline.getFlatShadeList()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifEntries.getValue()).thenReturn(Lists.newArrayList(mEntry));
setStateAsleep();
mLogger.onDozingChanged(false); // Wake to lockscreen
assertEquals(1, mNotificationPanelLoggerFake.getCalls().size());
@@ -213,7 +220,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
@Test
public void testLogPanelShownOnShadePull() {
- when(mNotifPipeline.getFlatShadeList()).thenReturn(Lists.newArrayList(mEntry));
+ when(mActiveNotifEntries.getValue()).thenReturn(Lists.newArrayList(mEntry));
setStateAwake();
// Now expand panel
mLogger.onPanelExpandedChanged(true);
@@ -241,7 +248,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
.build();
entry.setRow(mRow);
- when(mNotifPipeline.getFlatShadeList()).thenReturn(Lists.newArrayList(entry));
+ when(mActiveNotifEntries.getValue()).thenReturn(Lists.newArrayList(entry));
setStateAsleep();
mLogger.onDozingChanged(false); // Wake to lockscreen
assertEquals(1, mNotificationPanelLoggerFake.getCalls().size());
@@ -255,6 +262,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
TestableNotificationLogger(NotificationListener notificationListener,
Executor uiBgExecutor,
NotifPipelineFlags notifPipelineFlags,
+ NotifLiveDataStore notifLiveDataStore,
NotificationVisibilityProvider visibilityProvider,
NotificationEntryManager entryManager,
NotifPipeline notifPipeline,
@@ -265,6 +273,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
notificationListener,
uiBgExecutor,
notifPipelineFlags,
+ notifLiveDataStore,
visibilityProvider,
entryManager,
notifPipeline,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index eeda9ddd1466..a890414115dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -68,6 +68,7 @@ import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStoreMocksKt;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
@@ -191,6 +192,7 @@ public class NotificationEntryManagerInflationTest extends SysuiTestCase {
mLeakDetector,
mock(ForegroundServiceDismissalFeatureController.class),
mock(IStatusBarService.class),
+ NotifLiveDataStoreMocksKt.createNotifLiveDataStoreImplMock(),
mock(DumpManager.class)
);
mEntryManager.initialize(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
index e386263be5a0..9664035e1e1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
@@ -16,14 +16,12 @@
package com.android.systemui.statusbar.phone;
-import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -34,13 +32,13 @@ import android.view.View;
import android.view.ViewPropertyAnimator;
import android.view.WindowManager;
+import androidx.lifecycle.Observer;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotifLiveData;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import org.junit.Before;
import org.junit.Test;
@@ -59,18 +57,19 @@ public class LightsOutNotifControllerTest extends SysuiTestCase {
private static final int LIGHTS_ON = 0;
private static final int LIGHTS_OUT = APPEARANCE_LOW_PROFILE_BARS;
- @Mock private NotificationEntryManager mEntryManager;
+ @Mock private NotifLiveData<Boolean> mHasActiveNotifs;
+ @Mock private NotifLiveDataStore mNotifLiveDataStore;
@Mock private CommandQueue mCommandQueue;
@Mock private WindowManager mWindowManager;
@Mock private Display mDisplay;
- @Captor private ArgumentCaptor<NotificationEntryListener> mListenerCaptor;
+ @Captor private ArgumentCaptor<Observer<Boolean>> mObserverCaptor;
@Captor private ArgumentCaptor<CommandQueue.Callbacks> mCallbacksCaptor;
private View mLightsOutView;
private LightsOutNotifController mLightsOutNotifController;
private int mDisplayId;
- private NotificationEntryListener mEntryListener;
+ private Observer<Boolean> mHaActiveNotifsObserver;
private CommandQueue.Callbacks mCallbacks;
@Before
@@ -80,15 +79,20 @@ public class LightsOutNotifControllerTest extends SysuiTestCase {
mLightsOutView = new View(mContext);
when(mWindowManager.getDefaultDisplay()).thenReturn(mDisplay);
when(mDisplay.getDisplayId()).thenReturn(mDisplayId);
+ when(mNotifLiveDataStore.getHasActiveNotifs()).thenReturn(mHasActiveNotifs);
+ when(mHasActiveNotifs.getValue()).thenReturn(false);
mLightsOutNotifController = new LightsOutNotifController(
- mLightsOutView, mWindowManager, mEntryManager, mCommandQueue);
+ mLightsOutView,
+ mWindowManager,
+ mNotifLiveDataStore,
+ mCommandQueue);
mLightsOutNotifController.init();
mLightsOutNotifController.onViewAttached();
// Capture the entry listener object so we can simulate events in tests below
- verify(mEntryManager).addNotificationEntryListener(mListenerCaptor.capture());
- mEntryListener = Objects.requireNonNull(mListenerCaptor.getValue());
+ verify(mHasActiveNotifs).addSyncObserver(mObserverCaptor.capture());
+ mHaActiveNotifsObserver = Objects.requireNonNull(mObserverCaptor.getValue());
// Capture the callback object so we can simulate callback events in tests below
verify(mCommandQueue).addCallback(mCallbacksCaptor.capture());
@@ -138,7 +142,7 @@ public class LightsOutNotifControllerTest extends SysuiTestCase {
@Test
public void testLightsOut_withNotifs_onSystemBarAttributesChanged() {
// GIVEN active visible notifications
- when(mEntryManager.hasActiveNotifications()).thenReturn(true);
+ when(mHasActiveNotifs.getValue()).thenReturn(true);
// WHEN lights out
mCallbacks.onSystemBarAttributesChanged(
@@ -158,7 +162,7 @@ public class LightsOutNotifControllerTest extends SysuiTestCase {
@Test
public void testLightsOut_withoutNotifs_onSystemBarAttributesChanged() {
// GIVEN no active visible notifications
- when(mEntryManager.hasActiveNotifications()).thenReturn(false);
+ when(mHasActiveNotifs.getValue()).thenReturn(false);
// WHEN lights out
mCallbacks.onSystemBarAttributesChanged(
@@ -178,7 +182,7 @@ public class LightsOutNotifControllerTest extends SysuiTestCase {
@Test
public void testLightsOn_afterLightsOut_onSystemBarAttributesChanged() {
// GIVEN active visible notifications
- when(mEntryManager.hasActiveNotifications()).thenReturn(true);
+ when(mHasActiveNotifs.getValue()).thenReturn(true);
// WHEN lights on
mCallbacks.onSystemBarAttributesChanged(
@@ -198,15 +202,15 @@ public class LightsOutNotifControllerTest extends SysuiTestCase {
@Test
public void testEntryAdded() {
// GIVEN no visible notifications and lights out
- when(mEntryManager.hasActiveNotifications()).thenReturn(false);
+ when(mHasActiveNotifs.getValue()).thenReturn(false);
mLightsOutNotifController.mAppearance = LIGHTS_OUT;
mLightsOutNotifController.updateLightsOutView();
assertIsShowingDot(false);
// WHEN an active notification is added
- when(mEntryManager.hasActiveNotifications()).thenReturn(true);
+ when(mHasActiveNotifs.getValue()).thenReturn(true);
assertTrue(mLightsOutNotifController.shouldShowDot());
- mEntryListener.onNotificationAdded(mock(NotificationEntry.class));
+ mHaActiveNotifsObserver.onChanged(true);
// THEN we should see the dot view
assertIsShowingDot(true);
@@ -215,38 +219,20 @@ public class LightsOutNotifControllerTest extends SysuiTestCase {
@Test
public void testEntryRemoved() {
// GIVEN a visible notification and lights out
- when(mEntryManager.hasActiveNotifications()).thenReturn(true);
+ when(mHasActiveNotifs.getValue()).thenReturn(true);
mLightsOutNotifController.mAppearance = LIGHTS_OUT;
mLightsOutNotifController.updateLightsOutView();
assertIsShowingDot(true);
// WHEN all active notifications are removed
- when(mEntryManager.hasActiveNotifications()).thenReturn(false);
+ when(mHasActiveNotifs.getValue()).thenReturn(false);
assertFalse(mLightsOutNotifController.shouldShowDot());
- mEntryListener.onEntryRemoved(
- mock(NotificationEntry.class), null, false, REASON_CANCEL_ALL);
+ mHaActiveNotifsObserver.onChanged(false);
// THEN we shouldn't see the dot view
assertIsShowingDot(false);
}
- @Test
- public void testEntryUpdated() {
- // GIVEN no visible notifications and lights out
- when(mEntryManager.hasActiveNotifications()).thenReturn(false);
- mLightsOutNotifController.mAppearance = LIGHTS_OUT;
- mLightsOutNotifController.updateLightsOutView();
- assertIsShowingDot(false);
-
- // WHEN an active notification is added
- when(mEntryManager.hasActiveNotifications()).thenReturn(true);
- assertTrue(mLightsOutNotifController.shouldShowDot());
- mEntryListener.onPostEntryUpdated(mock(NotificationEntry.class));
-
- // THEN we should see the dot view
- assertIsShowingDot(true);
- }
-
private void assertIsShowingDot(boolean isShowing) {
// cancel the animation so we can check the end state
final ViewPropertyAnimator animation = mLightsOutView.animate();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 0289b9aff062..9d5b17ea6738 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -119,6 +119,7 @@ import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -274,6 +275,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
@Mock private ActivityLaunchAnimator mActivityLaunchAnimator;
@Mock private NotifPipelineFlags mNotifPipelineFlags;
+ @Mock private NotifLiveDataStore mNotifLiveDataStore;
private ShadeController mShadeController;
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -306,6 +308,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationListener,
mUiBgExecutor,
mNotifPipelineFlags,
+ mNotifLiveDataStore,
mVisibilityProvider,
mock(NotificationEntryManager.class),
mock(NotifPipeline.class),