Merge "Move call to MediaRouter2Manager to worker thread"
This commit is contained in:
committed by
Android (Google) Code Review
commit
1cf64dcf2d
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user