diff options
2 files changed, 87 insertions, 5 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt index 0f3e0acd007d..4e43ccffb6a7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt @@ -60,7 +60,6 @@ import com.android.internal.annotations.Keep import com.android.internal.logging.InstanceId import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.Dumpable -import com.android.systemui.res.R import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background @@ -83,6 +82,7 @@ import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.media.controls.util.MediaUiEventLogger import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.BcSmartspaceDataPlugin +import com.android.systemui.res.R import com.android.systemui.statusbar.NotificationMediaManager.isConnectingState import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState import com.android.systemui.statusbar.notification.row.HybridGroupManager @@ -1429,8 +1429,6 @@ class MediaDataManager( } private fun onSessionDestroyed(key: String) { - if (!mediaFlags.isRetainingPlayersEnabled()) return - if (DEBUG) Log.d(TAG, "session destroyed for $key") val entry = mediaEntries.remove(key) ?: return // Clear token since the session is no longer valid @@ -1474,7 +1472,7 @@ class MediaDataManager( if (DEBUG) Log.d(TAG, "Removing still-active player $key") notifyMediaDataRemoved(key) logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId) - } else { + } else if (mediaFlags.isRetainingPlayersEnabled() || isAbleToResume(removed)) { // Convert to resume if (DEBUG) { Log.d( @@ -1484,6 +1482,11 @@ class MediaDataManager( ) } convertToResumePlayer(key, removed) + } else { + // Retaining players flag is off and app doesn't support resume: remove player. + if (DEBUG) Log.d(TAG, "Removing player $key") + notifyMediaDataRemoved(key) + logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt index fb0a4be25aa0..59d81049ad46 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt @@ -48,7 +48,6 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito import com.android.internal.logging.InstanceId import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.InstanceIdSequenceFake -import com.android.systemui.res.R import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.dump.DumpManager @@ -63,6 +62,7 @@ import com.android.systemui.media.controls.util.MediaControllerFactory import com.android.systemui.media.controls.util.MediaFlags import com.android.systemui.media.controls.util.MediaUiEventLogger import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.res.R import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.tuner.TunerService import com.android.systemui.util.concurrency.FakeExecutor @@ -2204,6 +2204,85 @@ class MediaDataManagerTest : SysuiTestCase() { } @Test + fun testSessionPlayer_sessionDestroyed_noResume_fullyRemoved() { + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) + addPlaybackStateAction() + + // When a media control with PlaybackState actions is added, times out, + // and then the session is destroyed + addNotificationAndLoad() + val data = mediaDataCaptor.value + assertThat(data.active).isTrue() + mediaDataManager.setTimedOut(KEY, timedOut = true) + sessionCallbackCaptor.value.invoke(KEY) + + // It is fully removed. + verify(listener).onMediaDataRemoved(eq(KEY)) + verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId)) + verify(listener, never()) + .onMediaDataLoaded( + eq(PACKAGE_NAME), + eq(KEY), + capture(mediaDataCaptor), + eq(true), + eq(0), + eq(false) + ) + } + + @Test + fun testSessionPlayer_destroyedWhileActive_noResume_fullyRemoved() { + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) + addPlaybackStateAction() + + // When a media control using session actions is added, and then the session is destroyed + // without timing out first + addNotificationAndLoad() + val data = mediaDataCaptor.value + assertThat(data.active).isTrue() + sessionCallbackCaptor.value.invoke(KEY) + + // It is fully removed + verify(listener).onMediaDataRemoved(eq(KEY)) + verify(logger).logMediaRemoved(anyInt(), eq(PACKAGE_NAME), eq(data.instanceId)) + verify(listener, never()) + .onMediaDataLoaded(eq(PACKAGE_NAME), any(), any(), anyBoolean(), anyInt(), anyBoolean()) + } + + @Test + fun testSessionPlayer_canResume_destroyedWhileActive_setToResume() { + whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) + addPlaybackStateAction() + + // When a media control using session actions and that does allow resumption is added, + addNotificationAndLoad() + val dataResumable = mediaDataCaptor.value.copy(resumeAction = Runnable {}) + mediaDataManager.onMediaDataLoaded(KEY, null, dataResumable) + + // And then the session is destroyed without timing out first + sessionCallbackCaptor.value.invoke(KEY) + + // It is converted to a resume player + verify(listener) + .onMediaDataLoaded( + eq(PACKAGE_NAME), + eq(KEY), + capture(mediaDataCaptor), + eq(true), + eq(0), + eq(false) + ) + assertThat(mediaDataCaptor.value.resumption).isTrue() + assertThat(mediaDataCaptor.value.active).isFalse() + verify(logger) + .logActiveConvertedToResume( + anyInt(), + eq(PACKAGE_NAME), + eq(mediaDataCaptor.value.instanceId) + ) + } + + @Test fun testSessionDestroyed_noNotificationKey_stillRemoved() { whenever(mediaFlags.isRetainingPlayersEnabled()).thenReturn(true) whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) |