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.shared 18 19 import android.content.BroadcastReceiver 20 import android.content.Context 21 import android.content.Intent 22 import android.content.IntentFilter 23 import android.media.AudioManager 24 import android.util.Log 25 import com.android.settingslib.volume.shared.model.AudioManagerEvent 26 import com.android.settingslib.volume.shared.model.AudioStream 27 import kotlin.coroutines.CoroutineContext 28 import kotlinx.coroutines.CoroutineScope 29 import kotlinx.coroutines.channels.awaitClose 30 import kotlinx.coroutines.flow.SharedFlow 31 import kotlinx.coroutines.flow.SharingStarted 32 import kotlinx.coroutines.flow.callbackFlow 33 import kotlinx.coroutines.flow.filter 34 import kotlinx.coroutines.flow.filterNotNull 35 import kotlinx.coroutines.flow.flowOn 36 import kotlinx.coroutines.flow.mapNotNull 37 import kotlinx.coroutines.flow.shareIn 38 import kotlinx.coroutines.launch 39 40 /** Exposes [AudioManager] events as a observable shared flow. */ 41 interface AudioManagerEventsReceiver { 42 43 val events: SharedFlow<AudioManagerEvent> 44 } 45 46 class AudioManagerEventsReceiverImpl( 47 private val context: Context, 48 coroutineScope: CoroutineScope, 49 backgroundCoroutineContext: CoroutineContext, 50 ) : AudioManagerEventsReceiver { 51 52 private val allActions: Collection<String> 53 get() = 54 setOf( 55 AudioManager.STREAM_MUTE_CHANGED_ACTION, 56 AudioManager.MASTER_MUTE_CHANGED_ACTION, 57 AudioManager.VOLUME_CHANGED_ACTION, 58 AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION, 59 AudioManager.STREAM_DEVICES_CHANGED_ACTION, 60 AudioManager.ACTION_VOLUME_CHANGED, 61 ) 62 63 override val events: SharedFlow<AudioManagerEvent> = <lambda>null64 callbackFlow { 65 val receiver = 66 object : BroadcastReceiver() { 67 override fun onReceive(context: Context?, intent: Intent?) { 68 launch { send(intent) } 69 } 70 } 71 context.registerReceiver( 72 receiver, 73 IntentFilter().apply { 74 for (action in allActions) { 75 addAction(action) 76 } 77 } 78 ) 79 80 awaitClose { context.unregisterReceiver(receiver) } 81 } 82 .filterNotNull() intentnull83 .filter { intent -> allActions.contains(intent.action) } <lambda>null84 .mapNotNull { it.toAudioManagerEvent() } 85 .flowOn(backgroundCoroutineContext) 86 .shareIn(coroutineScope, SharingStarted.WhileSubscribed()) 87 toAudioManagerEventnull88 private fun Intent.toAudioManagerEvent(): AudioManagerEvent? { 89 when (action) { 90 AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION -> 91 return AudioManagerEvent.InternalRingerModeChanged 92 AudioManager.STREAM_DEVICES_CHANGED_ACTION -> 93 return AudioManagerEvent.StreamDevicesChanged 94 AudioManager.MASTER_MUTE_CHANGED_ACTION -> 95 return AudioManagerEvent.StreamMasterMuteChanged 96 } 97 98 val audioStreamType: Int = 99 getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, AudioManager.ERROR) 100 if (audioStreamType == AudioManager.ERROR) { 101 Log.e( 102 "AudioManagerIntentsReceiver", 103 "Intent doesn't have AudioManager.EXTRA_VOLUME_STREAM_TYPE extra", 104 ) 105 return null 106 } 107 val audioStream = AudioStream(audioStreamType) 108 return when (action) { 109 AudioManager.STREAM_MUTE_CHANGED_ACTION -> 110 AudioManagerEvent.StreamMuteChanged(audioStream) 111 AudioManager.VOLUME_CHANGED_ACTION -> AudioManagerEvent.StreamVolumeChanged(audioStream) 112 else -> null 113 } 114 } 115 } 116