1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.volume.panel.component.volume.domain.interactor
18 
19 import android.media.AudioDeviceInfo
20 import android.media.AudioManager
21 import com.android.settingslib.volume.data.repository.AudioRepository
22 import com.android.settingslib.volume.shared.model.AudioStream
23 import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor
24 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.MediaDeviceSession
25 import com.android.systemui.volume.panel.component.mediaoutput.shared.model.isTheSameSession
26 import com.android.systemui.volume.panel.component.volume.domain.model.SliderType
27 import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope
28 import com.android.systemui.volume.panel.shared.model.filterData
29 import javax.inject.Inject
30 import kotlinx.coroutines.CoroutineScope
31 import kotlinx.coroutines.coroutineScope
32 import kotlinx.coroutines.flow.SharingStarted
33 import kotlinx.coroutines.flow.StateFlow
34 import kotlinx.coroutines.flow.combineTransform
35 import kotlinx.coroutines.flow.stateIn
36 
37 /** Provides volume sliders to show in the Volume Panel. */
38 @VolumePanelScope
39 class AudioSlidersInteractor
40 @Inject
41 constructor(
42     @VolumePanelScope scope: CoroutineScope,
43     mediaOutputInteractor: MediaOutputInteractor,
44     audioRepository: AudioRepository,
45 ) {
46 
47     val volumePanelSliders: StateFlow<List<SliderType>> =
48         combineTransform(
49                 mediaOutputInteractor.activeMediaDeviceSessions,
50                 mediaOutputInteractor.defaultActiveMediaSession.filterData(),
51                 audioRepository.communicationDevice,
52             ) { activeSessions, defaultSession, communicationDevice ->
53                 coroutineScope {
54                     val viewModels = buildList {
55                         if (defaultSession?.isTheSameSession(activeSessions.remote) == true) {
56                             addSession(activeSessions.remote)
57                             addStream(AudioManager.STREAM_MUSIC)
58                         } else {
59                             addStream(AudioManager.STREAM_MUSIC)
60                             addSession(activeSessions.remote)
61                         }
62 
63                         if (communicationDevice?.type == AudioDeviceInfo.TYPE_BLUETOOTH_SCO) {
64                             addStream(AudioManager.STREAM_BLUETOOTH_SCO)
65                         } else {
66                             addStream(AudioManager.STREAM_VOICE_CALL)
67                         }
68                         addStream(AudioManager.STREAM_RING)
69                         addStream(AudioManager.STREAM_NOTIFICATION)
70                         addStream(AudioManager.STREAM_ALARM)
71                     }
72                     emit(viewModels)
73                 }
74             }
75             .stateIn(scope, SharingStarted.Eagerly, emptyList())
76 
77     private fun MutableList<SliderType>.addSession(remoteMediaDeviceSession: MediaDeviceSession?) {
78         if (remoteMediaDeviceSession?.canAdjustVolume == true) {
79             add(SliderType.MediaDeviceCast(remoteMediaDeviceSession))
80         }
81     }
82 
83     private fun MutableList<SliderType>.addStream(stream: Int) {
84         add(SliderType.Stream(AudioStream(stream)))
85     }
86 }
87