Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1cbefacd authored by Jeff DeCew's avatar Jeff DeCew Committed by Automerger Merge Worker
Browse files

Merge "Formalize CoreCoordinators" into udc-dev am: e7482b5c

parents 18499214 e7482b5c
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -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,
@@ -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] */
@@ -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)
@@ -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
+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
+7 −2
Original line number Diff line number Diff line
@@ -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
@@ -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)
    }
+8 −8
Original line number Diff line number Diff line
@@ -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
@@ -32,7 +31,6 @@ interface NotifCoordinators : Coordinator, PipelineDumpable

@CoordinatorScope
class NotifCoordinatorsImpl @Inject constructor(
        notifPipelineFlags: NotifPipelineFlags,
        sectionStyleProvider: SectionStyleProvider,
        dataStoreCoordinator: DataStoreCoordinator,
        hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
@@ -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()

@@ -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)
@@ -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)
        }
@@ -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 {
+14 −21
Original line number Diff line number Diff line
@@ -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()