1 /*
<lambda>null2  * Copyright (C) 2023 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 androidx.annotation.StringRes
20 import com.android.settingslib.bluetooth.BluetoothUtils
21 import com.android.settingslib.bluetooth.LocalBluetoothManager
22 import com.android.systemui.dagger.SysUISingleton
23 import com.android.systemui.dagger.qualifiers.Application
24 import com.android.systemui.dagger.qualifiers.Background
25 import com.android.systemui.res.R
26 import javax.inject.Inject
27 import kotlinx.coroutines.CoroutineDispatcher
28 import kotlinx.coroutines.CoroutineScope
29 import kotlinx.coroutines.flow.Flow
30 import kotlinx.coroutines.flow.SharingStarted
31 import kotlinx.coroutines.flow.combine
32 import kotlinx.coroutines.flow.flowOn
33 import kotlinx.coroutines.flow.stateIn
34 
35 internal sealed class AudioSharingButtonState {
36     object Gone : AudioSharingButtonState()
37     data class Visible(@StringRes val resId: Int) : AudioSharingButtonState()
38 }
39 
40 /** Holds business logic for the audio sharing state. */
41 @SysUISingleton
42 internal class AudioSharingInteractor
43 @Inject
44 constructor(
45     private val localBluetoothManager: LocalBluetoothManager?,
46     bluetoothStateInteractor: BluetoothStateInteractor,
47     deviceItemInteractor: DeviceItemInteractor,
48     @Application private val coroutineScope: CoroutineScope,
49     @Background private val backgroundDispatcher: CoroutineDispatcher,
50 ) {
51     /** Flow representing the update of AudioSharingButtonState. */
52     internal val audioSharingButtonStateUpdate: Flow<AudioSharingButtonState> =
53         combine(
54                 bluetoothStateInteractor.bluetoothStateUpdate,
55                 deviceItemInteractor.deviceItemUpdate
bluetoothStatenull56             ) { bluetoothState, deviceItem ->
57                 getButtonState(bluetoothState, deviceItem)
58             }
59             .flowOn(backgroundDispatcher)
60             .stateIn(
61                 coroutineScope,
62                 SharingStarted.WhileSubscribed(replayExpirationMillis = 0),
63                 initialValue = AudioSharingButtonState.Gone
64             )
65 
getButtonStatenull66     private fun getButtonState(
67         bluetoothState: Boolean,
68         deviceItem: List<DeviceItem>
69     ): AudioSharingButtonState {
70         return when {
71             // Don't show button when bluetooth is off
72             !bluetoothState -> AudioSharingButtonState.Gone
73             // Show sharing audio when broadcasting
74             BluetoothUtils.isBroadcasting(localBluetoothManager) ->
75                 AudioSharingButtonState.Visible(
76                     R.string.quick_settings_bluetooth_audio_sharing_button_sharing
77                 )
78             // When not broadcasting, don't show button if there's connected source in any device
79             deviceItem.any {
80                 BluetoothUtils.hasConnectedBroadcastSource(
81                     it.cachedBluetoothDevice,
82                     localBluetoothManager
83                 )
84             } -> AudioSharingButtonState.Gone
85             // Show audio sharing when there's a connected LE audio device
86             deviceItem.any { BluetoothUtils.isActiveLeAudioDevice(it.cachedBluetoothDevice) } ->
87                 AudioSharingButtonState.Visible(
88                     R.string.quick_settings_bluetooth_audio_sharing_button
89                 )
90             else -> AudioSharingButtonState.Gone
91         }
92     }
93 }
94