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