diff options
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() } |