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.systemui.plugins
18
19 import android.media.AudioManager
20 import android.media.AudioManager.CsdWarning
21 import android.os.Handler
22 import android.os.VibrationEffect
23 import androidx.core.util.getOrElse
24 import java.util.concurrent.CopyOnWriteArraySet
25
26 class FakeVolumeDialogController(private val audioManager: AudioManager) : VolumeDialogController {
27
28 var isVisible: Boolean = false
29 private set
30
31 var hasScheduledTouchFeedback: Boolean = false
32 private set
33
34 var vibrationEffect: VibrationEffect? = null
35 private set
36
37 var hasUserActivity: Boolean = false
38 private set
39
40 private val callbacks = CopyOnWriteArraySet<VolumeDialogController.Callbacks>()
41
42 private var hasVibrator: Boolean = true
43 private var state = VolumeDialogController.State()
44
45 override fun setActiveStream(stream: Int) {
46 updateState {
47 // ensure streamState existence for the active stream`
48 states.getOrElse(stream) {
49 VolumeDialogController.StreamState().also { streamState ->
50 state.states.put(stream, streamState)
51 }
52 }
53 activeStream = stream
54 }
55 }
56
57 override fun setStreamVolume(stream: Int, userLevel: Int) {
58 updateState {
59 val streamState =
60 states.getOrElse(stream) {
61 VolumeDialogController.StreamState().also { streamState ->
62 states.put(stream, streamState)
63 }
64 }
65 streamState.level = userLevel.coerceIn(streamState.levelMin, streamState.levelMax)
66 }
67 }
68
69 override fun setRingerMode(ringerModeNormal: Int, external: Boolean) {
70 updateState {
71 if (external) {
72 ringerModeExternal = ringerModeNormal
73 } else {
74 ringerModeInternal = ringerModeNormal
75 }
76 }
77 }
78
79 fun setHasVibrator(hasVibrator: Boolean) {
80 this.hasVibrator = hasVibrator
81 }
82
83 override fun hasVibrator(): Boolean = hasVibrator
84
85 override fun vibrate(effect: VibrationEffect) {
86 vibrationEffect = effect
87 }
88
89 override fun scheduleTouchFeedback() {
90 hasScheduledTouchFeedback = true
91 }
92
93 fun resetScheduledTouchFeedback() {
94 hasScheduledTouchFeedback = false
95 }
96
97 override fun getAudioManager(): AudioManager = audioManager
98
99 override fun notifyVisible(visible: Boolean) {
100 isVisible = visible
101 }
102
103 override fun addCallback(callbacks: VolumeDialogController.Callbacks?, handler: Handler?) {
104 this.callbacks.add(callbacks)
105 }
106
107 override fun removeCallback(callbacks: VolumeDialogController.Callbacks?) {
108 this.callbacks.remove(callbacks)
109 }
110
111 override fun userActivity() {
112 hasUserActivity = true
113 }
114
115 fun resetUserActivity() {
116 hasUserActivity = false
117 }
118
119 fun updateState(update: VolumeDialogController.State.() -> Unit) {
120 state = state.copy().apply(update)
121 getState()
122 }
123
124 override fun getState() {
125 callbacks.sendEvent { it.onStateChanged(state) }
126 }
127
128 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowRequested */
129 fun onShowRequested(reason: Int, keyguardLocked: Boolean, lockTaskModeState: Int) {
130 callbacks.sendEvent { it.onShowRequested(reason, keyguardLocked, lockTaskModeState) }
131 }
132
133 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onDismissRequested */
134 fun onDismissRequested(reason: Int) {
135 callbacks.sendEvent { it.onDismissRequested(reason) }
136 }
137
138 /**
139 * @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onLayoutDirectionChanged
140 */
141 fun onLayoutDirectionChanged(layoutDirection: Int) {
142 callbacks.sendEvent { it.onLayoutDirectionChanged(layoutDirection) }
143 }
144
145 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onConfigurationChanged */
146 fun onConfigurationChanged() {
147 callbacks.sendEvent { it.onConfigurationChanged() }
148 }
149
150 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowVibrateHint */
151 fun onShowVibrateHint() {
152 callbacks.sendEvent { it.onShowVibrateHint() }
153 }
154
155 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowSilentHint */
156 fun onShowSilentHint() {
157 callbacks.sendEvent { it.onShowSilentHint() }
158 }
159
160 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onScreenOff */
161 fun onScreenOff() {
162 callbacks.sendEvent { it.onScreenOff() }
163 }
164
165 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowSafetyWarning */
166 fun onShowSafetyWarning(flags: Int) {
167 callbacks.sendEvent { it.onShowSafetyWarning(flags) }
168 }
169
170 /**
171 * @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onAccessibilityModeChanged
172 */
173 fun onAccessibilityModeChanged(showA11yStream: Boolean?) {
174 callbacks.sendEvent { it.onAccessibilityModeChanged(showA11yStream) }
175 }
176
177 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onShowCsdWarning */
178 fun onShowCsdWarning(@CsdWarning csdWarning: Int, durationMs: Int) {
179 callbacks.sendEvent { it.onShowCsdWarning(csdWarning, durationMs) }
180 }
181
182 /** @see com.android.systemui.plugins.VolumeDialogController.Callbacks.onVolumeChangedFromKey */
183 fun onVolumeChangedFromKey() {
184 callbacks.sendEvent { it.onVolumeChangedFromKey() }
185 }
186
187 override fun getCaptionsEnabledState(checkForSwitchState: Boolean) {
188 error("Unsupported for the new Volume Dialog")
189 }
190
191 override fun setCaptionsEnabledState(enabled: Boolean) {
192 error("Unsupported for the new Volume Dialog")
193 }
194
195 override fun getCaptionsComponentState(fromTooltip: Boolean) {
196 error("Unsupported for the new Volume Dialog")
197 }
198 }
199
sendEventnull200 private inline fun CopyOnWriteArraySet<VolumeDialogController.Callbacks>.sendEvent(
201 event: (callback: VolumeDialogController.Callbacks) -> Unit
202 ) {
203 for (callback in this) {
204 event(callback)
205 }
206 }
207