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.bluetooth.qsdialog
18 
19 import com.android.settingslib.bluetooth.CachedBluetoothDevice
20 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast
21 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant
22 import com.android.settingslib.bluetooth.LocalBluetoothManager
23 import com.android.settingslib.bluetooth.onSourceConnectedOrRemoved
24 import com.android.settingslib.volume.data.repository.AudioSharingRepository as SettingsLibAudioSharingRepository
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Background
27 import kotlinx.coroutines.CoroutineDispatcher
28 import kotlinx.coroutines.flow.Flow
29 import kotlinx.coroutines.flow.MutableStateFlow
30 import kotlinx.coroutines.flow.StateFlow
31 import kotlinx.coroutines.flow.emptyFlow
32 import kotlinx.coroutines.withContext
33 
34 interface AudioSharingRepository {
35     val leAudioBroadcastProfile: LocalBluetoothLeBroadcast?
36 
37     val audioSourceStateUpdate: Flow<Unit>
38 
39     val inAudioSharing: StateFlow<Boolean>
40 
41     suspend fun audioSharingAvailable(): Boolean
42 
43     suspend fun addSource()
44 
45     suspend fun setActive(cachedBluetoothDevice: CachedBluetoothDevice)
46 
47     suspend fun startAudioSharing()
48 }
49 
50 @SysUISingleton
51 class AudioSharingRepositoryImpl(
52     private val localBluetoothManager: LocalBluetoothManager,
53     private val settingsLibAudioSharingRepository: SettingsLibAudioSharingRepository,
54     @Background private val backgroundDispatcher: CoroutineDispatcher,
55 ) : AudioSharingRepository {
56 
57     override val leAudioBroadcastProfile: LocalBluetoothLeBroadcast?
58         get() = localBluetoothManager.profileManager?.leAudioBroadcastProfile
59 
60     private val leAudioBroadcastAssistantProfile: LocalBluetoothLeBroadcastAssistant?
61         get() = localBluetoothManager.profileManager?.leAudioBroadcastAssistantProfile
62 
63     override val audioSourceStateUpdate: Flow<Unit> =
64         leAudioBroadcastAssistantProfile?.onSourceConnectedOrRemoved ?: emptyFlow()
65 
66     override val inAudioSharing: StateFlow<Boolean> =
67         settingsLibAudioSharingRepository.inAudioSharing
68 
audioSharingAvailablenull69     override suspend fun audioSharingAvailable(): Boolean {
70         return settingsLibAudioSharingRepository.audioSharingAvailable()
71     }
72 
addSourcenull73     override suspend fun addSource() {
74         withContext(backgroundDispatcher) {
75             if (!settingsLibAudioSharingRepository.audioSharingAvailable()) {
76                 return@withContext
77             }
78             leAudioBroadcastProfile?.latestBluetoothLeBroadcastMetadata?.let { metadata ->
79                 leAudioBroadcastAssistantProfile?.let {
80                     it.allConnectedDevices.forEach { sink -> it.addSource(sink, metadata, false) }
81                 }
82             }
83         }
84     }
85 
setActivenull86     override suspend fun setActive(cachedBluetoothDevice: CachedBluetoothDevice) {
87         withContext(backgroundDispatcher) {
88             if (!settingsLibAudioSharingRepository.audioSharingAvailable()) {
89                 return@withContext
90             }
91             cachedBluetoothDevice.setActive()
92         }
93     }
94 
startAudioSharingnull95     override suspend fun startAudioSharing() {
96         withContext(backgroundDispatcher) {
97             if (!settingsLibAudioSharingRepository.audioSharingAvailable()) {
98                 return@withContext
99             }
100             leAudioBroadcastProfile?.startPrivateBroadcast()
101         }
102     }
103 }
104 
105 @SysUISingleton
106 class AudioSharingRepositoryEmptyImpl : AudioSharingRepository {
107     override val leAudioBroadcastProfile: LocalBluetoothLeBroadcast? = null
108 
109     override val audioSourceStateUpdate: Flow<Unit> = emptyFlow()
110 
111     override val inAudioSharing: StateFlow<Boolean> = MutableStateFlow(false)
112 
audioSharingAvailablenull113     override suspend fun audioSharingAvailable(): Boolean = false
114 
115     override suspend fun addSource() {}
116 
setActivenull117     override suspend fun setActive(cachedBluetoothDevice: CachedBluetoothDevice) {}
118 
startAudioSharingnull119     override suspend fun startAudioSharing() {}
120 }
121