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