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