summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2020-09-28 11:46:56 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-09-28 11:46:56 +0000
commita51344f79258e29b84a5314eddc993c1a38486ea (patch)
tree6d1ff66d78111c189e5c1fff5904e91d7406ad27
parent62aab6994138d2b3df758e467801085f9c3268a5 (diff)
parent911b442f460b0d66db1b8eb9fe9d31a08e6cc9b4 (diff)
downloadbase-a51344f79258e29b84a5314eddc993c1a38486ea.tar.gz
Merge "Update device name on audio info changed" into rvc-qpr-dev
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt74
2 files changed, 73 insertions, 36 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index 102a4842e3c3..a993d00df01e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -16,7 +16,6 @@
package com.android.systemui.media
-import android.content.Context
import android.media.MediaRouter2Manager
import android.media.session.MediaController
import androidx.annotation.AnyThread
@@ -24,20 +23,22 @@ import androidx.annotation.MainThread
import androidx.annotation.WorkerThread
import com.android.settingslib.media.LocalMediaManager
import com.android.settingslib.media.MediaDevice
+import com.android.systemui.Dumpable
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
import java.io.FileDescriptor
import java.io.PrintWriter
import java.util.concurrent.Executor
import javax.inject.Inject
+private const val PLAYBACK_TYPE_UNKNOWN = 0
+
/**
* Provides information about the route (ie. device) where playback is occurring.
*/
class MediaDeviceManager @Inject constructor(
- private val context: Context,
+ private val controllerFactory: MediaControllerFactory,
private val localMediaManagerFactory: LocalMediaManagerFactory,
private val mr2manager: MediaRouter2Manager,
@Main private val fgExecutor: Executor,
@@ -71,7 +72,7 @@ class MediaDeviceManager @Inject constructor(
if (entry == null || entry?.token != data.token) {
entry?.stop()
val controller = data.token?.let {
- MediaController(context, it)
+ controllerFactory.create(it)
}
entry = Entry(key, oldKey, controller,
localMediaManagerFactory.create(data.packageName))
@@ -122,11 +123,12 @@ class MediaDeviceManager @Inject constructor(
val oldKey: String?,
val controller: MediaController?,
val localMediaManager: LocalMediaManager
- ) : LocalMediaManager.DeviceCallback {
+ ) : LocalMediaManager.DeviceCallback, MediaController.Callback() {
val token
get() = controller?.sessionToken
private var started = false
+ private var playbackType = PLAYBACK_TYPE_UNKNOWN
private var current: MediaDevice? = null
set(value) {
if (!started || value != field) {
@@ -141,6 +143,8 @@ class MediaDeviceManager @Inject constructor(
fun start() = bgExecutor.execute {
localMediaManager.registerCallback(this)
localMediaManager.startScan()
+ playbackType = controller?.playbackInfo?.playbackType ?: PLAYBACK_TYPE_UNKNOWN
+ controller?.registerCallback(this)
updateCurrent()
started = true
}
@@ -148,22 +152,37 @@ class MediaDeviceManager @Inject constructor(
@AnyThread
fun stop() = bgExecutor.execute {
started = false
+ controller?.unregisterCallback(this)
localMediaManager.stopScan()
localMediaManager.unregisterCallback(this)
}
fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
- val route = controller?.let {
+ val routingSession = controller?.let {
mr2manager.getRoutingSessionForMediaController(it)
}
+ val selectedRoutes = routingSession?.let {
+ mr2manager.getSelectedRoutes(it)
+ }
with(pw) {
println(" current device is ${current?.name}")
val type = controller?.playbackInfo?.playbackType
- println(" PlaybackType=$type (1 for local, 2 for remote)")
- println(" route=$route")
+ println(" PlaybackType=$type (1 for local, 2 for remote) cached=$playbackType")
+ println(" routingSession=$routingSession")
+ println(" selectedRoutes=$selectedRoutes")
}
}
+ @WorkerThread
+ override fun onAudioInfoChanged(info: MediaController.PlaybackInfo?) {
+ val newPlaybackType = info?.playbackType ?: PLAYBACK_TYPE_UNKNOWN
+ if (newPlaybackType == playbackType) {
+ return
+ }
+ playbackType = newPlaybackType
+ updateCurrent()
+ }
+
override fun onDeviceListUpdate(devices: List<MediaDevice>?) = bgExecutor.execute {
updateCurrent()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index fdb432cc097c..ab3b20898b23 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -16,13 +16,12 @@
package com.android.systemui.media
-import android.app.Notification
import android.graphics.drawable.Drawable
-import android.media.MediaMetadata
import android.media.MediaRouter2Manager
import android.media.RoutingSessionInfo
+import android.media.session.MediaController
+import android.media.session.MediaController.PlaybackInfo
import android.media.session.MediaSession
-import android.media.session.PlaybackState
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
@@ -55,7 +54,6 @@ private const val KEY = "TEST_KEY"
private const val KEY_OLD = "TEST_KEY_OLD"
private const val PACKAGE = "PKG"
private const val SESSION_KEY = "SESSION_KEY"
-private const val SESSION_ARTIST = "SESSION_ARTIST"
private const val SESSION_TITLE = "SESSION_TITLE"
private const val DEVICE_NAME = "DEVICE_NAME"
private const val USER_ID = 0
@@ -68,6 +66,7 @@ private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
public class MediaDeviceManagerTest : SysuiTestCase() {
private lateinit var manager: MediaDeviceManager
+ @Mock private lateinit var controllerFactory: MediaControllerFactory
@Mock private lateinit var lmmFactory: LocalMediaManagerFactory
@Mock private lateinit var lmm: LocalMediaManager
@Mock private lateinit var mr2: MediaRouter2Manager
@@ -78,10 +77,9 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Mock private lateinit var device: MediaDevice
@Mock private lateinit var icon: Drawable
@Mock private lateinit var route: RoutingSessionInfo
+ @Mock private lateinit var controller: MediaController
+ @Mock private lateinit var playbackInfo: PlaybackInfo
private lateinit var session: MediaSession
- private lateinit var metadataBuilder: MediaMetadata.Builder
- private lateinit var playbackBuilder: PlaybackState.Builder
- private lateinit var notifBuilder: Notification.Builder
private lateinit var mediaData: MediaData
@JvmField @Rule val mockito = MockitoJUnit.rule()
@@ -89,8 +87,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
fun setUp() {
fakeFgExecutor = FakeExecutor(FakeSystemClock())
fakeBgExecutor = FakeExecutor(FakeSystemClock())
- manager = MediaDeviceManager(context, lmmFactory, mr2, fakeFgExecutor, fakeBgExecutor,
- dumpster)
+ manager = MediaDeviceManager(controllerFactory, lmmFactory, mr2, fakeFgExecutor,
+ fakeBgExecutor, dumpster)
manager.addListener(listener)
// Configure mocks.
@@ -101,28 +99,13 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(route)
// Create a media sesssion and notification for testing.
- metadataBuilder = MediaMetadata.Builder().apply {
- putString(MediaMetadata.METADATA_KEY_ARTIST, SESSION_ARTIST)
- putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
- }
- playbackBuilder = PlaybackState.Builder().apply {
- setState(PlaybackState.STATE_PAUSED, 6000L, 1f)
- setActions(PlaybackState.ACTION_PLAY)
- }
- session = MediaSession(context, SESSION_KEY).apply {
- setMetadata(metadataBuilder.build())
- setPlaybackState(playbackBuilder.build())
- }
- session.setActive(true)
- notifBuilder = Notification.Builder(context, "NONE").apply {
- setContentTitle(SESSION_TITLE)
- setContentText(SESSION_ARTIST)
- setSmallIcon(android.R.drawable.ic_media_pause)
- setStyle(Notification.MediaStyle().setMediaSession(session.getSessionToken()))
- }
+ session = MediaSession(context, SESSION_KEY)
+
mediaData = MediaData(USER_ID, true, 0, PACKAGE, null, null, SESSION_TITLE, null,
emptyList(), emptyList(), PACKAGE, session.sessionToken, clickIntent = null,
device = null, active = true, resumeAction = null)
+ whenever(controllerFactory.create(session.sessionToken))
+ .thenReturn(controller)
}
@After
@@ -336,6 +319,41 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
assertThat(data.icon).isNull()
}
+ @Test
+ fun audioInfoChanged() {
+ whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_LOCAL)
+ whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
+ // GIVEN a controller with local playback type
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ reset(mr2)
+ // WHEN onAudioInfoChanged fires with remote playback type
+ whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+ val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+ verify(controller).registerCallback(captor.capture())
+ captor.value.onAudioInfoChanged(playbackInfo)
+ // THEN the route is checked
+ verify(mr2).getRoutingSessionForMediaController(eq(controller))
+ }
+
+ @Test
+ fun audioInfoHasntChanged() {
+ whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+ whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
+ // GIVEN a controller with remote playback type
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ reset(mr2)
+ // WHEN onAudioInfoChanged fires with remote playback type
+ val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+ verify(controller).registerCallback(captor.capture())
+ captor.value.onAudioInfoChanged(playbackInfo)
+ // THEN the route is not checked
+ verify(mr2, never()).getRoutingSessionForMediaController(eq(controller))
+ }
+
fun captureCallback(): LocalMediaManager.DeviceCallback {
val captor = ArgumentCaptor.forClass(LocalMediaManager.DeviceCallback::class.java)
verify(lmm).registerCallback(captor.capture())