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