Loading packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +14 −3 Original line number Original line Diff line number Diff line Loading @@ -518,9 +518,20 @@ class MediaDataManager( } } val actions = createActionsFromState(it.packageName, val actions = createActionsFromState(it.packageName, mediaControllerFactory.create(it.token), UserHandle(it.userId)) mediaControllerFactory.create(it.token), UserHandle(it.userId)) val data = it.copy( // Control buttons // If flag is enabled and controller has a PlaybackState, // create actions from session info // otherwise, no need to update semantic actions. val data = if (actions != null) { it.copy( semanticActions = actions, semanticActions = actions, isPlaying = isPlayingState(state.state)) isPlaying = isPlayingState(state.state)) } else { it.copy( isPlaying = isPlayingState(state.state) ) } if (DEBUG) Log.d(TAG, "State updated outside of notification") if (DEBUG) Log.d(TAG, "State updated outside of notification") onMediaDataLoaded(key, key, data) onMediaDataLoaded(key, key, data) } } Loading packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +78 −4 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.tuner.TunerService import com.android.systemui.tuner.TunerService import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.util.time.FakeSystemClock Loading Loading @@ -108,6 +107,7 @@ class MediaDataManagerTest : SysuiTestCase() { private val clock = FakeSystemClock() private val clock = FakeSystemClock() @Mock private lateinit var tunerService: TunerService @Mock private lateinit var tunerService: TunerService @Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable> @Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable> @Captor lateinit var callbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit> private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20) private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20) Loading Loading @@ -974,7 +974,6 @@ class MediaDataManagerTest : SysuiTestCase() { fun testPlaybackStateChange_keyExists_callsListener() { fun testPlaybackStateChange_keyExists_callsListener() { // Notification has been added // Notification has been added addNotificationAndLoad() addNotificationAndLoad() val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) // Callback gets an updated state // Callback gets an updated state Loading @@ -992,7 +991,6 @@ class MediaDataManagerTest : SysuiTestCase() { @Test @Test fun testPlaybackStateChange_keyDoesNotExist_doesNothing() { fun testPlaybackStateChange_keyDoesNotExist_doesNothing() { val state = PlaybackState.Builder().build() val state = PlaybackState.Builder().build() val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) // No media added with this key // No media added with this key Loading @@ -1013,7 +1011,6 @@ class MediaDataManagerTest : SysuiTestCase() { // And then get a state update // And then get a state update val state = PlaybackState.Builder().build() val state = PlaybackState.Builder().build() val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) // Then no changes are made // Then no changes are made Loading @@ -1022,6 +1019,83 @@ class MediaDataManagerTest : SysuiTestCase() { anyBoolean()) anyBoolean()) } } @Test fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() { whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) val state = PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, 0L, 1f) .build() whenever(controller.playbackState).thenReturn(state) addNotificationAndLoad() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) callbackCaptor.value.invoke(KEY, state) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false)) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() } @Test fun testPlaybackState_PauseStateAfterAddingResumption_keyExists_callsListener() { val desc = MediaDescription.Builder().run { setTitle(SESSION_TITLE) build() } val state = PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, 0L, 1f) .setActions(PlaybackState.ACTION_PLAY_PAUSE) .build() // Add resumption controls in order to have semantic actions. // To make sure that they are not null after changing state. mediaDataManager.addResumptionControls( USER_ID, desc, Runnable {}, session.sessionToken, APP_NAME, pendingIntent, PACKAGE_NAME ) backgroundExecutor.runAllReady() foregroundExecutor.runAllReady() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) callbackCaptor.value.invoke(PACKAGE_NAME, state) verify(listener) .onMediaDataLoaded( eq(PACKAGE_NAME), eq(PACKAGE_NAME), capture(mediaDataCaptor), eq(true), eq(0), eq(false) ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() } @Test fun testPlaybackStateNull_Pause_keyExists_callsListener() { whenever(controller.playbackState).thenReturn(null) val state = PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, 0L, 1f) .setActions(PlaybackState.ACTION_PLAY_PAUSE) .build() addNotificationAndLoad() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) callbackCaptor.value.invoke(KEY, state) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false)) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNull() } /** /** * Helper function to add a media notification and capture the resulting MediaData * Helper function to add a media notification and capture the resulting MediaData */ */ Loading Loading
packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +14 −3 Original line number Original line Diff line number Diff line Loading @@ -518,9 +518,20 @@ class MediaDataManager( } } val actions = createActionsFromState(it.packageName, val actions = createActionsFromState(it.packageName, mediaControllerFactory.create(it.token), UserHandle(it.userId)) mediaControllerFactory.create(it.token), UserHandle(it.userId)) val data = it.copy( // Control buttons // If flag is enabled and controller has a PlaybackState, // create actions from session info // otherwise, no need to update semantic actions. val data = if (actions != null) { it.copy( semanticActions = actions, semanticActions = actions, isPlaying = isPlayingState(state.state)) isPlaying = isPlayingState(state.state)) } else { it.copy( isPlaying = isPlayingState(state.state) ) } if (DEBUG) Log.d(TAG, "State updated outside of notification") if (DEBUG) Log.d(TAG, "State updated outside of notification") onMediaDataLoaded(key, key, data) onMediaDataLoaded(key, key, data) } } Loading
packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +78 −4 Original line number Original line Diff line number Diff line Loading @@ -31,7 +31,6 @@ import com.android.systemui.statusbar.SbnBuilder import com.android.systemui.tuner.TunerService import com.android.systemui.tuner.TunerService import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import com.android.systemui.util.time.FakeSystemClock Loading Loading @@ -108,6 +107,7 @@ class MediaDataManagerTest : SysuiTestCase() { private val clock = FakeSystemClock() private val clock = FakeSystemClock() @Mock private lateinit var tunerService: TunerService @Mock private lateinit var tunerService: TunerService @Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable> @Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable> @Captor lateinit var callbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit> private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20) private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20) Loading Loading @@ -974,7 +974,6 @@ class MediaDataManagerTest : SysuiTestCase() { fun testPlaybackStateChange_keyExists_callsListener() { fun testPlaybackStateChange_keyExists_callsListener() { // Notification has been added // Notification has been added addNotificationAndLoad() addNotificationAndLoad() val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) // Callback gets an updated state // Callback gets an updated state Loading @@ -992,7 +991,6 @@ class MediaDataManagerTest : SysuiTestCase() { @Test @Test fun testPlaybackStateChange_keyDoesNotExist_doesNothing() { fun testPlaybackStateChange_keyDoesNotExist_doesNothing() { val state = PlaybackState.Builder().build() val state = PlaybackState.Builder().build() val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) // No media added with this key // No media added with this key Loading @@ -1013,7 +1011,6 @@ class MediaDataManagerTest : SysuiTestCase() { // And then get a state update // And then get a state update val state = PlaybackState.Builder().build() val state = PlaybackState.Builder().build() val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) // Then no changes are made // Then no changes are made Loading @@ -1022,6 +1019,83 @@ class MediaDataManagerTest : SysuiTestCase() { anyBoolean()) anyBoolean()) } } @Test fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() { whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true) val state = PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, 0L, 1f) .build() whenever(controller.playbackState).thenReturn(state) addNotificationAndLoad() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) callbackCaptor.value.invoke(KEY, state) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false)) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() } @Test fun testPlaybackState_PauseStateAfterAddingResumption_keyExists_callsListener() { val desc = MediaDescription.Builder().run { setTitle(SESSION_TITLE) build() } val state = PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, 0L, 1f) .setActions(PlaybackState.ACTION_PLAY_PAUSE) .build() // Add resumption controls in order to have semantic actions. // To make sure that they are not null after changing state. mediaDataManager.addResumptionControls( USER_ID, desc, Runnable {}, session.sessionToken, APP_NAME, pendingIntent, PACKAGE_NAME ) backgroundExecutor.runAllReady() foregroundExecutor.runAllReady() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) callbackCaptor.value.invoke(PACKAGE_NAME, state) verify(listener) .onMediaDataLoaded( eq(PACKAGE_NAME), eq(PACKAGE_NAME), capture(mediaDataCaptor), eq(true), eq(0), eq(false) ) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNotNull() } @Test fun testPlaybackStateNull_Pause_keyExists_callsListener() { whenever(controller.playbackState).thenReturn(null) val state = PlaybackState.Builder() .setState(PlaybackState.STATE_PAUSED, 0L, 1f) .setActions(PlaybackState.ACTION_PLAY_PAUSE) .build() addNotificationAndLoad() verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor) callbackCaptor.value.invoke(KEY, state) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), eq(0), eq(false)) assertThat(mediaDataCaptor.value.isPlaying).isFalse() assertThat(mediaDataCaptor.value.semanticActions).isNull() } /** /** * Helper function to add a media notification and capture the resulting MediaData * Helper function to add a media notification and capture the resulting MediaData */ */ Loading