Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt +0 −1 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ 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 Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt +0 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.util.Assert import com.android.systemui.util.ListenerSet import com.android.systemui.util.isNotEmpty import java.io.PrintWriter import javax.inject.Inject Loading packages/SystemUI/src/com/android/systemui/util/IListenerSet.kt 0 → 100644 +36 −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.util /** * 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. Specifically, to ensure that * [ConcurrentModificationException] is never thrown, this iterator will not reflect changes made to * the set after the iterator is constructed. */ interface IListenerSet<E : Any> : Set<E> { /** * 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 /** A thread-safe, reentrant-safe method to remove a listener. */ fun remove(element: E): Boolean } packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt +3 −11 Original line number Diff line number Diff line Loading @@ -29,20 +29,12 @@ import java.util.concurrent.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> { Collection<E> by listeners, IListenerSet<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. */ fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(element) override fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(element) /** A thread-safe, reentrant-safe method to remove a listener. */ fun remove(element: E): Boolean = listeners.remove(element) override fun remove(element: E): Boolean = listeners.remove(element) } /** Extension to match Collection which is implemented to only be (easily) accessible in kotlin */ fun <T : Any> ListenerSet<T>.isNotEmpty(): Boolean = !isEmpty() packages/SystemUI/src/com/android/systemui/util/NamedListenerSet.kt 0 → 100644 +96 −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.util import java.util.concurrent.CopyOnWriteArrayList import java.util.function.Consumer /** * 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. Specifically, to ensure that * [ConcurrentModificationException] is never thrown, this iterator will not reflect changes made to * the set after the iterator is constructed. * * This class provides all the abilities of [ListenerSet], except that each listener has a name * calculated at runtime which can be used for time-efficient tracing of listener invocations. */ class NamedListenerSet<E : Any>( private val getName: (E) -> String = { it.javaClass.name }, ) : IListenerSet<E> { private val listeners = CopyOnWriteArrayList<NamedListener>() override val size: Int get() = listeners.size override fun isEmpty() = listeners.isEmpty() override fun iterator(): Iterator<E> = iterator { listeners.iterator().forEach { yield(it.listener) } } override fun containsAll(elements: Collection<E>) = listeners.count { it.listener in elements } == elements.size override fun contains(element: E) = listeners.firstOrNull { it.listener == element } != null override fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(NamedListener(element)) override fun remove(element: E): Boolean = listeners.removeIf { it.listener == element } /** A wrapper for the listener with an associated name. */ inner class NamedListener(val listener: E) { val name: String = getName(listener) override fun hashCode(): Int { return listener.hashCode() } override fun equals(other: Any?): Boolean = when { other === null -> false other === this -> true other !is NamedListenerSet<*>.NamedListener -> false listener == other.listener -> true else -> false } } /** Iterate the listeners in the set, providing the name for each one as well. */ inline fun forEachNamed(block: (String, E) -> Unit) = namedIterator().forEach { element -> block(element.name, element.listener) } /** * Iterate the listeners in the set, wrapping each call to the block with [traceSection] using * the listener name. */ inline fun forEachTraced(block: (E) -> Unit) = forEachNamed { name, listener -> traceSection(name) { block(listener) } } /** * Iterate the listeners in the set, wrapping each call to the block with [traceSection] using * the listener name. */ fun forEachTraced(consumer: Consumer<E>) = forEachNamed { name, listener -> traceSection(name) { consumer.accept(listener) } } /** Iterate over the [NamedListener]s currently in the set. */ fun namedIterator(): Iterator<NamedListener> = listeners.iterator() } Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt +0 −1 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ 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 Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt +0 −1 Original line number Diff line number Diff line Loading @@ -26,7 +26,6 @@ import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.util.Assert import com.android.systemui.util.ListenerSet import com.android.systemui.util.isNotEmpty import java.io.PrintWriter import javax.inject.Inject Loading
packages/SystemUI/src/com/android/systemui/util/IListenerSet.kt 0 → 100644 +36 −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.util /** * 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. Specifically, to ensure that * [ConcurrentModificationException] is never thrown, this iterator will not reflect changes made to * the set after the iterator is constructed. */ interface IListenerSet<E : Any> : Set<E> { /** * 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 /** A thread-safe, reentrant-safe method to remove a listener. */ fun remove(element: E): Boolean }
packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt +3 −11 Original line number Diff line number Diff line Loading @@ -29,20 +29,12 @@ import java.util.concurrent.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> { Collection<E> by listeners, IListenerSet<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. */ fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(element) override fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(element) /** A thread-safe, reentrant-safe method to remove a listener. */ fun remove(element: E): Boolean = listeners.remove(element) override fun remove(element: E): Boolean = listeners.remove(element) } /** Extension to match Collection which is implemented to only be (easily) accessible in kotlin */ fun <T : Any> ListenerSet<T>.isNotEmpty(): Boolean = !isEmpty()
packages/SystemUI/src/com/android/systemui/util/NamedListenerSet.kt 0 → 100644 +96 −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.util import java.util.concurrent.CopyOnWriteArrayList import java.util.function.Consumer /** * 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. Specifically, to ensure that * [ConcurrentModificationException] is never thrown, this iterator will not reflect changes made to * the set after the iterator is constructed. * * This class provides all the abilities of [ListenerSet], except that each listener has a name * calculated at runtime which can be used for time-efficient tracing of listener invocations. */ class NamedListenerSet<E : Any>( private val getName: (E) -> String = { it.javaClass.name }, ) : IListenerSet<E> { private val listeners = CopyOnWriteArrayList<NamedListener>() override val size: Int get() = listeners.size override fun isEmpty() = listeners.isEmpty() override fun iterator(): Iterator<E> = iterator { listeners.iterator().forEach { yield(it.listener) } } override fun containsAll(elements: Collection<E>) = listeners.count { it.listener in elements } == elements.size override fun contains(element: E) = listeners.firstOrNull { it.listener == element } != null override fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(NamedListener(element)) override fun remove(element: E): Boolean = listeners.removeIf { it.listener == element } /** A wrapper for the listener with an associated name. */ inner class NamedListener(val listener: E) { val name: String = getName(listener) override fun hashCode(): Int { return listener.hashCode() } override fun equals(other: Any?): Boolean = when { other === null -> false other === this -> true other !is NamedListenerSet<*>.NamedListener -> false listener == other.listener -> true else -> false } } /** Iterate the listeners in the set, providing the name for each one as well. */ inline fun forEachNamed(block: (String, E) -> Unit) = namedIterator().forEach { element -> block(element.name, element.listener) } /** * Iterate the listeners in the set, wrapping each call to the block with [traceSection] using * the listener name. */ inline fun forEachTraced(block: (E) -> Unit) = forEachNamed { name, listener -> traceSection(name) { block(listener) } } /** * Iterate the listeners in the set, wrapping each call to the block with [traceSection] using * the listener name. */ fun forEachTraced(consumer: Consumer<E>) = forEachNamed { name, listener -> traceSection(name) { consumer.accept(listener) } } /** Iterate over the [NamedListener]s currently in the set. */ fun namedIterator(): Iterator<NamedListener> = listeners.iterator() }