Loading packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +26 −8 Original line number Diff line number Diff line Loading @@ -19,8 +19,12 @@ package com.android.systemui.media import android.content.Context import android.media.MediaRouter2Manager import android.media.session.MediaController import androidx.annotation.AnyThread import androidx.annotation.MainThread import androidx.annotation.WorkerThread import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.Dumpable import com.android.systemui.dump.DumpManager Loading @@ -39,11 +43,12 @@ class MediaDeviceManager @Inject constructor( private val localMediaManagerFactory: LocalMediaManagerFactory, private val mr2manager: MediaRouter2Manager, @Main private val fgExecutor: Executor, @Background private val bgExecutor: Executor, private val mediaDataManager: MediaDataManager, private val dumpManager: DumpManager ) : MediaDataManager.Listener, Dumpable { private val listeners: MutableSet<Listener> = mutableSetOf() private val entries: MutableMap<String, Token> = mutableMapOf() private val entries: MutableMap<String, Entry> = mutableMapOf() init { mediaDataManager.addListener(this) Loading Loading @@ -71,7 +76,7 @@ class MediaDeviceManager @Inject constructor( val controller = data.token?.let { MediaController(context, it) } entry = Token(key, oldKey, controller, entry = Entry(key, oldKey, controller, localMediaManagerFactory.create(data.packageName)) entries[key] = entry entry.start() Loading Loading @@ -99,6 +104,7 @@ class MediaDeviceManager @Inject constructor( } } @MainThread private fun processDevice(key: String, oldKey: String?, device: MediaDevice?) { val enabled = device != null val data = MediaDeviceData(enabled, device?.iconWithoutBackground, device?.name) Loading @@ -114,12 +120,13 @@ class MediaDeviceManager @Inject constructor( fun onKeyRemoved(key: String) } private inner class Token( private inner class Entry( val key: String, val oldKey: String?, val controller: MediaController?, val localMediaManager: LocalMediaManager ) : LocalMediaManager.DeviceCallback { val token get() = controller?.sessionToken private var started = false Loading @@ -127,20 +134,27 @@ class MediaDeviceManager @Inject constructor( set(value) { if (!started || value != field) { field = value fgExecutor.execute { processDevice(key, oldKey, value) } } fun start() { } @AnyThread fun start() = bgExecutor.execute { localMediaManager.registerCallback(this) localMediaManager.startScan() updateCurrent() started = true } fun stop() { @AnyThread fun stop() = bgExecutor.execute { started = false localMediaManager.stopScan() localMediaManager.unregisterCallback(this) } fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) { val route = controller?.let { mr2manager.getRoutingSessionForMediaController(it) Loading @@ -152,14 +166,18 @@ class MediaDeviceManager @Inject constructor( println(" route=$route") } } override fun onDeviceListUpdate(devices: List<MediaDevice>?) = fgExecutor.execute { override fun onDeviceListUpdate(devices: List<MediaDevice>?) = bgExecutor.execute { updateCurrent() } override fun onSelectedDeviceStateChanged(device: MediaDevice, state: Int) { fgExecutor.execute { bgExecutor.execute { updateCurrent() } } @WorkerThread private fun updateCurrent() { val device = localMediaManager.getCurrentConnectedDevice() controller?.let { Loading packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt +36 −12 Original line number Diff line number Diff line Loading @@ -72,7 +72,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Mock private lateinit var lmmFactory: LocalMediaManagerFactory @Mock private lateinit var lmm: LocalMediaManager @Mock private lateinit var mr2: MediaRouter2Manager private lateinit var fakeExecutor: FakeExecutor private lateinit var fakeFgExecutor: FakeExecutor private lateinit var fakeBgExecutor: FakeExecutor @Mock private lateinit var dumpster: DumpManager @Mock private lateinit var listener: MediaDeviceManager.Listener @Mock private lateinit var device: MediaDevice Loading @@ -87,9 +88,10 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Before fun setUp() { fakeExecutor = FakeExecutor(FakeSystemClock()) manager = MediaDeviceManager(context, lmmFactory, mr2, fakeExecutor, mediaDataManager, dumpster) fakeFgExecutor = FakeExecutor(FakeSystemClock()) fakeBgExecutor = FakeExecutor(FakeSystemClock()) manager = MediaDeviceManager(context, lmmFactory, mr2, fakeFgExecutor, fakeBgExecutor, mediaDataManager, dumpster) manager.addListener(listener) // Configure mocks. Loading Loading @@ -144,13 +146,15 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun loadAndRemoveMediaData() { manager.onMediaDataLoaded(KEY, null, mediaData) manager.onMediaDataRemoved(KEY) fakeBgExecutor.runAllReady() verify(lmm).unregisterCallback(any()) } @Test fun loadMediaDataWithNullToken() { manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) fakeExecutor.runAllReady() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() assertThat(data.name).isEqualTo(DEVICE_NAME) Loading @@ -163,6 +167,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { reset(listener) // WHEN data is loaded with a new key manager.onMediaDataLoaded(KEY, KEY_OLD, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the listener for the old key should removed. verify(lmm).unregisterCallback(any()) // AND a new device event emitted Loading @@ -186,6 +192,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun unknownOldKey() { val oldKey = "unknown" manager.onMediaDataLoaded(KEY, oldKey, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() verify(listener).onMediaDeviceChanged(eq(KEY), eq(oldKey), any()) } Loading @@ -193,13 +201,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun updateToSessionTokenWithNullRoute() { // GIVEN that media data has been loaded with a null token manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() reset(listener) // 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) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device should be disabled fakeExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() assertThat(data.name).isNull() Loading @@ -210,7 +221,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun deviceEventOnAddNotification() { // WHEN a notification is added manager.onMediaDataLoaded(KEY, null, mediaData) val deviceCallback = captureCallback() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the update is dispatched to the listener val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() Loading @@ -230,10 +242,12 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Test fun deviceListUpdate() { manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() val deviceCallback = captureCallback() // WHEN the device list changes deviceCallback.onDeviceListUpdate(mutableListOf(device)) assertThat(fakeExecutor.runAllReady()).isEqualTo(1) assertThat(fakeBgExecutor.runAllReady()).isEqualTo(1) assertThat(fakeFgExecutor.runAllReady()).isEqualTo(1) // THEN the update is dispatched to the listener val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() Loading @@ -244,10 +258,12 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Test fun selectedDeviceStateChanged() { manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() val deviceCallback = captureCallback() // WHEN the selected device changes state deviceCallback.onSelectedDeviceStateChanged(device, 1) assertThat(fakeExecutor.runAllReady()).isEqualTo(1) assertThat(fakeBgExecutor.runAllReady()).isEqualTo(1) assertThat(fakeFgExecutor.runAllReady()).isEqualTo(1) // THEN the update is dispatched to the listener val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() Loading @@ -270,6 +286,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) // WHEN a notification is added manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device is disabled val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() Loading @@ -281,13 +299,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceChanged() { // GIVEN a notif is added manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() reset(listener) // AND MR2Manager returns null for routing session whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) // WHEN the selected device changes state val deviceCallback = captureCallback() deviceCallback.onSelectedDeviceStateChanged(device, 1) fakeExecutor.runAllReady() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device is disabled val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() Loading @@ -299,13 +320,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceListUpdate() { // GIVEN a notif is added manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() reset(listener) // GIVEN that MR2Manager returns null for routing session whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) // WHEN the selected device changes state val deviceCallback = captureCallback() deviceCallback.onDeviceListUpdate(mutableListOf(device)) fakeExecutor.runAllReady() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device is disabled val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() Loading Loading
packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +26 −8 Original line number Diff line number Diff line Loading @@ -19,8 +19,12 @@ package com.android.systemui.media import android.content.Context import android.media.MediaRouter2Manager import android.media.session.MediaController import androidx.annotation.AnyThread import androidx.annotation.MainThread import androidx.annotation.WorkerThread import com.android.settingslib.media.LocalMediaManager import com.android.settingslib.media.MediaDevice import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.Dumpable import com.android.systemui.dump.DumpManager Loading @@ -39,11 +43,12 @@ class MediaDeviceManager @Inject constructor( private val localMediaManagerFactory: LocalMediaManagerFactory, private val mr2manager: MediaRouter2Manager, @Main private val fgExecutor: Executor, @Background private val bgExecutor: Executor, private val mediaDataManager: MediaDataManager, private val dumpManager: DumpManager ) : MediaDataManager.Listener, Dumpable { private val listeners: MutableSet<Listener> = mutableSetOf() private val entries: MutableMap<String, Token> = mutableMapOf() private val entries: MutableMap<String, Entry> = mutableMapOf() init { mediaDataManager.addListener(this) Loading Loading @@ -71,7 +76,7 @@ class MediaDeviceManager @Inject constructor( val controller = data.token?.let { MediaController(context, it) } entry = Token(key, oldKey, controller, entry = Entry(key, oldKey, controller, localMediaManagerFactory.create(data.packageName)) entries[key] = entry entry.start() Loading Loading @@ -99,6 +104,7 @@ class MediaDeviceManager @Inject constructor( } } @MainThread private fun processDevice(key: String, oldKey: String?, device: MediaDevice?) { val enabled = device != null val data = MediaDeviceData(enabled, device?.iconWithoutBackground, device?.name) Loading @@ -114,12 +120,13 @@ class MediaDeviceManager @Inject constructor( fun onKeyRemoved(key: String) } private inner class Token( private inner class Entry( val key: String, val oldKey: String?, val controller: MediaController?, val localMediaManager: LocalMediaManager ) : LocalMediaManager.DeviceCallback { val token get() = controller?.sessionToken private var started = false Loading @@ -127,20 +134,27 @@ class MediaDeviceManager @Inject constructor( set(value) { if (!started || value != field) { field = value fgExecutor.execute { processDevice(key, oldKey, value) } } fun start() { } @AnyThread fun start() = bgExecutor.execute { localMediaManager.registerCallback(this) localMediaManager.startScan() updateCurrent() started = true } fun stop() { @AnyThread fun stop() = bgExecutor.execute { started = false localMediaManager.stopScan() localMediaManager.unregisterCallback(this) } fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) { val route = controller?.let { mr2manager.getRoutingSessionForMediaController(it) Loading @@ -152,14 +166,18 @@ class MediaDeviceManager @Inject constructor( println(" route=$route") } } override fun onDeviceListUpdate(devices: List<MediaDevice>?) = fgExecutor.execute { override fun onDeviceListUpdate(devices: List<MediaDevice>?) = bgExecutor.execute { updateCurrent() } override fun onSelectedDeviceStateChanged(device: MediaDevice, state: Int) { fgExecutor.execute { bgExecutor.execute { updateCurrent() } } @WorkerThread private fun updateCurrent() { val device = localMediaManager.getCurrentConnectedDevice() controller?.let { Loading
packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt +36 −12 Original line number Diff line number Diff line Loading @@ -72,7 +72,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Mock private lateinit var lmmFactory: LocalMediaManagerFactory @Mock private lateinit var lmm: LocalMediaManager @Mock private lateinit var mr2: MediaRouter2Manager private lateinit var fakeExecutor: FakeExecutor private lateinit var fakeFgExecutor: FakeExecutor private lateinit var fakeBgExecutor: FakeExecutor @Mock private lateinit var dumpster: DumpManager @Mock private lateinit var listener: MediaDeviceManager.Listener @Mock private lateinit var device: MediaDevice Loading @@ -87,9 +88,10 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Before fun setUp() { fakeExecutor = FakeExecutor(FakeSystemClock()) manager = MediaDeviceManager(context, lmmFactory, mr2, fakeExecutor, mediaDataManager, dumpster) fakeFgExecutor = FakeExecutor(FakeSystemClock()) fakeBgExecutor = FakeExecutor(FakeSystemClock()) manager = MediaDeviceManager(context, lmmFactory, mr2, fakeFgExecutor, fakeBgExecutor, mediaDataManager, dumpster) manager.addListener(listener) // Configure mocks. Loading Loading @@ -144,13 +146,15 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun loadAndRemoveMediaData() { manager.onMediaDataLoaded(KEY, null, mediaData) manager.onMediaDataRemoved(KEY) fakeBgExecutor.runAllReady() verify(lmm).unregisterCallback(any()) } @Test fun loadMediaDataWithNullToken() { manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) fakeExecutor.runAllReady() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() assertThat(data.name).isEqualTo(DEVICE_NAME) Loading @@ -163,6 +167,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { reset(listener) // WHEN data is loaded with a new key manager.onMediaDataLoaded(KEY, KEY_OLD, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the listener for the old key should removed. verify(lmm).unregisterCallback(any()) // AND a new device event emitted Loading @@ -186,6 +192,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun unknownOldKey() { val oldKey = "unknown" manager.onMediaDataLoaded(KEY, oldKey, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() verify(listener).onMediaDeviceChanged(eq(KEY), eq(oldKey), any()) } Loading @@ -193,13 +201,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun updateToSessionTokenWithNullRoute() { // GIVEN that media data has been loaded with a null token manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null)) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() reset(listener) // 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) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device should be disabled fakeExecutor.runAllReady() val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() assertThat(data.name).isNull() Loading @@ -210,7 +221,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun deviceEventOnAddNotification() { // WHEN a notification is added manager.onMediaDataLoaded(KEY, null, mediaData) val deviceCallback = captureCallback() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the update is dispatched to the listener val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() Loading @@ -230,10 +242,12 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Test fun deviceListUpdate() { manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() val deviceCallback = captureCallback() // WHEN the device list changes deviceCallback.onDeviceListUpdate(mutableListOf(device)) assertThat(fakeExecutor.runAllReady()).isEqualTo(1) assertThat(fakeBgExecutor.runAllReady()).isEqualTo(1) assertThat(fakeFgExecutor.runAllReady()).isEqualTo(1) // THEN the update is dispatched to the listener val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() Loading @@ -244,10 +258,12 @@ public class MediaDeviceManagerTest : SysuiTestCase() { @Test fun selectedDeviceStateChanged() { manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() val deviceCallback = captureCallback() // WHEN the selected device changes state deviceCallback.onSelectedDeviceStateChanged(device, 1) assertThat(fakeExecutor.runAllReady()).isEqualTo(1) assertThat(fakeBgExecutor.runAllReady()).isEqualTo(1) assertThat(fakeFgExecutor.runAllReady()).isEqualTo(1) // THEN the update is dispatched to the listener val data = captureDeviceData(KEY) assertThat(data.enabled).isTrue() Loading @@ -270,6 +286,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() { whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) // WHEN a notification is added manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device is disabled val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() Loading @@ -281,13 +299,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceChanged() { // GIVEN a notif is added manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() reset(listener) // AND MR2Manager returns null for routing session whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) // WHEN the selected device changes state val deviceCallback = captureCallback() deviceCallback.onSelectedDeviceStateChanged(device, 1) fakeExecutor.runAllReady() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device is disabled val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() Loading @@ -299,13 +320,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() { fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceListUpdate() { // GIVEN a notif is added manager.onMediaDataLoaded(KEY, null, mediaData) fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() reset(listener) // GIVEN that MR2Manager returns null for routing session whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null) // WHEN the selected device changes state val deviceCallback = captureCallback() deviceCallback.onDeviceListUpdate(mutableListOf(device)) fakeExecutor.runAllReady() fakeBgExecutor.runAllReady() fakeFgExecutor.runAllReady() // THEN the device is disabled val data = captureDeviceData(KEY) assertThat(data.enabled).isFalse() Loading