Loading packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt 0 → 100644 +85 −0 Original line number Diff line number Diff line /* * 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.volume.domain.interactor import android.media.AudioDeviceInfo import android.media.AudioManager import com.android.settingslib.volume.data.repository.AudioRepository 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 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession import com.android.systemui.volume.panel.component.volume.domain.model.SliderType import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.stateIn /** Provides volume sliders to show in the Volume Panel. */ @VolumePanelScope class AudioSlidersInteractor @Inject constructor( @VolumePanelScope scope: CoroutineScope, mediaOutputInteractor: MediaOutputInteractor, audioRepository: AudioRepository, ) { val volumePanelSliders: StateFlow<List<SliderType>> = combineTransform( mediaOutputInteractor.activeMediaDeviceSessions, mediaOutputInteractor.defaultActiveMediaSession, audioRepository.communicationDevice, ) { activeSessions, defaultSession, communicationDevice -> coroutineScope { val viewModels = buildList { if (defaultSession?.isTheSameSession(activeSessions.remote) == true) { addSession(activeSessions.remote) addStream(AudioManager.STREAM_MUSIC) } else { addStream(AudioManager.STREAM_MUSIC) addSession(activeSessions.remote) } if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { addStream(AudioManager.STREAM_BLUETOOTH_SCO) } else { addStream(AudioManager.STREAM_VOICE_CALL) } addStream(AudioManager.STREAM_RING) addStream(AudioManager.STREAM_NOTIFICATION) addStream(AudioManager.STREAM_ALARM) } emit(viewModels) } } .stateIn(scope, SharingStarted.Eagerly, emptyList()) private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) { if (remoteMediaDeviceSession?.canAdjustVolume == true) { add(SliderType.MediaDeviceCast(remoteMediaDeviceSession)) } } private fun MutableList<SliderType>.addStream(stream: Int) { add(SliderType.Stream(AudioStream(stream))) } } packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.volume.panel.component.volume.domain.model import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession /** The type of volume slider that can be shown at the UI. */ sealed interface SliderType { Loading @@ -25,5 +26,5 @@ sealed interface SliderType { data class Stream(val stream: AudioStream) : SliderType /** The represents media device casting volume. */ data object MediaDeviceCast : SliderType data class MediaDeviceCast(val session: MediaDeviceSession) : SliderType } packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt +4 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ constructor( mapOf( AudioStream(AudioManager.STREAM_MUSIC) to R.drawable.ic_music_note, AudioStream(AudioManager.STREAM_VOICE_CALL) to R.drawable.ic_call, AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to R.drawable.ic_call, AudioStream(AudioManager.STREAM_RING) to R.drawable.ic_ring_volume, AudioStream(AudioManager.STREAM_NOTIFICATION) to R.drawable.ic_volume_ringer, AudioStream(AudioManager.STREAM_ALARM) to R.drawable.ic_volume_alarm, Loading @@ -61,6 +62,7 @@ constructor( mapOf( AudioStream(AudioManager.STREAM_MUSIC) to R.string.stream_music, AudioStream(AudioManager.STREAM_VOICE_CALL) to R.string.stream_voice_call, AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to R.string.stream_voice_call, AudioStream(AudioManager.STREAM_RING) to R.string.stream_ring, AudioStream(AudioManager.STREAM_NOTIFICATION) to R.string.stream_notification, AudioStream(AudioManager.STREAM_ALARM) to R.string.stream_alarm, Loading @@ -78,6 +80,8 @@ constructor( VolumePanelUiEvent.VOLUME_PANEL_MUSIC_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_VOICE_CALL) to VolumePanelUiEvent.VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to VolumePanelUiEvent.VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_RING) to VolumePanelUiEvent.VOLUME_PANEL_RING_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_NOTIFICATION) to Loading packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt +24 −42 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import android.media.AudioManager 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 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession import com.android.systemui.volume.panel.component.volume.domain.interactor.AudioSlidersInteractor import com.android.systemui.volume.panel.component.volume.domain.model.SliderType import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.AudioStreamSliderViewModel import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel Loading @@ -33,12 +33,12 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch /** Loading @@ -55,27 +55,20 @@ constructor( private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, streamsInteractor: AudioSlidersInteractor, ) { val sliderViewModels: StateFlow<List<SliderViewModel>> = combineTransform( mediaOutputInteractor.activeMediaDeviceSessions, mediaOutputInteractor.defaultActiveMediaSession, ) { activeSessions, defaultSession -> streamsInteractor.volumePanelSliders .transformLatest { sliderTypes -> coroutineScope { val viewModels = buildList { if (defaultSession?.isTheSameSession(activeSessions.remote) == true) { addRemoteViewModelIfNeeded(this, activeSessions.remote) addStreamViewModel(this, AudioManager.STREAM_MUSIC) } else { addStreamViewModel(this, AudioManager.STREAM_MUSIC) addRemoteViewModelIfNeeded(this, activeSessions.remote) val viewModels = sliderTypes.map { type -> when (type) { is SliderType.Stream -> createStreamViewModel(type.stream) is SliderType.MediaDeviceCast -> createSessionViewModel(type.session) } addStreamViewModel(this, AudioManager.STREAM_VOICE_CALL) addStreamViewModel(this, AudioManager.STREAM_RING) addStreamViewModel(this, AudioManager.STREAM_NOTIFICATION) addStreamViewModel(this, AudioManager.STREAM_ALARM) } emit(viewModels) } Loading @@ -98,29 +91,18 @@ constructor( scope.launch { mutableIsExpanded.emit(isExpanded) } } private fun CoroutineScope.addRemoteViewModelIfNeeded( list: MutableList<SliderViewModel>, remoteMediaDeviceSession: MediaDeviceSession? ) { if (remoteMediaDeviceSession?.canAdjustVolume == true) { val viewModel = castVolumeSliderViewModelFactory.create( remoteMediaDeviceSession, this, ) list.add(viewModel) } private fun CoroutineScope.createSessionViewModel( session: MediaDeviceSession ): CastVolumeSliderViewModel { return castVolumeSliderViewModelFactory.create(session, this) } private fun CoroutineScope.addStreamViewModel( list: MutableList<SliderViewModel>, stream: Int, ) { val viewModel = streamSliderViewModelFactory.create( AudioStreamSliderViewModel.FactoryAudioStreamWrapper(AudioStream(stream)), private fun CoroutineScope.createStreamViewModel( stream: AudioStream, ): AudioStreamSliderViewModel { return streamSliderViewModelFactory.create( AudioStreamSliderViewModel.FactoryAudioStreamWrapper(stream), this, ) list.add(viewModel) } } Loading
packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/interactor/AudioSlidersInteractor.kt 0 → 100644 +85 −0 Original line number Diff line number Diff line /* * 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.volume.domain.interactor import android.media.AudioDeviceInfo import android.media.AudioManager import com.android.settingslib.volume.data.repository.AudioRepository 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 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession import com.android.systemui.volume.panel.component.volume.domain.model.SliderType import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.stateIn /** Provides volume sliders to show in the Volume Panel. */ @VolumePanelScope class AudioSlidersInteractor @Inject constructor( @VolumePanelScope scope: CoroutineScope, mediaOutputInteractor: MediaOutputInteractor, audioRepository: AudioRepository, ) { val volumePanelSliders: StateFlow<List<SliderType>> = combineTransform( mediaOutputInteractor.activeMediaDeviceSessions, mediaOutputInteractor.defaultActiveMediaSession, audioRepository.communicationDevice, ) { activeSessions, defaultSession, communicationDevice -> coroutineScope { val viewModels = buildList { if (defaultSession?.isTheSameSession(activeSessions.remote) == true) { addSession(activeSessions.remote) addStream(AudioManager.STREAM_MUSIC) } else { addStream(AudioManager.STREAM_MUSIC) addSession(activeSessions.remote) } if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) { addStream(AudioManager.STREAM_BLUETOOTH_SCO) } else { addStream(AudioManager.STREAM_VOICE_CALL) } addStream(AudioManager.STREAM_RING) addStream(AudioManager.STREAM_NOTIFICATION) addStream(AudioManager.STREAM_ALARM) } emit(viewModels) } } .stateIn(scope, SharingStarted.Eagerly, emptyList()) private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) { if (remoteMediaDeviceSession?.canAdjustVolume == true) { add(SliderType.MediaDeviceCast(remoteMediaDeviceSession)) } } private fun MutableList<SliderType>.addStream(stream: Int) { add(SliderType.Stream(AudioStream(stream))) } }
packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/domain/model/SliderType.kt +2 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.systemui.volume.panel.component.volume.domain.model import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession /** The type of volume slider that can be shown at the UI. */ sealed interface SliderType { Loading @@ -25,5 +26,5 @@ sealed interface SliderType { data class Stream(val stream: AudioStream) : SliderType /** The represents media device casting volume. */ data object MediaDeviceCast : SliderType data class MediaDeviceCast(val session: MediaDeviceSession) : SliderType }
packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt +4 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ constructor( mapOf( AudioStream(AudioManager.STREAM_MUSIC) to R.drawable.ic_music_note, AudioStream(AudioManager.STREAM_VOICE_CALL) to R.drawable.ic_call, AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to R.drawable.ic_call, AudioStream(AudioManager.STREAM_RING) to R.drawable.ic_ring_volume, AudioStream(AudioManager.STREAM_NOTIFICATION) to R.drawable.ic_volume_ringer, AudioStream(AudioManager.STREAM_ALARM) to R.drawable.ic_volume_alarm, Loading @@ -61,6 +62,7 @@ constructor( mapOf( AudioStream(AudioManager.STREAM_MUSIC) to R.string.stream_music, AudioStream(AudioManager.STREAM_VOICE_CALL) to R.string.stream_voice_call, AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to R.string.stream_voice_call, AudioStream(AudioManager.STREAM_RING) to R.string.stream_ring, AudioStream(AudioManager.STREAM_NOTIFICATION) to R.string.stream_notification, AudioStream(AudioManager.STREAM_ALARM) to R.string.stream_alarm, Loading @@ -78,6 +80,8 @@ constructor( VolumePanelUiEvent.VOLUME_PANEL_MUSIC_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_VOICE_CALL) to VolumePanelUiEvent.VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_BLUETOOTH_SCO) to VolumePanelUiEvent.VOLUME_PANEL_VOICE_CALL_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_RING) to VolumePanelUiEvent.VOLUME_PANEL_RING_SLIDER_TOUCHED, AudioStream(AudioManager.STREAM_NOTIFICATION) to Loading
packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt +24 −42 Original line number Diff line number Diff line Loading @@ -16,12 +16,12 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import android.media.AudioManager 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 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession import com.android.systemui.volume.panel.component.volume.domain.interactor.AudioSlidersInteractor import com.android.systemui.volume.panel.component.volume.domain.model.SliderType import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.AudioStreamSliderViewModel import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.SliderViewModel Loading @@ -33,12 +33,12 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combineTransform import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch /** Loading @@ -55,27 +55,20 @@ constructor( private val mediaDeviceSessionInteractor: MediaDeviceSessionInteractor, private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, streamsInteractor: AudioSlidersInteractor, ) { val sliderViewModels: StateFlow<List<SliderViewModel>> = combineTransform( mediaOutputInteractor.activeMediaDeviceSessions, mediaOutputInteractor.defaultActiveMediaSession, ) { activeSessions, defaultSession -> streamsInteractor.volumePanelSliders .transformLatest { sliderTypes -> coroutineScope { val viewModels = buildList { if (defaultSession?.isTheSameSession(activeSessions.remote) == true) { addRemoteViewModelIfNeeded(this, activeSessions.remote) addStreamViewModel(this, AudioManager.STREAM_MUSIC) } else { addStreamViewModel(this, AudioManager.STREAM_MUSIC) addRemoteViewModelIfNeeded(this, activeSessions.remote) val viewModels = sliderTypes.map { type -> when (type) { is SliderType.Stream -> createStreamViewModel(type.stream) is SliderType.MediaDeviceCast -> createSessionViewModel(type.session) } addStreamViewModel(this, AudioManager.STREAM_VOICE_CALL) addStreamViewModel(this, AudioManager.STREAM_RING) addStreamViewModel(this, AudioManager.STREAM_NOTIFICATION) addStreamViewModel(this, AudioManager.STREAM_ALARM) } emit(viewModels) } Loading @@ -98,29 +91,18 @@ constructor( scope.launch { mutableIsExpanded.emit(isExpanded) } } private fun CoroutineScope.addRemoteViewModelIfNeeded( list: MutableList<SliderViewModel>, remoteMediaDeviceSession: MediaDeviceSession? ) { if (remoteMediaDeviceSession?.canAdjustVolume == true) { val viewModel = castVolumeSliderViewModelFactory.create( remoteMediaDeviceSession, this, ) list.add(viewModel) } private fun CoroutineScope.createSessionViewModel( session: MediaDeviceSession ): CastVolumeSliderViewModel { return castVolumeSliderViewModelFactory.create(session, this) } private fun CoroutineScope.addStreamViewModel( list: MutableList<SliderViewModel>, stream: Int, ) { val viewModel = streamSliderViewModelFactory.create( AudioStreamSliderViewModel.FactoryAudioStreamWrapper(AudioStream(stream)), private fun CoroutineScope.createStreamViewModel( stream: AudioStream, ): AudioStreamSliderViewModel { return streamSliderViewModelFactory.create( AudioStreamSliderViewModel.FactoryAudioStreamWrapper(stream), this, ) list.add(viewModel) } }