Loading packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt +7 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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( Loading @@ -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) } } Loading packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt +80 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -2203,6 +2203,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) Loading Loading
packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataManager.kt +7 −4 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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( Loading @@ -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) } } Loading
packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataManagerTest.kt +80 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -2203,6 +2203,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) Loading