Loading packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +23 −19 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ class MediaDeviceManager @Inject constructor( private val context: Context, private val localMediaManagerFactory: LocalMediaManagerFactory, private val mr2manager: MediaRouter2Manager, private val featureFlag: MediaFeatureFlag, @Main private val fgExecutor: Executor, private val mediaDataManager: MediaDataManager ) : MediaDataManager.Listener { Loading @@ -56,20 +55,19 @@ class MediaDeviceManager @Inject constructor( fun removeListener(listener: Listener) = listeners.remove(listener) override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { if (featureFlag.enabled) { if (oldKey != null && oldKey != key) { val oldToken = entries.remove(oldKey) oldToken?.stop() val oldEntry = entries.remove(oldKey) oldEntry?.stop() } var tok = entries[key] if (tok == null && data.token != null) { val controller = MediaController(context, data.token!!) tok = Token(key, controller, localMediaManagerFactory.create(data.packageName)) entries[key] = tok tok.start() var entry = entries[key] if (entry == null || entry?.token != data.token) { entry?.stop() val controller = data.token?.let { MediaController(context, it) } } else { onMediaDataRemoved(key) entry = Token(key, controller, localMediaManagerFactory.create(data.packageName)) entries[key] = entry entry.start() } } Loading Loading @@ -100,9 +98,11 @@ class MediaDeviceManager @Inject constructor( private inner class Token( val key: String, val controller: MediaController, val controller: MediaController?, val localMediaManager: LocalMediaManager ) : LocalMediaManager.DeviceCallback { val token get() = controller?.sessionToken private var started = false private var current: MediaDevice? = null set(value) { Loading Loading @@ -132,10 +132,14 @@ class MediaDeviceManager @Inject constructor( } private fun updateCurrent() { val device = localMediaManager.getCurrentConnectedDevice() val route = mr2manager.getRoutingSessionForMediaController(controller) controller?.let { val route = mr2manager.getRoutingSessionForMediaController(it) // If we get a null route, then don't trust the device. Just set to null to disable the // output switcher chip. current = if (route != null) device else null } ?: run { current = device } } } } packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt +69 −11 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit private const val KEY = "TEST_KEY" private const val KEY_OLD = "TEST_KEY_OLD" private const val PACKAGE = "PKG" private const val SESSION_KEY = "SESSION_KEY" private const val SESSION_ARTIST = "SESSION_ARTIST" Loading @@ -69,7 +70,6 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Mock private lateinit var lmmFactory: LocalMediaManagerFactory @Mock private lateinit var lmm: LocalMediaManager @Mock private lateinit var mr2: MediaRouter2Manager @Mock private lateinit var featureFlag: MediaFeatureFlag private lateinit var fakeExecutor: FakeExecutor @Mock private lateinit var listener: MediaDeviceManager.Listener @Mock private lateinit var device: MediaDevice Loading @@ -85,8 +85,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Before fun setUp() { fakeExecutor = FakeExecutor(FakeSystemClock()) manager = MediaDeviceManager(context, lmmFactory, mr2, featureFlag, fakeExecutor, mediaDataManager) manager = MediaDeviceManager(context, lmmFactory, mr2, fakeExecutor, mediaDataManager) manager.addListener(listener) // Configure mocks. Loading @@ -95,7 +94,6 @@ public class MediaDeviceManagerTest : SysuiTestCase() { whenever(lmmFactory.create(PACKAGE)).thenReturn(lmm) whenever(lmm.getCurrentConnectedDevice()).thenReturn(device) whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route) whenever(featureFlag.enabled).thenReturn(true) // Create a media sesssion and notification for testing. metadataBuilder = MediaMetadata.Builder().apply { Loading Loading @@ -132,23 +130,74 @@ public class MediaDeviceManagerTest : SysuiTestCase() { } @Test fun addNotification() { fun loadMediaData() { manager.onMediaDataLoaded(KEY, null, mediaData) verify(lmmFactory).create(PACKAGE) } @Test fun featureDisabled() { whenever(featureFlag.enabled).thenReturn(false) fun loadAndRemoveMediaData() { manager.onMediaDataLoaded(KEY, null, mediaData) verify(lmmFactory, never()).create(PACKAGE) manager.onMediaDataRemoved(KEY) verify(lmm).unregisterCallback(any()) } @Test fun addAndRemoveNotification() { manager.onMediaDataLoaded(KEY, null, mediaData) manager.onMediaDataRemoved(KEY) fun loadMediaDataWithNullToken() { manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) fakeExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() assertThat(data.name).isEqualTo(DEVICE_NAME) } @Test fun loadWithNewKey() { // GIVEN that media data has been loaded with an old key manager.onMediaDataLoaded(KEY_OLD, null, mediaData) reset(listener) // WHEN data is loaded with a new key manager.onMediaDataLoaded(KEY, KEY_OLD, mediaData) // THEN the listener for the old key should removed. verify(lmm).unregisterCallback(any()) // AND a new device event emitted val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() assertThat(data.name).isEqualTo(DEVICE_NAME) } @Test fun newKeySameAsOldKey() { // GIVEN that media data has been loaded manager.onMediaDataLoaded(KEY, null, mediaData) reset(listener) // WHEN the new key is the same as the old key manager.onMediaDataLoaded(KEY, KEY, mediaData) // THEN no event should be emitted verify(listener, never()).onMediaDeviceChanged(eq(KEY), any()) } @Test fun unknownOldKey() { manager.onMediaDataLoaded(KEY, "unknown", mediaData) verify(listener).onMediaDeviceChanged(eq(KEY), any()) } @Test fun updateToSessionTokenWithNullRoute() { // GIVEN that media data has been loaded with a null token manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) // WHEN media data is loaded with a different token // AND that token results in a null route reset(listener) whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) manager.onMediaDataLoaded(KEY, null, mediaData) // THEN the device should be disabled fakeExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() assertThat(data.name).isNull() assertThat(data.icon).isNull() } @Test Loading @@ -163,6 +212,15 @@ public class MediaDeviceManagerTest : SysuiTestCase() { assertThat(data.icon).isEqualTo(icon) } @Test fun removeListener() { // WHEN a listener is removed manager.removeListener(listener) // THEN it doesn't receive device events manager.onMediaDataLoaded(KEY, null, mediaData) verify(listener, never()).onMediaDeviceChanged(eq(KEY), any()) } @Test fun deviceListUpdate() { manager.onMediaDataLoaded(KEY, null, mediaData) Loading Loading
packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +23 −19 Original line number Diff line number Diff line Loading @@ -34,7 +34,6 @@ class MediaDeviceManager @Inject constructor( private val context: Context, private val localMediaManagerFactory: LocalMediaManagerFactory, private val mr2manager: MediaRouter2Manager, private val featureFlag: MediaFeatureFlag, @Main private val fgExecutor: Executor, private val mediaDataManager: MediaDataManager ) : MediaDataManager.Listener { Loading @@ -56,20 +55,19 @@ class MediaDeviceManager @Inject constructor( fun removeListener(listener: Listener) = listeners.remove(listener) override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { if (featureFlag.enabled) { if (oldKey != null && oldKey != key) { val oldToken = entries.remove(oldKey) oldToken?.stop() val oldEntry = entries.remove(oldKey) oldEntry?.stop() } var tok = entries[key] if (tok == null && data.token != null) { val controller = MediaController(context, data.token!!) tok = Token(key, controller, localMediaManagerFactory.create(data.packageName)) entries[key] = tok tok.start() var entry = entries[key] if (entry == null || entry?.token != data.token) { entry?.stop() val controller = data.token?.let { MediaController(context, it) } } else { onMediaDataRemoved(key) entry = Token(key, controller, localMediaManagerFactory.create(data.packageName)) entries[key] = entry entry.start() } } Loading Loading @@ -100,9 +98,11 @@ class MediaDeviceManager @Inject constructor( private inner class Token( val key: String, val controller: MediaController, val controller: MediaController?, val localMediaManager: LocalMediaManager ) : LocalMediaManager.DeviceCallback { val token get() = controller?.sessionToken private var started = false private var current: MediaDevice? = null set(value) { Loading Loading @@ -132,10 +132,14 @@ class MediaDeviceManager @Inject constructor( } private fun updateCurrent() { val device = localMediaManager.getCurrentConnectedDevice() val route = mr2manager.getRoutingSessionForMediaController(controller) controller?.let { val route = mr2manager.getRoutingSessionForMediaController(it) // If we get a null route, then don't trust the device. Just set to null to disable the // output switcher chip. current = if (route != null) device else null } ?: run { current = device } } } }
packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt +69 −11 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.junit.MockitoJUnit private const val KEY = "TEST_KEY" private const val KEY_OLD = "TEST_KEY_OLD" private const val PACKAGE = "PKG" private const val SESSION_KEY = "SESSION_KEY" private const val SESSION_ARTIST = "SESSION_ARTIST" Loading @@ -69,7 +70,6 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Mock private lateinit var lmmFactory: LocalMediaManagerFactory @Mock private lateinit var lmm: LocalMediaManager @Mock private lateinit var mr2: MediaRouter2Manager @Mock private lateinit var featureFlag: MediaFeatureFlag private lateinit var fakeExecutor: FakeExecutor @Mock private lateinit var listener: MediaDeviceManager.Listener @Mock private lateinit var device: MediaDevice Loading @@ -85,8 +85,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Before fun setUp() { fakeExecutor = FakeExecutor(FakeSystemClock()) manager = MediaDeviceManager(context, lmmFactory, mr2, featureFlag, fakeExecutor, mediaDataManager) manager = MediaDeviceManager(context, lmmFactory, mr2, fakeExecutor, mediaDataManager) manager.addListener(listener) // Configure mocks. Loading @@ -95,7 +94,6 @@ public class MediaDeviceManagerTest : SysuiTestCase() { whenever(lmmFactory.create(PACKAGE)).thenReturn(lmm) whenever(lmm.getCurrentConnectedDevice()).thenReturn(device) whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route) whenever(featureFlag.enabled).thenReturn(true) // Create a media sesssion and notification for testing. metadataBuilder = MediaMetadata.Builder().apply { Loading Loading @@ -132,23 +130,74 @@ public class MediaDeviceManagerTest : SysuiTestCase() { } @Test fun addNotification() { fun loadMediaData() { manager.onMediaDataLoaded(KEY, null, mediaData) verify(lmmFactory).create(PACKAGE) } @Test fun featureDisabled() { whenever(featureFlag.enabled).thenReturn(false) fun loadAndRemoveMediaData() { manager.onMediaDataLoaded(KEY, null, mediaData) verify(lmmFactory, never()).create(PACKAGE) manager.onMediaDataRemoved(KEY) verify(lmm).unregisterCallback(any()) } @Test fun addAndRemoveNotification() { manager.onMediaDataLoaded(KEY, null, mediaData) manager.onMediaDataRemoved(KEY) fun loadMediaDataWithNullToken() { manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) fakeExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() assertThat(data.name).isEqualTo(DEVICE_NAME) } @Test fun loadWithNewKey() { // GIVEN that media data has been loaded with an old key manager.onMediaDataLoaded(KEY_OLD, null, mediaData) reset(listener) // WHEN data is loaded with a new key manager.onMediaDataLoaded(KEY, KEY_OLD, mediaData) // THEN the listener for the old key should removed. verify(lmm).unregisterCallback(any()) // AND a new device event emitted val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() assertThat(data.name).isEqualTo(DEVICE_NAME) } @Test fun newKeySameAsOldKey() { // GIVEN that media data has been loaded manager.onMediaDataLoaded(KEY, null, mediaData) reset(listener) // WHEN the new key is the same as the old key manager.onMediaDataLoaded(KEY, KEY, mediaData) // THEN no event should be emitted verify(listener, never()).onMediaDeviceChanged(eq(KEY), any()) } @Test fun unknownOldKey() { manager.onMediaDataLoaded(KEY, "unknown", mediaData) verify(listener).onMediaDeviceChanged(eq(KEY), any()) } @Test fun updateToSessionTokenWithNullRoute() { // GIVEN that media data has been loaded with a null token manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) // WHEN media data is loaded with a different token // AND that token results in a null route reset(listener) whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) manager.onMediaDataLoaded(KEY, null, mediaData) // THEN the device should be disabled fakeExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() assertThat(data.name).isNull() assertThat(data.icon).isNull() } @Test Loading @@ -163,6 +212,15 @@ public class MediaDeviceManagerTest : SysuiTestCase() { assertThat(data.icon).isEqualTo(icon) } @Test fun removeListener() { // WHEN a listener is removed manager.removeListener(listener) // THEN it doesn't receive device events manager.onMediaDataLoaded(KEY, null, mediaData) verify(listener, never()).onMediaDeviceChanged(eq(KEY), any()) } @Test fun deviceListUpdate() { manager.onMediaDataLoaded(KEY, null, mediaData) Loading