Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt +37 −0 Original line number Diff line number Diff line Loading @@ -101,12 +101,27 @@ class AudioSharingInteractorTest : SysuiTestCase() { } } @Test fun audioSourceStateUpdate_profileNotReady_returnEmpty() = with(kosmos) { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setInAudioSharing(true) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(false) val value by collectLastValue(underTest.audioSourceStateUpdate) runCurrent() assertThat(value).isNull() } } @Test fun audioSourceStateUpdate_notInAudioSharing_returnEmpty() = with(kosmos) { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setInAudioSharing(false) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val value by collectLastValue(underTest.audioSourceStateUpdate) runCurrent() Loading @@ -120,6 +135,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setInAudioSharing(true) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val value by collectLastValue(underTest.audioSourceStateUpdate) runCurrent() bluetoothTileDialogAudioSharingRepository.emitAudioSourceStateUpdate() Loading Loading @@ -158,6 +174,23 @@ class AudioSharingInteractorTest : SysuiTestCase() { } } @Test fun handleAudioSourceWhenReady_profileNotReady_sourceNotAdded() = with(kosmos) { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(false) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() assertThat(bluetoothTileDialogAudioSharingRepository.sourceAdded).isFalse() job.cancel() } } @Test fun handleAudioSourceWhenReady_hasProfileButAudioSharingNeverTriggered_sourceNotAdded() = with(kosmos) { Loading @@ -166,6 +199,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() Loading @@ -184,6 +218,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() // Verify callback registered for onBroadcastStartedOrStopped Loading @@ -209,6 +244,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() // Verify callback registered for onBroadcastStartedOrStopped Loading @@ -234,6 +270,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() // Verify callback registered for onBroadcastStartedOrStopped Loading packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingRepositoryTest.kt +38 −3 Original line number Diff line number Diff line Loading @@ -24,10 +24,12 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant import com.android.settingslib.bluetooth.LocalBluetoothProfileManager import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.android.systemui.volume.data.repository.audioSharingRepository import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before Loading Loading @@ -58,12 +60,14 @@ class AudioSharingRepositoryTest : SysuiTestCase() { @Before fun setUp() { whenever(kosmos.localBluetoothManager.profileManager).thenReturn(profileManager) underTest = AudioSharingRepositoryImpl( kosmos.localBluetoothManager, kosmos.audioSharingRepository, kosmos.bluetoothTileDialogLogger, kosmos.testDispatcher, kosmos.testScope.backgroundScope, ) } Loading Loading @@ -91,7 +95,6 @@ class AudioSharingRepositoryTest : SysuiTestCase() { fun testStartAudioSharing() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) audioSharingRepository.setAudioSharingAvailable(true) underTest.startAudioSharing() Loading @@ -117,7 +120,6 @@ class AudioSharingRepositoryTest : SysuiTestCase() { fun testStopAudioSharing() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) audioSharingRepository.setAudioSharingAvailable(true) underTest.stopAudioSharing() Loading Loading @@ -155,7 +157,6 @@ class AudioSharingRepositoryTest : SysuiTestCase() { fun testAddSource_noMetadata_doesNothing() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) audioSharingRepository.setAudioSharingAvailable(true) whenever(leAudioBroadcastProfile.latestBluetoothLeBroadcastMetadata) Loading Loading @@ -212,4 +213,38 @@ class AudioSharingRepositoryTest : SysuiTestCase() { .logAudioSharingRequest(AudioSharingRequest.ADD_SOURCE) } } @Test fun testIsAudioSharingProfilesReady_notReady() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) whenever(profileManager.leAudioBroadcastAssistantProfile) .thenReturn(leAudioBroadcastAssistant) whenever(leAudioBroadcastProfile.isProfileReady).thenReturn(false) whenever(leAudioBroadcastAssistant.isProfileReady).thenReturn(false) val value by collectLastValue(underTest.isAudioSharingProfilesReady) runCurrent() assertThat(value).isFalse() } } @Test fun testIsAudioSharingProfilesReady_ready() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) whenever(profileManager.leAudioBroadcastAssistantProfile) .thenReturn(leAudioBroadcastAssistant) whenever(leAudioBroadcastProfile.isProfileReady).thenReturn(true) whenever(leAudioBroadcastAssistant.isProfileReady).thenReturn(true) val value by collectLastValue(underTest.isAudioSharingProfilesReady) runCurrent() assertThat(value).isTrue() } } } packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt +8 −5 Original line number Diff line number Diff line Loading @@ -31,7 +31,9 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow Loading Loading @@ -109,10 +111,11 @@ constructor( override suspend fun handleAudioSourceWhenReady() { withContext(backgroundDispatcher) { if (audioSharingAvailable()) { audioSharingRepository.isAudioSharingProfilesReady.filter { it }.first() audioSharingRepository.leAudioBroadcastProfile?.let { profile -> merge( // Register and start listen to onBroadcastMetadataChanged (means ready // to add source) // Register and start listen to onBroadcastMetadataChanged // (means ready to add source) audioSharingStartedEvents.receiveAsFlow().map { true }, // When session is off or failed to start, stop listening to // onBroadcastMetadataChanged as we won't be adding source Loading @@ -122,9 +125,9 @@ constructor( ) .mapNotNull { shouldListenToMetadata -> if (shouldListenToMetadata) { // onBroadcastMetadataChanged could emit multiple times during one // audio sharing session, we only perform add source on the first // time // onBroadcastMetadataChanged could emit multiple times // during one audio sharing session, we only perform add // source on the first time profile.onBroadcastMetadataChanged.firstOrNull() } else { null Loading packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingRepository.kt +40 −3 Original line number Diff line number Diff line Loading @@ -20,18 +20,29 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.settingslib.bluetooth.onServiceStateChanged import com.android.settingslib.bluetooth.onSourceConnectedOrRemoved import com.android.settingslib.volume.data.repository.AudioSharingRepository as SettingsLibAudioSharingRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext interface AudioSharingRepository { val isAudioSharingProfilesReady: StateFlow<Boolean> val leAudioBroadcastProfile: LocalBluetoothLeBroadcast? val audioSourceStateUpdate: Flow<Unit> Loading @@ -55,16 +66,40 @@ class AudioSharingRepositoryImpl( private val settingsLibAudioSharingRepository: SettingsLibAudioSharingRepository, private val logger: BluetoothTileDialogLogger, @Background private val backgroundDispatcher: CoroutineDispatcher, @Application private val coroutineScope: CoroutineScope, ) : AudioSharingRepository { override val leAudioBroadcastProfile: LocalBluetoothLeBroadcast? get() = localBluetoothManager.profileManager?.leAudioBroadcastProfile get() = localBluetoothManager.profileManager.leAudioBroadcastProfile private val leAudioBroadcastAssistantProfile: LocalBluetoothLeBroadcastAssistant? get() = localBluetoothManager.profileManager?.leAudioBroadcastAssistantProfile get() = localBluetoothManager.profileManager.leAudioBroadcastAssistantProfile override val isAudioSharingProfilesReady: StateFlow<Boolean> = localBluetoothManager.profileManager.onServiceStateChanged .map { leAudioBroadcastProfile?.isProfileReady == true && leAudioBroadcastAssistantProfile?.isProfileReady == true } .onStart { emit( leAudioBroadcastProfile?.isProfileReady == true && leAudioBroadcastAssistantProfile?.isProfileReady == true ) } .flowOn(backgroundDispatcher) .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), false) override val audioSourceStateUpdate: Flow<Unit> = isAudioSharingProfilesReady .flatMapLatest { if (it) { leAudioBroadcastAssistantProfile?.onSourceConnectedOrRemoved ?: emptyFlow() } else { emptyFlow() } } .flowOn(backgroundDispatcher) override val inAudioSharing: StateFlow<Boolean> = settingsLibAudioSharingRepository.inAudioSharing Loading Loading @@ -124,6 +159,8 @@ class AudioSharingRepositoryImpl( @SysUISingleton class AudioSharingRepositoryEmptyImpl : AudioSharingRepository { override val isAudioSharingProfilesReady: StateFlow<Boolean> = MutableStateFlow(false) override val leAudioBroadcastProfile: LocalBluetoothLeBroadcast? = null override val audioSourceStateUpdate: Flow<Unit> = emptyFlow() Loading packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/dagger/AudioSharingModule.kt +4 −0 Original line number Diff line number Diff line Loading @@ -38,11 +38,13 @@ import com.android.systemui.bluetooth.qsdialog.DeviceItemFactory import com.android.systemui.bluetooth.qsdialog.DeviceItemType import com.android.systemui.bluetooth.qsdialog.SavedDeviceItemFactory import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import dagger.Lazy import dagger.Module import dagger.Provides import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope /** Dagger module for audio sharing code for BT QS dialog */ @Module Loading @@ -56,6 +58,7 @@ interface AudioSharingModule { settingsLibAudioSharingRepository: SettingsLibAudioSharingRepository, logger: BluetoothTileDialogLogger, @Background backgroundDispatcher: CoroutineDispatcher, @Application coroutineScope: CoroutineScope, ): AudioSharingRepository = if ( (Flags.enableLeAudioSharing() || Flags.audioSharingDeveloperOption()) && Loading @@ -66,6 +69,7 @@ interface AudioSharingModule { settingsLibAudioSharingRepository, logger, backgroundDispatcher, coroutineScope, ) } else { AudioSharingRepositoryEmptyImpl() Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractorTest.kt +37 −0 Original line number Diff line number Diff line Loading @@ -101,12 +101,27 @@ class AudioSharingInteractorTest : SysuiTestCase() { } } @Test fun audioSourceStateUpdate_profileNotReady_returnEmpty() = with(kosmos) { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setInAudioSharing(true) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(false) val value by collectLastValue(underTest.audioSourceStateUpdate) runCurrent() assertThat(value).isNull() } } @Test fun audioSourceStateUpdate_notInAudioSharing_returnEmpty() = with(kosmos) { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setInAudioSharing(false) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val value by collectLastValue(underTest.audioSourceStateUpdate) runCurrent() Loading @@ -120,6 +135,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setInAudioSharing(true) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val value by collectLastValue(underTest.audioSourceStateUpdate) runCurrent() bluetoothTileDialogAudioSharingRepository.emitAudioSourceStateUpdate() Loading Loading @@ -158,6 +174,23 @@ class AudioSharingInteractorTest : SysuiTestCase() { } } @Test fun handleAudioSourceWhenReady_profileNotReady_sourceNotAdded() = with(kosmos) { testScope.runTest { bluetoothTileDialogAudioSharingRepository.setAudioSharingAvailable(true) bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(false) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() assertThat(bluetoothTileDialogAudioSharingRepository.sourceAdded).isFalse() job.cancel() } } @Test fun handleAudioSourceWhenReady_hasProfileButAudioSharingNeverTriggered_sourceNotAdded() = with(kosmos) { Loading @@ -166,6 +199,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() Loading @@ -184,6 +218,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() // Verify callback registered for onBroadcastStartedOrStopped Loading @@ -209,6 +244,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() // Verify callback registered for onBroadcastStartedOrStopped Loading @@ -234,6 +270,7 @@ class AudioSharingInteractorTest : SysuiTestCase() { bluetoothTileDialogAudioSharingRepository.setLeAudioBroadcastProfile( localBluetoothLeBroadcast ) bluetoothTileDialogAudioSharingRepository.setIsAudioSharingProfilesReady(true) val job = launch { underTest.handleAudioSourceWhenReady() } runCurrent() // Verify callback registered for onBroadcastStartedOrStopped Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/bluetooth/qsdialog/AudioSharingRepositoryTest.kt +38 −3 Original line number Diff line number Diff line Loading @@ -24,10 +24,12 @@ import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant import com.android.settingslib.bluetooth.LocalBluetoothProfileManager import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.testKosmos import com.android.systemui.volume.data.repository.audioSharingRepository import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before Loading Loading @@ -58,12 +60,14 @@ class AudioSharingRepositoryTest : SysuiTestCase() { @Before fun setUp() { whenever(kosmos.localBluetoothManager.profileManager).thenReturn(profileManager) underTest = AudioSharingRepositoryImpl( kosmos.localBluetoothManager, kosmos.audioSharingRepository, kosmos.bluetoothTileDialogLogger, kosmos.testDispatcher, kosmos.testScope.backgroundScope, ) } Loading Loading @@ -91,7 +95,6 @@ class AudioSharingRepositoryTest : SysuiTestCase() { fun testStartAudioSharing() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) audioSharingRepository.setAudioSharingAvailable(true) underTest.startAudioSharing() Loading @@ -117,7 +120,6 @@ class AudioSharingRepositoryTest : SysuiTestCase() { fun testStopAudioSharing() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) audioSharingRepository.setAudioSharingAvailable(true) underTest.stopAudioSharing() Loading Loading @@ -155,7 +157,6 @@ class AudioSharingRepositoryTest : SysuiTestCase() { fun testAddSource_noMetadata_doesNothing() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) audioSharingRepository.setAudioSharingAvailable(true) whenever(leAudioBroadcastProfile.latestBluetoothLeBroadcastMetadata) Loading Loading @@ -212,4 +213,38 @@ class AudioSharingRepositoryTest : SysuiTestCase() { .logAudioSharingRequest(AudioSharingRequest.ADD_SOURCE) } } @Test fun testIsAudioSharingProfilesReady_notReady() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) whenever(profileManager.leAudioBroadcastAssistantProfile) .thenReturn(leAudioBroadcastAssistant) whenever(leAudioBroadcastProfile.isProfileReady).thenReturn(false) whenever(leAudioBroadcastAssistant.isProfileReady).thenReturn(false) val value by collectLastValue(underTest.isAudioSharingProfilesReady) runCurrent() assertThat(value).isFalse() } } @Test fun testIsAudioSharingProfilesReady_ready() = with(kosmos) { testScope.runTest { whenever(localBluetoothManager.profileManager).thenReturn(profileManager) whenever(profileManager.leAudioBroadcastProfile).thenReturn(leAudioBroadcastProfile) whenever(profileManager.leAudioBroadcastAssistantProfile) .thenReturn(leAudioBroadcastAssistant) whenever(leAudioBroadcastProfile.isProfileReady).thenReturn(true) whenever(leAudioBroadcastAssistant.isProfileReady).thenReturn(true) val value by collectLastValue(underTest.isAudioSharingProfilesReady) runCurrent() assertThat(value).isTrue() } } }
packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingInteractor.kt +8 −5 Original line number Diff line number Diff line Loading @@ -31,7 +31,9 @@ import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filterNot import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flow Loading Loading @@ -109,10 +111,11 @@ constructor( override suspend fun handleAudioSourceWhenReady() { withContext(backgroundDispatcher) { if (audioSharingAvailable()) { audioSharingRepository.isAudioSharingProfilesReady.filter { it }.first() audioSharingRepository.leAudioBroadcastProfile?.let { profile -> merge( // Register and start listen to onBroadcastMetadataChanged (means ready // to add source) // Register and start listen to onBroadcastMetadataChanged // (means ready to add source) audioSharingStartedEvents.receiveAsFlow().map { true }, // When session is off or failed to start, stop listening to // onBroadcastMetadataChanged as we won't be adding source Loading @@ -122,9 +125,9 @@ constructor( ) .mapNotNull { shouldListenToMetadata -> if (shouldListenToMetadata) { // onBroadcastMetadataChanged could emit multiple times during one // audio sharing session, we only perform add source on the first // time // onBroadcastMetadataChanged could emit multiple times // during one audio sharing session, we only perform add // source on the first time profile.onBroadcastMetadataChanged.firstOrNull() } else { null Loading
packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/AudioSharingRepository.kt +40 −3 Original line number Diff line number Diff line Loading @@ -20,18 +20,29 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcastAssistant import com.android.settingslib.bluetooth.LocalBluetoothManager import com.android.settingslib.bluetooth.onServiceStateChanged import com.android.settingslib.bluetooth.onSourceConnectedOrRemoved import com.android.settingslib.volume.data.repository.AudioSharingRepository as SettingsLibAudioSharingRepository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext interface AudioSharingRepository { val isAudioSharingProfilesReady: StateFlow<Boolean> val leAudioBroadcastProfile: LocalBluetoothLeBroadcast? val audioSourceStateUpdate: Flow<Unit> Loading @@ -55,16 +66,40 @@ class AudioSharingRepositoryImpl( private val settingsLibAudioSharingRepository: SettingsLibAudioSharingRepository, private val logger: BluetoothTileDialogLogger, @Background private val backgroundDispatcher: CoroutineDispatcher, @Application private val coroutineScope: CoroutineScope, ) : AudioSharingRepository { override val leAudioBroadcastProfile: LocalBluetoothLeBroadcast? get() = localBluetoothManager.profileManager?.leAudioBroadcastProfile get() = localBluetoothManager.profileManager.leAudioBroadcastProfile private val leAudioBroadcastAssistantProfile: LocalBluetoothLeBroadcastAssistant? get() = localBluetoothManager.profileManager?.leAudioBroadcastAssistantProfile get() = localBluetoothManager.profileManager.leAudioBroadcastAssistantProfile override val isAudioSharingProfilesReady: StateFlow<Boolean> = localBluetoothManager.profileManager.onServiceStateChanged .map { leAudioBroadcastProfile?.isProfileReady == true && leAudioBroadcastAssistantProfile?.isProfileReady == true } .onStart { emit( leAudioBroadcastProfile?.isProfileReady == true && leAudioBroadcastAssistantProfile?.isProfileReady == true ) } .flowOn(backgroundDispatcher) .stateIn(coroutineScope, SharingStarted.WhileSubscribed(), false) override val audioSourceStateUpdate: Flow<Unit> = isAudioSharingProfilesReady .flatMapLatest { if (it) { leAudioBroadcastAssistantProfile?.onSourceConnectedOrRemoved ?: emptyFlow() } else { emptyFlow() } } .flowOn(backgroundDispatcher) override val inAudioSharing: StateFlow<Boolean> = settingsLibAudioSharingRepository.inAudioSharing Loading Loading @@ -124,6 +159,8 @@ class AudioSharingRepositoryImpl( @SysUISingleton class AudioSharingRepositoryEmptyImpl : AudioSharingRepository { override val isAudioSharingProfilesReady: StateFlow<Boolean> = MutableStateFlow(false) override val leAudioBroadcastProfile: LocalBluetoothLeBroadcast? = null override val audioSourceStateUpdate: Flow<Unit> = emptyFlow() Loading
packages/SystemUI/src/com/android/systemui/bluetooth/qsdialog/dagger/AudioSharingModule.kt +4 −0 Original line number Diff line number Diff line Loading @@ -38,11 +38,13 @@ import com.android.systemui.bluetooth.qsdialog.DeviceItemFactory import com.android.systemui.bluetooth.qsdialog.DeviceItemType import com.android.systemui.bluetooth.qsdialog.SavedDeviceItemFactory import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import dagger.Lazy import dagger.Module import dagger.Provides import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope /** Dagger module for audio sharing code for BT QS dialog */ @Module Loading @@ -56,6 +58,7 @@ interface AudioSharingModule { settingsLibAudioSharingRepository: SettingsLibAudioSharingRepository, logger: BluetoothTileDialogLogger, @Background backgroundDispatcher: CoroutineDispatcher, @Application coroutineScope: CoroutineScope, ): AudioSharingRepository = if ( (Flags.enableLeAudioSharing() || Flags.audioSharingDeveloperOption()) && Loading @@ -66,6 +69,7 @@ interface AudioSharingModule { settingsLibAudioSharingRepository, logger, backgroundDispatcher, coroutineScope, ) } else { AudioSharingRepositoryEmptyImpl() Loading