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.settingslib.volume.data.repository 18 19 import android.bluetooth.BluetoothLeBroadcast 20 import android.bluetooth.BluetoothLeBroadcastMetadata 21 import com.android.internal.util.ConcurrentUtils 22 import com.android.settingslib.bluetooth.LocalBluetoothManager 23 import com.android.settingslib.flags.Flags 24 import kotlin.coroutines.CoroutineContext 25 import kotlinx.coroutines.channels.awaitClose 26 import kotlinx.coroutines.flow.Flow 27 import kotlinx.coroutines.flow.callbackFlow 28 import kotlinx.coroutines.flow.flowOf 29 import kotlinx.coroutines.flow.flowOn 30 import kotlinx.coroutines.flow.onStart 31 import kotlinx.coroutines.launch 32 33 /** Provides audio sharing functionality. */ 34 interface AudioSharingRepository { 35 /** Whether the device is in audio sharing. */ 36 val inAudioSharing: Flow<Boolean> 37 } 38 39 class AudioSharingRepositoryImpl( 40 private val localBluetoothManager: LocalBluetoothManager?, 41 backgroundCoroutineContext: CoroutineContext, 42 ) : AudioSharingRepository { 43 override val inAudioSharing: Flow<Boolean> = 44 if (Flags.enableLeAudioSharing()) { leBroadcastnull45 localBluetoothManager?.profileManager?.leAudioBroadcastProfile?.let { leBroadcast -> 46 callbackFlow { 47 val listener = 48 object : BluetoothLeBroadcast.Callback { 49 override fun onBroadcastStarted(reason: Int, broadcastId: Int) { 50 launch { send(isBroadcasting()) } 51 } 52 53 override fun onBroadcastStartFailed(reason: Int) { 54 launch { send(isBroadcasting()) } 55 } 56 57 override fun onBroadcastStopped(reason: Int, broadcastId: Int) { 58 launch { send(isBroadcasting()) } 59 } 60 61 override fun onBroadcastStopFailed(reason: Int) { 62 launch { send(isBroadcasting()) } 63 } 64 65 override fun onPlaybackStarted(reason: Int, broadcastId: Int) {} 66 67 override fun onPlaybackStopped(reason: Int, broadcastId: Int) {} 68 69 override fun onBroadcastUpdated(reason: Int, broadcastId: Int) {} 70 71 override fun onBroadcastUpdateFailed( 72 reason: Int, 73 broadcastId: Int 74 ) {} 75 76 override fun onBroadcastMetadataChanged( 77 broadcastId: Int, 78 metadata: BluetoothLeBroadcastMetadata 79 ) {} 80 } 81 82 leBroadcast.registerServiceCallBack( 83 ConcurrentUtils.DIRECT_EXECUTOR, 84 listener, 85 ) 86 awaitClose { leBroadcast.unregisterServiceCallBack(listener) } 87 } 88 .onStart { emit(isBroadcasting()) } 89 .flowOn(backgroundCoroutineContext) 90 } ?: flowOf(false) 91 } else { 92 flowOf(false) 93 } 94 isBroadcastingnull95 private fun isBroadcasting(): Boolean { 96 return Flags.enableLeAudioSharing() && 97 (localBluetoothManager?.profileManager?.leAudioBroadcastProfile?.isEnabled(null) 98 ?: false) 99 } 100 } 101