Merge "Move call to MediaRouter2Manager to worker thread"

This commit is contained in:
Robert Snoeberger
2020-07-21 13:08:28 +00:00
committed by Android (Google) Code Review
2 changed files with 62 additions and 20 deletions

View File

@@ -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
@@ -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)
@@ -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()
@@ -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)
@@ -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
@@ -127,20 +134,27 @@ class MediaDeviceManager @Inject constructor(
set(value) {
if (!started || value != field) {
field = value
processDevice(key, oldKey, 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)
@@ -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 {

View File

@@ -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
@@ -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.
@@ -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)
@@ -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
@@ -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())
}
@@ -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()
@@ -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()
@@ -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()
@@ -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()
@@ -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()
@@ -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()
@@ -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()