Merge "Check for new media session token" into rvc-dev

This commit is contained in:
Robert Snoeberger
2020-06-10 19:14:22 +00:00
committed by Android (Google) Code Review
2 changed files with 94 additions and 32 deletions

View File

@@ -34,7 +34,6 @@ class MediaDeviceManager @Inject constructor(
private val context: Context, private val context: Context,
private val localMediaManagerFactory: LocalMediaManagerFactory, private val localMediaManagerFactory: LocalMediaManagerFactory,
private val mr2manager: MediaRouter2Manager, private val mr2manager: MediaRouter2Manager,
private val featureFlag: MediaFeatureFlag,
@Main private val fgExecutor: Executor, @Main private val fgExecutor: Executor,
private val mediaDataManager: MediaDataManager private val mediaDataManager: MediaDataManager
) : MediaDataManager.Listener { ) : MediaDataManager.Listener {
@@ -56,20 +55,19 @@ class MediaDeviceManager @Inject constructor(
fun removeListener(listener: Listener) = listeners.remove(listener) fun removeListener(listener: Listener) = listeners.remove(listener)
override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) { override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
if (featureFlag.enabled) {
if (oldKey != null && oldKey != key) { if (oldKey != null && oldKey != key) {
val oldToken = entries.remove(oldKey) val oldEntry = entries.remove(oldKey)
oldToken?.stop() oldEntry?.stop()
} }
var tok = entries[key] var entry = entries[key]
if (tok == null && data.token != null) { if (entry == null || entry?.token != data.token) {
val controller = MediaController(context, data.token!!) entry?.stop()
tok = Token(key, controller, localMediaManagerFactory.create(data.packageName)) val controller = data.token?.let {
entries[key] = tok MediaController(context, it)
tok.start()
} }
} else { entry = Token(key, controller, localMediaManagerFactory.create(data.packageName))
onMediaDataRemoved(key) entries[key] = entry
entry.start()
} }
} }
@@ -100,9 +98,11 @@ class MediaDeviceManager @Inject constructor(
private inner class Token( private inner class Token(
val key: String, val key: String,
val controller: MediaController, val controller: MediaController?,
val localMediaManager: LocalMediaManager val localMediaManager: LocalMediaManager
) : LocalMediaManager.DeviceCallback { ) : LocalMediaManager.DeviceCallback {
val token
get() = controller?.sessionToken
private var started = false private var started = false
private var current: MediaDevice? = null private var current: MediaDevice? = null
set(value) { set(value) {
@@ -132,10 +132,14 @@ class MediaDeviceManager @Inject constructor(
} }
private fun updateCurrent() { private fun updateCurrent() {
val device = localMediaManager.getCurrentConnectedDevice() 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 // If we get a null route, then don't trust the device. Just set to null to disable the
// output switcher chip. // output switcher chip.
current = if (route != null) device else null current = if (route != null) device else null
} ?: run {
current = device
}
} }
} }
} }

View File

@@ -51,6 +51,7 @@ import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit import org.mockito.junit.MockitoJUnit
private const val KEY = "TEST_KEY" private const val KEY = "TEST_KEY"
private const val KEY_OLD = "TEST_KEY_OLD"
private const val PACKAGE = "PKG" private const val PACKAGE = "PKG"
private const val SESSION_KEY = "SESSION_KEY" private const val SESSION_KEY = "SESSION_KEY"
private const val SESSION_ARTIST = "SESSION_ARTIST" private const val SESSION_ARTIST = "SESSION_ARTIST"
@@ -69,7 +70,6 @@ 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
@Mock private lateinit var featureFlag: MediaFeatureFlag
private lateinit var fakeExecutor: FakeExecutor private lateinit var fakeExecutor: FakeExecutor
@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
@@ -85,8 +85,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Before @Before
fun setUp() { fun setUp() {
fakeExecutor = FakeExecutor(FakeSystemClock()) fakeExecutor = FakeExecutor(FakeSystemClock())
manager = MediaDeviceManager(context, lmmFactory, mr2, featureFlag, fakeExecutor, manager = MediaDeviceManager(context, lmmFactory, mr2, fakeExecutor, mediaDataManager)
mediaDataManager)
manager.addListener(listener) manager.addListener(listener)
// Configure mocks. // Configure mocks.
@@ -95,7 +94,6 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
whenever(lmmFactory.create(PACKAGE)).thenReturn(lmm) whenever(lmmFactory.create(PACKAGE)).thenReturn(lmm)
whenever(lmm.getCurrentConnectedDevice()).thenReturn(device) whenever(lmm.getCurrentConnectedDevice()).thenReturn(device)
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route) whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route)
whenever(featureFlag.enabled).thenReturn(true)
// Create a media sesssion and notification for testing. // Create a media sesssion and notification for testing.
metadataBuilder = MediaMetadata.Builder().apply { metadataBuilder = MediaMetadata.Builder().apply {
@@ -132,25 +130,76 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
} }
@Test @Test
fun addNotification() { fun loadMediaData() {
manager.onMediaDataLoaded(KEY, null, mediaData) manager.onMediaDataLoaded(KEY, null, mediaData)
verify(lmmFactory).create(PACKAGE) verify(lmmFactory).create(PACKAGE)
} }
@Test @Test
fun featureDisabled() { fun loadAndRemoveMediaData() {
whenever(featureFlag.enabled).thenReturn(false)
manager.onMediaDataLoaded(KEY, null, mediaData)
verify(lmmFactory, never()).create(PACKAGE)
}
@Test
fun addAndRemoveNotification() {
manager.onMediaDataLoaded(KEY, null, mediaData) manager.onMediaDataLoaded(KEY, null, mediaData)
manager.onMediaDataRemoved(KEY) manager.onMediaDataRemoved(KEY)
verify(lmm).unregisterCallback(any()) verify(lmm).unregisterCallback(any())
} }
@Test
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 @Test
fun deviceEventOnAddNotification() { fun deviceEventOnAddNotification() {
// WHEN a notification is added // WHEN a notification is added
@@ -163,6 +212,15 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
assertThat(data.icon).isEqualTo(icon) 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 @Test
fun deviceListUpdate() { fun deviceListUpdate() {
manager.onMediaDataLoaded(KEY, null, mediaData) manager.onMediaDataLoaded(KEY, null, mediaData)