summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt7
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractorTest.kt231
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt69
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt52
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt14
9 files changed, 338 insertions, 57 deletions
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt b/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt
index 68f471dd4e4f..d198136447a5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/media/session/MediaSessionManagerExt.kt
@@ -45,14 +45,13 @@ val MediaSessionManager.activeMediaChanges: Flow<List<MediaController>?>
.buffer(capacity = Channel.CONFLATED)
/** [Flow] for [MediaSessionManager.RemoteSessionCallback]. */
-val MediaSessionManager.remoteSessionChanges: Flow<MediaSession.Token?>
+val MediaSessionManager.defaultRemoteSessionChanged: Flow<MediaSession.Token?>
get() =
callbackFlow {
val callback =
object : MediaSessionManager.RemoteSessionCallback {
- override fun onVolumeChanged(sessionToken: MediaSession.Token, flags: Int) {
- launch { send(sessionToken) }
- }
+ override fun onVolumeChanged(sessionToken: MediaSession.Token, flags: Int) =
+ Unit
override fun onDefaultRemoteSessionChanged(
sessionToken: MediaSession.Token?
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt
index e4ac9fe686a3..195ccfcd328d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/MediaControllerRepository.kt
@@ -21,6 +21,7 @@ import android.media.session.MediaSessionManager
import com.android.settingslib.bluetooth.LocalBluetoothManager
import com.android.settingslib.bluetooth.headsetAudioModeChanges
import com.android.settingslib.media.session.activeMediaChanges
+import com.android.settingslib.media.session.defaultRemoteSessionChanged
import com.android.settingslib.volume.shared.AudioManagerEventsReceiver
import com.android.settingslib.volume.shared.model.AudioManagerEvent
import kotlin.coroutines.CoroutineContext
@@ -59,6 +60,9 @@ class MediaControllerRepositoryImpl(
override val activeSessions: StateFlow<List<MediaController>> =
merge(
+ mediaSessionManager.defaultRemoteSessionChanged.map {
+ mediaSessionManager.getActiveSessions(null)
+ },
mediaSessionManager.activeMediaChanges.filterNotNull(),
localBluetoothManager?.headsetAudioModeChanges?.map {
mediaSessionManager.getActiveSessions(null)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
index 632196ccf66d..2af2602c6f52 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractorTest.kt
@@ -21,6 +21,7 @@ import android.graphics.drawable.TestStubDrawable
import android.media.AudioDeviceInfo
import android.media.AudioDevicePort
import android.media.AudioManager
+import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.R
@@ -54,6 +55,7 @@ import org.junit.runner.RunWith
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@SmallTest
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
class AudioOutputInteractorTest : SysuiTestCase() {
private val kosmos = testKosmos()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractorTest.kt
new file mode 100644
index 000000000000..9e86cedb6732
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractorTest.kt
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.volume.panel.component.mediaoutput.domain.interactor
+
+import android.media.AudioAttributes
+import android.media.VolumeProvider
+import android.media.session.MediaController
+import android.media.session.PlaybackState
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.android.systemui.volume.data.repository.FakeLocalMediaRepository
+import com.android.systemui.volume.localMediaController
+import com.android.systemui.volume.localMediaRepositoryFactory
+import com.android.systemui.volume.localPlaybackInfo
+import com.android.systemui.volume.localPlaybackStateBuilder
+import com.android.systemui.volume.mediaControllerRepository
+import com.android.systemui.volume.mediaOutputInteractor
+import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
+import com.android.systemui.volume.panel.shared.model.Result
+import com.android.systemui.volume.remoteMediaController
+import com.android.systemui.volume.remotePlaybackInfo
+import com.android.systemui.volume.remotePlaybackStateBuilder
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class MediaOutputInteractorTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+
+ private lateinit var underTest: MediaOutputInteractor
+
+ @Before
+ fun setUp() =
+ with(kosmos) {
+ localMediaRepositoryFactory.setLocalMediaRepository(
+ "local.test.pkg",
+ FakeLocalMediaRepository().apply {
+ updateCurrentConnectedDevice(
+ mock { whenever(name).thenReturn("local_media_device") }
+ )
+ },
+ )
+ localMediaRepositoryFactory.setLocalMediaRepository(
+ "remote.test.pkg",
+ FakeLocalMediaRepository().apply {
+ updateCurrentConnectedDevice(
+ mock { whenever(name).thenReturn("remote_media_device") }
+ )
+ },
+ )
+
+ underTest = kosmos.mediaOutputInteractor
+ }
+
+ @Test
+ fun noActiveMediaDeviceSessions_nulls() =
+ with(kosmos) {
+ testScope.runTest {
+ mediaControllerRepository.setActiveSessions(emptyList())
+
+ val activeMediaDeviceSessions by
+ collectLastValue(underTest.activeMediaDeviceSessions)
+ runCurrent()
+
+ assertThat(activeMediaDeviceSessions!!.local).isNull()
+ assertThat(activeMediaDeviceSessions!!.remote).isNull()
+ }
+ }
+
+ @Test
+ fun activeMediaDeviceSessions_areParsed() =
+ with(kosmos) {
+ testScope.runTest {
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val activeMediaDeviceSessions by
+ collectLastValue(underTest.activeMediaDeviceSessions)
+ runCurrent()
+
+ with(activeMediaDeviceSessions!!.local!!) {
+ assertThat(packageName).isEqualTo("local.test.pkg")
+ assertThat(appLabel).isEqualTo("local_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ with(activeMediaDeviceSessions!!.remote!!) {
+ assertThat(packageName).isEqualTo("remote.test.pkg")
+ assertThat(appLabel).isEqualTo("remote_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ }
+ }
+
+ @Test
+ fun activeMediaDeviceSessions_volumeControlFixed_cantAdjustVolume() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackInfo =
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+ VolumeProvider.VOLUME_CONTROL_FIXED,
+ 0,
+ 0,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ remotePlaybackInfo =
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
+ VolumeProvider.VOLUME_CONTROL_FIXED,
+ 0,
+ 0,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val activeMediaDeviceSessions by
+ collectLastValue(underTest.activeMediaDeviceSessions)
+ runCurrent()
+
+ assertThat(activeMediaDeviceSessions!!.local!!.canAdjustVolume).isFalse()
+ assertThat(activeMediaDeviceSessions!!.remote!!.canAdjustVolume).isFalse()
+ }
+ }
+
+ @Test
+ fun activeLocalAndRemoteSession_defaultSession_local() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackStateBuilder.setState(PlaybackState.STATE_PLAYING, 0, 0f)
+ remotePlaybackStateBuilder.setState(PlaybackState.STATE_PLAYING, 0, 0f)
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val defaultActiveMediaSession by
+ collectLastValue(underTest.defaultActiveMediaSession)
+ val currentDevice by collectLastValue(underTest.currentConnectedDevice)
+ runCurrent()
+
+ with((defaultActiveMediaSession as Result.Data<MediaDeviceSession?>).data!!) {
+ assertThat(packageName).isEqualTo("local.test.pkg")
+ assertThat(appLabel).isEqualTo("local_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ assertThat(currentDevice!!.name).isEqualTo("local_media_device")
+ }
+ }
+
+ @Test
+ fun activeRemoteSession_defaultSession_remote() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackStateBuilder.setState(PlaybackState.STATE_PAUSED, 0, 0f)
+ remotePlaybackStateBuilder.setState(PlaybackState.STATE_PLAYING, 0, 0f)
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val defaultActiveMediaSession by
+ collectLastValue(underTest.defaultActiveMediaSession)
+ val currentDevice by collectLastValue(underTest.currentConnectedDevice)
+ runCurrent()
+
+ with((defaultActiveMediaSession as Result.Data<MediaDeviceSession?>).data!!) {
+ assertThat(packageName).isEqualTo("remote.test.pkg")
+ assertThat(appLabel).isEqualTo("remote_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ assertThat(currentDevice!!.name).isEqualTo("remote_media_device")
+ }
+ }
+
+ @Test
+ fun inactiveLocalAndRemoteSession_defaultSession_local() =
+ with(kosmos) {
+ testScope.runTest {
+ localPlaybackStateBuilder.setState(PlaybackState.STATE_PAUSED, 0, 0f)
+ remotePlaybackStateBuilder.setState(PlaybackState.STATE_PAUSED, 0, 0f)
+ mediaControllerRepository.setActiveSessions(
+ listOf(localMediaController, remoteMediaController)
+ )
+
+ val defaultActiveMediaSession by
+ collectLastValue(underTest.defaultActiveMediaSession)
+ val currentDevice by collectLastValue(underTest.currentConnectedDevice)
+ runCurrent()
+
+ with((defaultActiveMediaSession as Result.Data<MediaDeviceSession?>).data!!) {
+ assertThat(packageName).isEqualTo("local.test.pkg")
+ assertThat(appLabel).isEqualTo("local_media_controller_label")
+ assertThat(canAdjustVolume).isTrue()
+ }
+ assertThat(currentDevice!!.name).isEqualTo("local_media_device")
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
index 19d9c3f125b7..3eec3d91c809 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/domain/interactor/AudioOutputInteractor.kt
@@ -32,7 +32,6 @@ import com.android.systemui.volume.domain.model.AudioOutputDevice
import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
-import com.android.systemui.volume.panel.shared.model.filterData
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
@@ -69,14 +68,9 @@ constructor(
communicationDevice?.toAudioOutputDevice()
}
} else {
- mediaOutputInteractor.defaultActiveMediaSession
- .filterData()
- .flatMapLatest {
- localMediaRepositoryFactory
- .create(it?.packageName)
- .currentConnectedDevice
- }
- .map { mediaDevice -> mediaDevice?.toAudioOutputDevice() }
+ mediaOutputInteractor.currentConnectedDevice.map { mediaDevice ->
+ mediaDevice?.toAudioOutputDevice()
+ }
}
}
.map { it ?: AudioOutputDevice.Unknown }
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
index b974f90191e9..b00829e48404 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/interactor/MediaOutputInteractor.kt
@@ -19,10 +19,12 @@ package com.android.systemui.volume.panel.component.mediaoutput.domain.interacto
import android.content.pm.PackageManager
import android.media.VolumeProvider
import android.media.session.MediaController
+import android.os.Handler
import android.util.Log
import com.android.settingslib.media.MediaDevice
import com.android.settingslib.volume.data.repository.LocalMediaRepository
import com.android.settingslib.volume.data.repository.MediaControllerRepository
+import com.android.settingslib.volume.data.repository.stateChanges
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaDeviceSessions
@@ -36,14 +38,15 @@ import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.withContext
@@ -58,21 +61,31 @@ constructor(
@VolumePanelScope private val coroutineScope: CoroutineScope,
@Background private val backgroundCoroutineContext: CoroutineContext,
mediaControllerRepository: MediaControllerRepository,
+ @Background private val backgroundHandler: Handler,
) {
private val activeMediaControllers: Flow<MediaControllers> =
mediaControllerRepository.activeSessions
+ .flatMapLatest { activeSessions ->
+ activeSessions
+ .map { activeSession -> activeSession.stateChanges() }
+ .merge()
+ .map { activeSessions }
+ .onStart { emit(activeSessions) }
+ }
.map { getMediaControllers(it) }
- .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)
+ .stateIn(coroutineScope, SharingStarted.Eagerly, MediaControllers(null, null))
/** [MediaDeviceSessions] that contains currently active sessions. */
val activeMediaDeviceSessions: Flow<MediaDeviceSessions> =
- activeMediaControllers.map {
- MediaDeviceSessions(
- local = it.local?.mediaDeviceSession(),
- remote = it.remote?.mediaDeviceSession()
- )
- }
+ activeMediaControllers
+ .map {
+ MediaDeviceSessions(
+ local = it.local?.mediaDeviceSession(),
+ remote = it.remote?.mediaDeviceSession()
+ )
+ }
+ .stateIn(coroutineScope, SharingStarted.Eagerly, MediaDeviceSessions(null, null))
/** Returns the default [MediaDeviceSession] from [activeMediaDeviceSessions] */
val defaultActiveMediaSession: StateFlow<Result<MediaDeviceSession?>> =
@@ -89,13 +102,17 @@ constructor(
.flowOn(backgroundCoroutineContext)
.stateIn(coroutineScope, SharingStarted.Eagerly, Result.Loading())
- private val localMediaRepository: SharedFlow<LocalMediaRepository> =
+ private val localMediaRepository: Flow<LocalMediaRepository> =
defaultActiveMediaSession
.filterData()
.map { it?.packageName }
.distinctUntilChanged()
.map { localMediaRepositoryFactory.create(it) }
- .shareIn(coroutineScope, SharingStarted.Eagerly, replay = 1)
+ .stateIn(
+ coroutineScope,
+ SharingStarted.Eagerly,
+ localMediaRepositoryFactory.create(null)
+ )
/** Currently connected [MediaDevice]. */
val currentConnectedDevice: Flow<MediaDevice?> =
@@ -134,21 +151,33 @@ constructor(
}
if (!remoteMediaSessions.contains(controller.packageName)) {
remoteMediaSessions.add(controller.packageName)
- if (remoteController == null) {
- remoteController = controller
- }
+ remoteController = chooseController(remoteController, controller)
}
}
MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL -> {
if (controller.packageName in remoteMediaSessions) continue
- if (localController != null) continue
- localController = controller
+ localController = chooseController(localController, controller)
}
}
}
return MediaControllers(local = localController, remote = remoteController)
}
+ private fun chooseController(
+ currentController: MediaController?,
+ newController: MediaController,
+ ): MediaController {
+ if (currentController == null) {
+ return newController
+ }
+ val isNewControllerActive = newController.playbackState?.isActive == true
+ val isCurrentControllerActive = currentController.playbackState?.isActive == true
+ if (isNewControllerActive && !isCurrentControllerActive) {
+ return newController
+ }
+ return currentController
+ }
+
private suspend fun MediaController.mediaDeviceSession(): MediaDeviceSession? {
return MediaDeviceSession(
packageName = packageName,
@@ -160,6 +189,14 @@ constructor(
)
}
+ private fun MediaController?.stateChanges(): Flow<MediaController?> {
+ if (this == null) {
+ return flowOf(null)
+ }
+
+ return stateChanges(backgroundHandler).map { this }.onStart { emit(this@stateChanges) }
+ }
+
private data class MediaControllers(
val local: MediaController?,
val remote: MediaController?,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt
index 5db17243c4e3..546a797482a5 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaControllerKosmos.kt
@@ -19,8 +19,10 @@ package com.android.systemui.volume
import android.content.packageManager
import android.content.pm.ApplicationInfo
import android.media.AudioAttributes
+import android.media.VolumeProvider
import android.media.session.MediaController
import android.media.session.MediaSession
+import android.media.session.PlaybackState
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -28,6 +30,18 @@ import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
private const val LOCAL_PACKAGE = "local.test.pkg"
+var Kosmos.localPlaybackInfo by
+ Kosmos.Fixture {
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+ VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
+ 10,
+ 3,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ }
+var Kosmos.localPlaybackStateBuilder by Kosmos.Fixture { PlaybackState.Builder() }
var Kosmos.localMediaController: MediaController by
Kosmos.Fixture {
val appInfo: ApplicationInfo = mock {
@@ -39,22 +53,25 @@ var Kosmos.localMediaController: MediaController by
val localSessionToken: MediaSession.Token = MediaSession.Token(0, mock {})
mock {
whenever(packageName).thenReturn(LOCAL_PACKAGE)
- whenever(playbackInfo)
- .thenReturn(
- MediaController.PlaybackInfo(
- MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
- 0,
- 0,
- 0,
- AudioAttributes.Builder().build(),
- "",
- )
- )
+ whenever(playbackInfo).thenReturn(localPlaybackInfo)
+ whenever(playbackState).thenReturn(localPlaybackStateBuilder.build())
whenever(sessionToken).thenReturn(localSessionToken)
}
}
private const val REMOTE_PACKAGE = "remote.test.pkg"
+var Kosmos.remotePlaybackInfo by
+ Kosmos.Fixture {
+ MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
+ VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
+ 10,
+ 7,
+ AudioAttributes.Builder().build(),
+ "",
+ )
+ }
+var Kosmos.remotePlaybackStateBuilder by Kosmos.Fixture { PlaybackState.Builder() }
var Kosmos.remoteMediaController: MediaController by
Kosmos.Fixture {
val appInfo: ApplicationInfo = mock {
@@ -66,17 +83,8 @@ var Kosmos.remoteMediaController: MediaController by
val remoteSessionToken: MediaSession.Token = MediaSession.Token(0, mock {})
mock {
whenever(packageName).thenReturn(REMOTE_PACKAGE)
- whenever(playbackInfo)
- .thenReturn(
- MediaController.PlaybackInfo(
- MediaController.PlaybackInfo.PLAYBACK_TYPE_REMOTE,
- 0,
- 0,
- 0,
- AudioAttributes.Builder().build(),
- "",
- )
- )
+ whenever(playbackInfo).thenReturn(remotePlaybackInfo)
+ whenever(playbackState).thenReturn(remotePlaybackStateBuilder.build())
whenever(sessionToken).thenReturn(remoteSessionToken)
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt
index fa3a19bae655..d74355894581 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/MediaOutputKosmos.kt
@@ -30,13 +30,12 @@ import com.android.systemui.util.mockito.whenever
import com.android.systemui.volume.data.repository.FakeLocalMediaRepository
import com.android.systemui.volume.data.repository.FakeMediaControllerRepository
import com.android.systemui.volume.panel.component.mediaoutput.data.repository.FakeLocalMediaRepositoryFactory
-import com.android.systemui.volume.panel.component.mediaoutput.data.repository.LocalMediaRepositoryFactory
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor
import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
val Kosmos.localMediaRepository by Kosmos.Fixture { FakeLocalMediaRepository() }
-val Kosmos.localMediaRepositoryFactory: LocalMediaRepositoryFactory by
+val Kosmos.localMediaRepositoryFactory by
Kosmos.Fixture { FakeLocalMediaRepositoryFactory { localMediaRepository } }
val Kosmos.mediaOutputActionsInteractor by
@@ -55,6 +54,7 @@ val Kosmos.mediaOutputInteractor by
testScope.backgroundScope,
testScope.testScheduler,
mediaControllerRepository,
+ Handler(TestableLooper.get(testCase).looper),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt
index 1b3480c423e4..9c902cf57fde 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/mediaoutput/data/repository/FakeLocalMediaRepositoryFactory.kt
@@ -18,9 +18,15 @@ package com.android.systemui.volume.panel.component.mediaoutput.data.repository
import com.android.settingslib.volume.data.repository.LocalMediaRepository
-class FakeLocalMediaRepositoryFactory(
- val provider: (packageName: String?) -> LocalMediaRepository
-) : LocalMediaRepositoryFactory {
+class FakeLocalMediaRepositoryFactory(private val defaultProvider: () -> LocalMediaRepository) :
+ LocalMediaRepositoryFactory {
- override fun create(packageName: String?): LocalMediaRepository = provider(packageName)
+ private val repositories = mutableMapOf<String, LocalMediaRepository>()
+
+ fun setLocalMediaRepository(packageName: String, localMediaRepository: LocalMediaRepository) {
+ repositories[packageName] = localMediaRepository
+ }
+
+ override fun create(packageName: String?): LocalMediaRepository =
+ repositories[packageName] ?: defaultProvider()
}