Loading packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt +19 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.volume.panel.component.volume.domain.interactor import android.media.AudioDeviceInfo import android.media.AudioManager import com.android.settingslib.volume.data.repository.AudioRepository import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession Loading @@ -42,6 +43,7 @@ constructor( @VolumePanelScope scope: CoroutineScope, mediaOutputInteractor: MediaOutputInteractor, audioRepository: AudioRepository, audioModeInteractor: AudioModeInteractor, ) { val volumePanelSliders: StateFlow<List<SliderType>> = Loading @@ -49,9 +51,14 @@ constructor( mediaOutputInteractor.activeMediaDeviceSessions, mediaOutputInteractor.defaultActiveMediaSession.filterData(), audioRepository.communicationDevice, ) { activeSessions, defaultSession, communicationDevice -> audioModeInteractor.isOngoingCall, ) { activeSessions, defaultSession, communicationDevice, isOngoingCall -> coroutineScope { val viewModels = buildList { if (isOngoingCall) { addCall(communicationDevice?.type) } if (defaultSession?.isTheSameSession(activeSessions.remote) == true) { addSession(activeSessions.remote) addStream(AudioManager.STREAM_MUSIC) Loading @@ -60,11 +67,10 @@ constructor( addSession(activeSessions.remote) } if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { addStream(AudioManager.STREAM_BLUETOOTH_SCO) } else { addStream(AudioManager.STREAM_VOICE_CALL) if (!isOngoingCall) { addCall(communicationDevice?.type) } addStream(AudioManager.STREAM_RING) addStream(AudioManager.STREAM_NOTIFICATION) addStream(AudioManager.STREAM_ALARM) Loading @@ -74,6 +80,14 @@ constructor( } .stateIn(scope, SharingStarted.Eagerly, emptyList()) private fun MutableList<SliderType>.addCall(communicationDeviceType: Int?) { if (communicationDeviceType == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { addStream(AudioManager.STREAM_BLUETOOTH_SCO) } else { addStream(AudioManager.STREAM_VOICE_CALL) } } private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) { if (remoteMediaDeviceSession?.canAdjustVolume == true) { add(SliderType.MediaDeviceCast(remoteMediaDeviceSession)) Loading packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt +25 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor Loading @@ -35,9 +36,11 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn Loading @@ -58,24 +61,31 @@ constructor( mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, audioModeInteractor: AudioModeInteractor, streamsInteractor: AudioSlidersInteractor, ) { private val mutableIsExpanded = MutableStateFlow<Boolean?>(null) private val isPlaybackActive: Flow<Boolean?> = mediaOutputInteractor.defaultActiveMediaSession .filterData() .flatMapLatest { session -> private val isActive: Flow<Boolean?> = combine( audioModeInteractor.isOngoingCall, mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session -> if (session == null) { flowOf(false) } else { mediaDeviceSessionInteractor.playbackState(session).map { it?.isActive == true } mediaDeviceSessionInteractor.playbackState(session).map { it?.isActive == true } } .onEach { isPlaybackActive -> mutableIsExpanded.value = !isPlaybackActive } }, ) { isOngoingCall, isPlaybackActive -> isOngoingCall || isPlaybackActive } .stateIn(scope, SharingStarted.Eagerly, null) private val portraitExpandable: Flow<SlidersExpandableViewModel> = isPlaybackActive isActive .filterNotNull() .flatMapLatest { isActive -> if (isActive) { Loading Loading @@ -105,6 +115,10 @@ constructor( } .stateIn(scope, SharingStarted.Eagerly, emptyList()) init { isActive.filterNotNull().onEach { mutableIsExpanded.value = !it }.launchIn(scope) } fun isExpandable(isPortrait: Boolean): Flow<SlidersExpandableViewModel> { return if (isPortrait) { portraitExpandable Loading packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt +4 −2 Original line number Diff line number Diff line Loading @@ -17,15 +17,17 @@ package com.android.systemui.volume.panel.component.volume.domain.interactor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.volume.data.repository.audioRepository import com.android.systemui.volume.domain.interactor.audioModeInteractor import com.android.systemui.volume.mediaOutputInteractor val Kosmos.audioSlidersInteractor by Kosmos.Fixture { AudioSlidersInteractor( testScope.backgroundScope, applicationCoroutineScope, mediaOutputInteractor, audioRepository, audioModeInteractor, ) } packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt +2 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.volume.domain.interactor.audioModeInteractor import com.android.systemui.volume.mediaDeviceSessionInteractor import com.android.systemui.volume.mediaOutputInteractor import com.android.systemui.volume.panel.component.volume.domain.interactor.audioSlidersInteractor Loading @@ -32,6 +33,7 @@ val Kosmos.audioVolumeComponentViewModel by mediaDeviceSessionInteractor, audioStreamSliderViewModelFactory, castVolumeSliderViewModelFactory, audioModeInteractor, audioSlidersInteractor, ) } Loading
packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt +19 −5 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.volume.panel.component.volume.domain.interactor import android.media.AudioDeviceInfo import android.media.AudioManager import com.android.settingslib.volume.data.repository.AudioRepository import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession Loading @@ -42,6 +43,7 @@ constructor( @VolumePanelScope scope: CoroutineScope, mediaOutputInteractor: MediaOutputInteractor, audioRepository: AudioRepository, audioModeInteractor: AudioModeInteractor, ) { val volumePanelSliders: StateFlow<List<SliderType>> = Loading @@ -49,9 +51,14 @@ constructor( mediaOutputInteractor.activeMediaDeviceSessions, mediaOutputInteractor.defaultActiveMediaSession.filterData(), audioRepository.communicationDevice, ) { activeSessions, defaultSession, communicationDevice -> audioModeInteractor.isOngoingCall, ) { activeSessions, defaultSession, communicationDevice, isOngoingCall -> coroutineScope { val viewModels = buildList { if (isOngoingCall) { addCall(communicationDevice?.type) } if (defaultSession?.isTheSameSession(activeSessions.remote) == true) { addSession(activeSessions.remote) addStream(AudioManager.STREAM_MUSIC) Loading @@ -60,11 +67,10 @@ constructor( addSession(activeSessions.remote) } if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { addStream(AudioManager.STREAM_BLUETOOTH_SCO) } else { addStream(AudioManager.STREAM_VOICE_CALL) if (!isOngoingCall) { addCall(communicationDevice?.type) } addStream(AudioManager.STREAM_RING) addStream(AudioManager.STREAM_NOTIFICATION) addStream(AudioManager.STREAM_ALARM) Loading @@ -74,6 +80,14 @@ constructor( } .stateIn(scope, SharingStarted.Eagerly, emptyList()) private fun MutableList<SliderType>.addCall(communicationDeviceType: Int?) { if (communicationDeviceType == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { addStream(AudioManager.STREAM_BLUETOOTH_SCO) } else { addStream(AudioManager.STREAM_VOICE_CALL) } } private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) { if (remoteMediaDeviceSession?.canAdjustVolume == true) { add(SliderType.MediaDeviceCast(remoteMediaDeviceSession)) Loading
packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt +25 −11 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import com.android.settingslib.volume.domain.interactor.AudioModeInteractor import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaDeviceSessionInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor Loading @@ -35,9 +36,11 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn Loading @@ -58,24 +61,31 @@ constructor( mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, audioModeInteractor: AudioModeInteractor, streamsInteractor: AudioSlidersInteractor, ) { private val mutableIsExpanded = MutableStateFlow<Boolean?>(null) private val isPlaybackActive: Flow<Boolean?> = mediaOutputInteractor.defaultActiveMediaSession .filterData() .flatMapLatest { session -> private val isActive: Flow<Boolean?> = combine( audioModeInteractor.isOngoingCall, mediaOutputInteractor.defaultActiveMediaSession.filterData().flatMapLatest { session -> if (session == null) { flowOf(false) } else { mediaDeviceSessionInteractor.playbackState(session).map { it?.isActive == true } mediaDeviceSessionInteractor.playbackState(session).map { it?.isActive == true } } .onEach { isPlaybackActive -> mutableIsExpanded.value = !isPlaybackActive } }, ) { isOngoingCall, isPlaybackActive -> isOngoingCall || isPlaybackActive } .stateIn(scope, SharingStarted.Eagerly, null) private val portraitExpandable: Flow<SlidersExpandableViewModel> = isPlaybackActive isActive .filterNotNull() .flatMapLatest { isActive -> if (isActive) { Loading Loading @@ -105,6 +115,10 @@ constructor( } .stateIn(scope, SharingStarted.Eagerly, emptyList()) init { isActive.filterNotNull().onEach { mutableIsExpanded.value = !it }.launchIn(scope) } fun isExpandable(isPortrait: Boolean): Flow<SlidersExpandableViewModel> { return if (isPortrait) { portraitExpandable Loading
packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractorKosmos.kt +4 −2 Original line number Diff line number Diff line Loading @@ -17,15 +17,17 @@ package com.android.systemui.volume.panel.component.volume.domain.interactor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.volume.data.repository.audioRepository import com.android.systemui.volume.domain.interactor.audioModeInteractor import com.android.systemui.volume.mediaOutputInteractor val Kosmos.audioSlidersInteractor by Kosmos.Fixture { AudioSlidersInteractor( testScope.backgroundScope, applicationCoroutineScope, mediaOutputInteractor, audioRepository, audioModeInteractor, ) }
packages/SystemUI/tests/utils/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/VolumeSlidersViewModelKosmos.kt +2 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope import com.android.systemui.volume.domain.interactor.audioModeInteractor import com.android.systemui.volume.mediaDeviceSessionInteractor import com.android.systemui.volume.mediaOutputInteractor import com.android.systemui.volume.panel.component.volume.domain.interactor.audioSlidersInteractor Loading @@ -32,6 +33,7 @@ val Kosmos.audioVolumeComponentViewModel by mediaDeviceSessionInteractor, audioStreamSliderViewModelFactory, castVolumeSliderViewModelFactory, audioModeInteractor, audioSlidersInteractor, ) }