From 3dca24f6b8e1337e90fb97c9a3eae15e09b0e503 Mon Sep 17 00:00:00 2001 From: Robert Snoeberger Date: Fri, 11 Sep 2020 15:24:52 -0400 Subject: [PATCH] Only filter when remote session has associated notification Bug: 167706409 Test: manual - Cast from Google Play Books and check that media controls are available in QS. Change-Id: Ifc404be2de6f5f87a1d43e3b51d3ca00c73c6e06 (cherry picked from commit 8cc72bdf3ab4f33e6353409d887f19ca3f4cc8e7) Merged-In: Ifc404be2de6f5f87a1d43e3b51d3ca00c73c6e06 --- .../systemui/media/MediaSessionBasedFilter.kt | 16 ++++++-- .../media/MediaSessionBasedFilterTest.kt | 41 ++++++++++++++++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt index f01713fb5f6c2..f695622b943a1 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt @@ -52,9 +52,12 @@ class MediaSessionBasedFilter @Inject constructor( private val packageControllers: LinkedHashMap> = LinkedHashMap() - // Keep track of the key used for the session tokens. This information is used to know when + // Keep track of the key used for the session tokens. This information is used to know when to // dispatch a removed event so that a media object for a local session will be removed. - private val keyedTokens: MutableMap> = mutableMapOf() + private val keyedTokens: MutableMap> = mutableMapOf() + + // Keep track of which media session tokens have associated notifications. + private val tokensWithNotifications: MutableSet = mutableSetOf() private val sessionListener = object : MediaSessionManager.OnActiveSessionsChangedListener { override fun onActiveSessionsChanged(controllers: List) { @@ -90,6 +93,9 @@ class MediaSessionBasedFilter @Inject constructor( */ override fun onMediaDataLoaded(key: String, oldKey: String?, info: MediaData) { backgroundExecutor.execute { + info.token?.let { + tokensWithNotifications.add(it) + } val isMigration = oldKey != null && key != oldKey if (isMigration) { keyedTokens.remove(oldKey)?.let { removed -> keyedTokens.put(key, removed) } @@ -99,7 +105,7 @@ class MediaSessionBasedFilter @Inject constructor( tokens -> tokens.add(info.token) } ?: run { - val tokens = mutableListOf(info.token) + val tokens = mutableSetOf(info.token) keyedTokens.put(key, tokens) } } @@ -110,7 +116,8 @@ class MediaSessionBasedFilter @Inject constructor( } // Limiting search to only apps with a single remote session. val remote = if (remoteControllers?.size == 1) remoteControllers.firstOrNull() else null - if (isMigration || remote == null || remote.sessionToken == info.token) { + if (isMigration || remote == null || remote.sessionToken == info.token || + !tokensWithNotifications.contains(remote.sessionToken)) { // Not filtering in this case. Passing the event along to listeners. dispatchMediaDataLoaded(key, oldKey, info) } else { @@ -159,5 +166,6 @@ class MediaSessionBasedFilter @Inject constructor( packageControllers.put(controller.packageName, tokens) } } + tokensWithNotifications.retainAll(controllers.map { it.sessionToken }) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt index 887cc777d4fe4..2d90cc4f67121 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt @@ -225,7 +225,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { @Test fun remoteSession_loadedEventNotFiltered() { - // GIVEN a remove session + // GIVEN a remote session whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo) val controllers = listOf(controller1) whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) @@ -259,6 +259,22 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { verify(mediaListener, never()).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2)) } + @Test + fun remoteAndLocalSessions_remoteSessionWithoutNotification() { + // GIVEN remote and local sessions + whenever(controller2.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1, controller2) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matches the local session + filter.onMediaDataLoaded(KEY, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered because there isn't a notification for the remote + // session. + verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1)) + } + @Test fun remoteAndLocalHaveDifferentKeys_localLoadedEventFiltered() { // GIVEN remote and local sessions @@ -284,6 +300,29 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { verify(mediaListener).onMediaDataRemoved(eq(key2)) } + @Test + fun remoteAndLocalHaveDifferentKeys_remoteSessionWithoutNotification() { + // GIVEN remote and local sessions + val key1 = "KEY_1" + val key2 = "KEY_2" + whenever(controller2.getPlaybackInfo()).thenReturn(remotePlaybackInfo) + val controllers = listOf(controller1, controller2) + whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers) + sessionListener.onActiveSessionsChanged(controllers) + // WHEN a loaded event is received that matches the local session + filter.onMediaDataLoaded(key1, null, mediaData1) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1)) + // WHEN a loaded event is received that matches the remote session + filter.onMediaDataLoaded(key2, null, mediaData2) + bgExecutor.runAllReady() + fgExecutor.runAllReady() + // THEN the event is not filtered + verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2)) + } + @Test fun multipleRemoteSessions_loadedEventNotFiltered() { // GIVEN two remote sessions