summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Luca Zuccarini <acul@google.com> 2025-01-10 07:52:49 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-01-10 07:52:49 -0800
commit7615f9b216e78d73b8df3e183d6c782d62cf448f (patch)
treee4de36487e3acca27eea902a92ce11b1a941108e
parent7d5db209ccd22761047bf52933fd366954cbac9b (diff)
parent73387d2cedd49a830c013173697c174bc00ab805 (diff)
Merge "Fix concurrent modification issue with lifecycle listeners." into main
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt22
2 files changed, 28 insertions, 4 deletions
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
index b0c7ac09551a..c8d3430bf54b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityTransitionAnimator.kt
@@ -232,19 +232,21 @@ constructor(
private val lifecycleListener =
object : Listener {
override fun onTransitionAnimationStart() {
- listeners.forEach { it.onTransitionAnimationStart() }
+ LinkedHashSet(listeners).forEach { it.onTransitionAnimationStart() }
}
override fun onTransitionAnimationEnd() {
- listeners.forEach { it.onTransitionAnimationEnd() }
+ LinkedHashSet(listeners).forEach { it.onTransitionAnimationEnd() }
}
override fun onTransitionAnimationProgress(linearProgress: Float) {
- listeners.forEach { it.onTransitionAnimationProgress(linearProgress) }
+ LinkedHashSet(listeners).forEach {
+ it.onTransitionAnimationProgress(linearProgress)
+ }
}
override fun onTransitionAnimationCancelled() {
- listeners.forEach { it.onTransitionAnimationCancelled() }
+ LinkedHashSet(listeners).forEach { it.onTransitionAnimationCancelled() }
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt
index 37eb148a5ea7..fd751d9cc7c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityTransitionAnimatorTest.kt
@@ -466,6 +466,28 @@ class ActivityTransitionAnimatorTest : SysuiTestCase() {
assertNull(runner.delegate)
}
+ @Test
+ fun concurrentListenerModification_doesNotThrow() {
+ // Need a second listener to trigger the concurrent modification.
+ activityTransitionAnimator.addListener(object : ActivityTransitionAnimator.Listener {})
+ `when`(listener.onTransitionAnimationStart()).thenAnswer {
+ activityTransitionAnimator.removeListener(listener)
+ listener
+ }
+
+ val runner = activityTransitionAnimator.createEphemeralRunner(controller)
+ runner.onAnimationStart(
+ TRANSIT_NONE,
+ arrayOf(fakeWindow()),
+ emptyArray(),
+ emptyArray(),
+ iCallback,
+ )
+
+ waitForIdleSync()
+ verify(listener).onTransitionAnimationStart()
+ }
+
private fun controllerFactory(
cookie: ActivityTransitionAnimator.TransitionCookie =
mock(ActivityTransitionAnimator.TransitionCookie::class.java),