Fix a crash when dismissing the last notification from the locked shade.
The crash was caused by a coordinator emitting an event that would invalidate while the pipeline was running. Bug: 201329618 Test: atest ShadeEventCoordinatorTest Change-Id: If9656a540372ce75827e7487e1542af0a2f3abf3
This commit is contained in:
@@ -18,11 +18,13 @@ package com.android.systemui.statusbar.notification.collection.coordinator
|
||||
|
||||
import android.service.notification.NotificationListenerService
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
import com.android.systemui.statusbar.notification.collection.ListEntry
|
||||
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
|
||||
import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource
|
||||
import java.util.concurrent.Executor
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
@@ -32,6 +34,7 @@ import javax.inject.Inject
|
||||
// TODO(b/204468557): Move to @CoordinatorScope
|
||||
@SysUISingleton
|
||||
class ShadeEventCoordinator @Inject internal constructor(
|
||||
@Main private val mMainExecutor: Executor,
|
||||
private val mLogger: ShadeEventCoordinatorLogger
|
||||
) : Coordinator, NotifShadeEventSource {
|
||||
private var mNotifRemovedByUserCallback: Runnable? = null
|
||||
@@ -67,11 +70,13 @@ class ShadeEventCoordinator @Inject internal constructor(
|
||||
private fun onBeforeRenderList(entries: List<ListEntry>) {
|
||||
if (mEntryRemoved && entries.isEmpty()) {
|
||||
mLogger.logShadeEmptied()
|
||||
mShadeEmptiedCallback?.run()
|
||||
// TODO(b/206023518): This was bad. Do not copy this.
|
||||
mShadeEmptiedCallback?.let { mMainExecutor.execute(it) }
|
||||
}
|
||||
if (mEntryRemoved && mEntryRemovedByUser) {
|
||||
mLogger.logNotifRemovedByUser()
|
||||
mNotifRemovedByUserCallback?.run()
|
||||
// TODO(b/206023518): This was bad. Do not copy this.
|
||||
mNotifRemovedByUserCallback?.let { mMainExecutor.execute(it) }
|
||||
}
|
||||
mEntryRemoved = false
|
||||
mEntryRemovedByUser = false
|
||||
|
||||
@@ -31,9 +31,12 @@ import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations.initMocks
|
||||
import java.util.concurrent.Executor
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@@ -48,13 +51,18 @@ class ShadeEventCoordinatorTest : SysuiTestCase() {
|
||||
|
||||
@Mock private lateinit var pipeline: NotifPipeline
|
||||
@Mock private lateinit var logger: ShadeEventCoordinatorLogger
|
||||
@Mock private lateinit var executor: Executor
|
||||
@Mock private lateinit var notifRemovedByUserCallback: Runnable
|
||||
@Mock private lateinit var shadeEmptiedCallback: Runnable
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
initMocks(this)
|
||||
coordinator = ShadeEventCoordinator(logger)
|
||||
whenever(executor.execute(any())).then {
|
||||
(it.arguments[0] as Runnable).run()
|
||||
true
|
||||
}
|
||||
coordinator = ShadeEventCoordinator(executor, logger)
|
||||
coordinator.attach(pipeline)
|
||||
notifCollectionListener = withArgCaptor {
|
||||
verify(pipeline).addCollectionListener(capture())
|
||||
|
||||
Reference in New Issue
Block a user