Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt +13 −2 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import javax.inject.Inject @SysUISingleton class NotifLiveDataStoreImpl @Inject constructor( @Main private val mainExecutor: Executor ) : NotifLiveDataStore { ) : NotifLiveDataStore, PipelineDumpable { private val hasActiveNotifsPrivate = NotifLiveDataImpl( name = "hasActiveNotifs", initialValue = false, Loading Loading @@ -66,6 +66,12 @@ class NotifLiveDataStoreImpl @Inject constructor( ).forEach { dispatcher -> dispatcher.invoke() } } } override fun dumpPipeline(d: PipelineDumper) { d.dump("activeNotifListPrivate", activeNotifListPrivate) d.dump("activeNotifCountPrivate", activeNotifCountPrivate) d.dump("hasActiveNotifsPrivate", hasActiveNotifsPrivate) } } /** Read-write implementation of [NotifLiveData] */ Loading @@ -73,7 +79,7 @@ class NotifLiveDataImpl<T>( private val name: String, initialValue: T, @Main private val mainExecutor: Executor ) : NotifLiveData<T> { ) : NotifLiveData<T>, PipelineDumpable { private val syncObservers = ListenerSet<Observer<T>>() private val asyncObservers = ListenerSet<Observer<T>>() private val atomicValue = AtomicReference(initialValue) Loading Loading @@ -134,4 +140,9 @@ class NotifLiveDataImpl<T>( syncObservers.remove(observer) asyncObservers.remove(observer) } override fun dumpPipeline(d: PipelineDumper) { d.dump("syncObservers", syncObservers) d.dump("asyncObservers", asyncObservers) } } No newline at end of file packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CoreCoordinator.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.PipelineDumpable /** * A special type of [Coordinator] that is also a core part of the pipeline, and so is also a * [PipelineDumpable]. */ interface CoreCoordinator : Coordinator, PipelineDumpable packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt +7 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ 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.PipelineDumper import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.render.requireSummary import javax.inject.Inject Loading @@ -32,13 +33,17 @@ import javax.inject.Inject @CoordinatorScope class DataStoreCoordinator @Inject internal constructor( private val notifLiveDataStoreImpl: NotifLiveDataStoreImpl ) : Coordinator { ) : CoreCoordinator { override fun attach(pipeline: NotifPipeline) { pipeline.addOnAfterRenderListListener { entries, _ -> onAfterRenderList(entries) } } fun onAfterRenderList(entries: List<ListEntry>) { override fun dumpPipeline(d: PipelineDumper) { d.dump("notifLiveDataStoreImpl", notifLiveDataStoreImpl) } private fun onAfterRenderList(entries: List<ListEntry>) { val flatEntryList = flattenedEntryList(entries) notifLiveDataStoreImpl.setActiveNotifList(flatEntryList) } Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +8 −8 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.systemui.statusbar.notification.NotifPipelineFlags import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumper Loading @@ -32,7 +31,6 @@ interface NotifCoordinators : Coordinator, PipelineDumpable @CoordinatorScope class NotifCoordinatorsImpl @Inject constructor( notifPipelineFlags: NotifPipelineFlags, sectionStyleProvider: SectionStyleProvider, dataStoreCoordinator: DataStoreCoordinator, hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator, Loading Loading @@ -61,6 +59,7 @@ class NotifCoordinatorsImpl @Inject constructor( dismissibilityCoordinator: DismissibilityCoordinator, ) : NotifCoordinators { private val mCoreCoordinators: MutableList<CoreCoordinator> = ArrayList() private val mCoordinators: MutableList<Coordinator> = ArrayList() private val mOrderedSections: MutableList<NotifSectioner> = ArrayList() Loading @@ -68,11 +67,8 @@ class NotifCoordinatorsImpl @Inject constructor( * Creates all the coordinators. */ init { // 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. mCoordinators.add(dataStoreCoordinator) // Attach core coordinators. mCoreCoordinators.add(dataStoreCoordinator) // Attach normal coordinators. mCoordinators.add(hideLocallyDismissedNotifsCoordinator) Loading Loading @@ -122,6 +118,9 @@ class NotifCoordinatorsImpl @Inject constructor( * [Pluggable]s, [NotifCollectionListener]s and [NotifLifetimeExtender]s. */ override fun attach(pipeline: NotifPipeline) { for (c in mCoreCoordinators) { c.attach(pipeline) } for (c in mCoordinators) { c.attach(pipeline) } Loading @@ -133,7 +132,8 @@ class NotifCoordinatorsImpl @Inject constructor( * as they are dumped in the RenderStageManager instead. */ override fun dumpPipeline(d: PipelineDumper) = with(d) { dump("coordinators", mCoordinators) dump("core coordinators", mCoreCoordinators) dump("normal coordinators", mCoordinators) } companion object { Loading packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt +14 −21 Original line number Diff line number Diff line Loading @@ -22,34 +22,27 @@ import java.util.concurrent.CopyOnWriteArrayList * A collection of listeners, observers, callbacks, etc. * * This container is optimized for infrequent mutation and frequent iteration, with thread safety * and reentrant-safety guarantees as well. * and reentrant-safety guarantees as well. Specifically, to ensure that * [ConcurrentModificationException] is never thrown, this iterator will not reflect changes made to * the set after the iterator is constructed. */ class ListenerSet<E> : Iterable<E> { private val listeners: CopyOnWriteArrayList<E> = CopyOnWriteArrayList() class ListenerSet<E : Any> /** Private constructor takes the internal list so that we can use auto-delegation */ private constructor(private val listeners: CopyOnWriteArrayList<E>) : Collection<E> by listeners, Set<E> { /** Create a new instance */ constructor() : this(CopyOnWriteArrayList()) /** * A thread-safe, reentrant-safe method to add a listener. * Does nothing if the listener is already in the set. * A thread-safe, reentrant-safe method to add a listener. Does nothing if the listener is * already in the set. */ fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(element) /** * A thread-safe, reentrant-safe method to remove a listener. */ /** A thread-safe, reentrant-safe method to remove a listener. */ 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() fun <T : Any> ListenerSet<T>.isNotEmpty(): Boolean = !isEmpty() Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt +13 −2 Original line number Diff line number Diff line Loading @@ -32,7 +32,7 @@ import javax.inject.Inject @SysUISingleton class NotifLiveDataStoreImpl @Inject constructor( @Main private val mainExecutor: Executor ) : NotifLiveDataStore { ) : NotifLiveDataStore, PipelineDumpable { private val hasActiveNotifsPrivate = NotifLiveDataImpl( name = "hasActiveNotifs", initialValue = false, Loading Loading @@ -66,6 +66,12 @@ class NotifLiveDataStoreImpl @Inject constructor( ).forEach { dispatcher -> dispatcher.invoke() } } } override fun dumpPipeline(d: PipelineDumper) { d.dump("activeNotifListPrivate", activeNotifListPrivate) d.dump("activeNotifCountPrivate", activeNotifCountPrivate) d.dump("hasActiveNotifsPrivate", hasActiveNotifsPrivate) } } /** Read-write implementation of [NotifLiveData] */ Loading @@ -73,7 +79,7 @@ class NotifLiveDataImpl<T>( private val name: String, initialValue: T, @Main private val mainExecutor: Executor ) : NotifLiveData<T> { ) : NotifLiveData<T>, PipelineDumpable { private val syncObservers = ListenerSet<Observer<T>>() private val asyncObservers = ListenerSet<Observer<T>>() private val atomicValue = AtomicReference(initialValue) Loading Loading @@ -134,4 +140,9 @@ class NotifLiveDataImpl<T>( syncObservers.remove(observer) asyncObservers.remove(observer) } override fun dumpPipeline(d: PipelineDumper) { d.dump("syncObservers", syncObservers) d.dump("asyncObservers", asyncObservers) } } No newline at end of file
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CoreCoordinator.kt 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.PipelineDumpable /** * A special type of [Coordinator] that is also a core part of the pipeline, and so is also a * [PipelineDumpable]. */ interface CoreCoordinator : Coordinator, PipelineDumpable
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt +7 −2 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ 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.PipelineDumper import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.render.requireSummary import javax.inject.Inject Loading @@ -32,13 +33,17 @@ import javax.inject.Inject @CoordinatorScope class DataStoreCoordinator @Inject internal constructor( private val notifLiveDataStoreImpl: NotifLiveDataStoreImpl ) : Coordinator { ) : CoreCoordinator { override fun attach(pipeline: NotifPipeline) { pipeline.addOnAfterRenderListListener { entries, _ -> onAfterRenderList(entries) } } fun onAfterRenderList(entries: List<ListEntry>) { override fun dumpPipeline(d: PipelineDumper) { d.dump("notifLiveDataStoreImpl", notifLiveDataStoreImpl) } private fun onAfterRenderList(entries: List<ListEntry>) { val flatEntryList = flattenedEntryList(entries) notifLiveDataStoreImpl.setActiveNotifList(flatEntryList) } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt +8 −8 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ package com.android.systemui.statusbar.notification.collection.coordinator import com.android.systemui.statusbar.notification.NotifPipelineFlags import com.android.systemui.statusbar.notification.collection.NotifPipeline import com.android.systemui.statusbar.notification.collection.PipelineDumpable import com.android.systemui.statusbar.notification.collection.PipelineDumper Loading @@ -32,7 +31,6 @@ interface NotifCoordinators : Coordinator, PipelineDumpable @CoordinatorScope class NotifCoordinatorsImpl @Inject constructor( notifPipelineFlags: NotifPipelineFlags, sectionStyleProvider: SectionStyleProvider, dataStoreCoordinator: DataStoreCoordinator, hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator, Loading Loading @@ -61,6 +59,7 @@ class NotifCoordinatorsImpl @Inject constructor( dismissibilityCoordinator: DismissibilityCoordinator, ) : NotifCoordinators { private val mCoreCoordinators: MutableList<CoreCoordinator> = ArrayList() private val mCoordinators: MutableList<Coordinator> = ArrayList() private val mOrderedSections: MutableList<NotifSectioner> = ArrayList() Loading @@ -68,11 +67,8 @@ class NotifCoordinatorsImpl @Inject constructor( * Creates all the coordinators. */ init { // 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. mCoordinators.add(dataStoreCoordinator) // Attach core coordinators. mCoreCoordinators.add(dataStoreCoordinator) // Attach normal coordinators. mCoordinators.add(hideLocallyDismissedNotifsCoordinator) Loading Loading @@ -122,6 +118,9 @@ class NotifCoordinatorsImpl @Inject constructor( * [Pluggable]s, [NotifCollectionListener]s and [NotifLifetimeExtender]s. */ override fun attach(pipeline: NotifPipeline) { for (c in mCoreCoordinators) { c.attach(pipeline) } for (c in mCoordinators) { c.attach(pipeline) } Loading @@ -133,7 +132,8 @@ class NotifCoordinatorsImpl @Inject constructor( * as they are dumped in the RenderStageManager instead. */ override fun dumpPipeline(d: PipelineDumper) = with(d) { dump("coordinators", mCoordinators) dump("core coordinators", mCoreCoordinators) dump("normal coordinators", mCoordinators) } companion object { Loading
packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt +14 −21 Original line number Diff line number Diff line Loading @@ -22,34 +22,27 @@ import java.util.concurrent.CopyOnWriteArrayList * A collection of listeners, observers, callbacks, etc. * * This container is optimized for infrequent mutation and frequent iteration, with thread safety * and reentrant-safety guarantees as well. * and reentrant-safety guarantees as well. Specifically, to ensure that * [ConcurrentModificationException] is never thrown, this iterator will not reflect changes made to * the set after the iterator is constructed. */ class ListenerSet<E> : Iterable<E> { private val listeners: CopyOnWriteArrayList<E> = CopyOnWriteArrayList() class ListenerSet<E : Any> /** Private constructor takes the internal list so that we can use auto-delegation */ private constructor(private val listeners: CopyOnWriteArrayList<E>) : Collection<E> by listeners, Set<E> { /** Create a new instance */ constructor() : this(CopyOnWriteArrayList()) /** * A thread-safe, reentrant-safe method to add a listener. * Does nothing if the listener is already in the set. * A thread-safe, reentrant-safe method to add a listener. Does nothing if the listener is * already in the set. */ fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(element) /** * A thread-safe, reentrant-safe method to remove a listener. */ /** A thread-safe, reentrant-safe method to remove a listener. */ 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() fun <T : Any> ListenerSet<T>.isNotEmpty(): Boolean = !isEmpty()