1 /*
2  * Copyright (C) 2023 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.server.hdmi;
18 
19 import static android.media.AudioDeviceVolumeManager.OnAudioDeviceVolumeChangedListener;
20 import static android.media.AudioDeviceVolumeManager.OnDeviceVolumeBehaviorChangedListener;
21 
22 import android.annotation.CallbackExecutor;
23 import android.annotation.NonNull;
24 import android.media.AudioAttributes;
25 import android.media.AudioDeviceAttributes;
26 import android.media.AudioManager;
27 import android.media.AudioSystem;
28 import android.media.VolumeInfo;
29 
30 import java.util.Collections;
31 import java.util.HashMap;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.concurrent.Executor;
37 
38 /**
39  * Contains a fake AudioManager and fake AudioDeviceVolumeManager.
40  * Stores the shared state for these managers, simulating a fake AudioService.
41  */
42 public class FakeAudioFramework {
43 
44     private final FakeAudioManagerWrapper mAudioManager = new FakeAudioManagerWrapper();
45     private final FakeAudioDeviceVolumeManagerWrapper mAudioDeviceVolumeManager =
46             new FakeAudioDeviceVolumeManagerWrapper();
47 
48     private static final int DEFAULT_DEVICE_VOLUME_BEHAVIOR =
49             AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE;
50     private final Map<AudioDeviceAttributes, Integer> mDeviceVolumeBehaviors = new HashMap<>();
51 
52     private final Set<OnDeviceVolumeBehaviorChangedListener> mVolumeBehaviorListeners =
53             new HashSet<>();
54 
55     private final Map<AudioAttributes, List<AudioDeviceAttributes>> mDevicesForAttributes =
56             new HashMap<>();
57 
58     private static final int DEFAULT_VOLUME = 0;
59     private final Map<Integer, Integer> mStreamVolumes = new HashMap<>();
60 
61     private static final int DEFAULT_MAX_VOLUME = 100;
62     private final Map<Integer, Integer> mStreamMaxVolumes = new HashMap<>();
63 
64     private static final boolean DEFAULT_MUTE_STATUS = false;
65     private final Map<Integer, Boolean> mStreamMuteStatuses = new HashMap<>();
66 
FakeAudioFramework()67     public FakeAudioFramework() {
68     }
69 
70     /**
71      * Returns a fake AudioManager whose methods affect this object's internal state.
72      */
getAudioManager()73     public FakeAudioManagerWrapper getAudioManager() {
74         return mAudioManager;
75     }
76 
77     public class FakeAudioManagerWrapper implements AudioManagerWrapper {
78         @Override
adjustStreamVolume(int streamType, int direction, @AudioManager.PublicVolumeFlags int flags)79         public void adjustStreamVolume(int streamType, int direction,
80                 @AudioManager.PublicVolumeFlags int flags) {
81             switch (direction) {
82                 case AudioManager.ADJUST_MUTE:
83                     mStreamMuteStatuses.put(streamType, true);
84                     break;
85                 case AudioManager.ADJUST_UNMUTE:
86                     mStreamMuteStatuses.put(streamType, false);
87                     break;
88                 default:
89                     // Other adjustments not implemented
90             }
91         }
92 
93         @Override
setStreamVolume(int streamType, int index, @AudioManager.PublicVolumeFlags int flags)94         public void setStreamVolume(int streamType, int index,
95                 @AudioManager.PublicVolumeFlags int flags) {
96             mStreamVolumes.put(streamType, index);
97         }
98 
99         @Override
getStreamVolume(int streamType)100         public int getStreamVolume(int streamType) {
101             return mStreamVolumes.getOrDefault(streamType, DEFAULT_VOLUME);
102         }
103 
104         @Override
getStreamMinVolume(int streamType)105         public int getStreamMinVolume(int streamType) {
106             return 0;
107         }
108 
109         @Override
getStreamMaxVolume(int streamType)110         public int getStreamMaxVolume(int streamType) {
111             return mStreamMaxVolumes.getOrDefault(streamType, DEFAULT_MAX_VOLUME);
112         }
113 
114         @Override
isStreamMute(int streamType)115         public boolean isStreamMute(int streamType) {
116             return mStreamMuteStatuses.getOrDefault(streamType, DEFAULT_MUTE_STATUS);
117         }
118 
119         @Override
setStreamMute(int streamType, boolean state)120         public void setStreamMute(int streamType, boolean state) {
121             mStreamMuteStatuses.put(streamType, state);
122         }
123 
124         @Override
setHdmiSystemAudioSupported(boolean on)125         public int setHdmiSystemAudioSupported(boolean on) {
126             return AudioSystem.DEVICE_NONE;
127         }
128 
129         @Override
setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state)130         public void setWiredDeviceConnectionState(AudioDeviceAttributes attributes, int state) {
131             // Do nothing
132         }
133 
134         @Override
setWiredDeviceConnectionState(int device, int state, String address, String name)135         public void setWiredDeviceConnectionState(int device, int state, String address,
136                 String name) {
137             // Do nothing
138         }
139 
140 
141         @Override
142         @AudioManager.DeviceVolumeBehavior
getDeviceVolumeBehavior(@onNull AudioDeviceAttributes device)143         public int getDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device) {
144             return mDeviceVolumeBehaviors.getOrDefault(device, DEFAULT_DEVICE_VOLUME_BEHAVIOR);
145         }
146 
setDeviceVolumeBehavior(@onNull AudioDeviceAttributes device, @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior)147         public void setDeviceVolumeBehavior(@NonNull AudioDeviceAttributes device,
148                 @AudioManager.DeviceVolumeBehavior int deviceVolumeBehavior) {
149             setVolumeBehaviorHelper(device, deviceVolumeBehavior);
150         }
151 
152         @Override
153         @NonNull
getDevicesForAttributes( @onNull AudioAttributes attributes)154         public List<AudioDeviceAttributes> getDevicesForAttributes(
155                 @NonNull AudioAttributes attributes) {
156             return mDevicesForAttributes.getOrDefault(attributes, Collections.emptyList());
157         }
158     }
159 
160     /**
161      * Returns a fake AudioDeviceVolumeManager whose methods affect this object's internal state.
162      */
getAudioDeviceVolumeManager()163     public FakeAudioDeviceVolumeManagerWrapper getAudioDeviceVolumeManager() {
164         return mAudioDeviceVolumeManager;
165     }
166 
167     public class FakeAudioDeviceVolumeManagerWrapper implements AudioDeviceVolumeManagerWrapper {
168         @Override
addOnDeviceVolumeBehaviorChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnDeviceVolumeBehaviorChangedListener listener)169         public void addOnDeviceVolumeBehaviorChangedListener(
170                 @NonNull @CallbackExecutor Executor executor,
171                 @NonNull OnDeviceVolumeBehaviorChangedListener listener)
172                 throws SecurityException {
173             mVolumeBehaviorListeners.add(listener);
174         }
175 
176         @Override
removeOnDeviceVolumeBehaviorChangedListener( @onNull OnDeviceVolumeBehaviorChangedListener listener)177         public void removeOnDeviceVolumeBehaviorChangedListener(
178                 @NonNull OnDeviceVolumeBehaviorChangedListener listener) {
179             mVolumeBehaviorListeners.remove(listener);
180         }
181 
182         @Override
setDeviceAbsoluteVolumeBehavior( @onNull AudioDeviceAttributes device, @NonNull VolumeInfo volume, @NonNull @CallbackExecutor Executor executor, @NonNull OnAudioDeviceVolumeChangedListener vclistener, boolean handlesVolumeAdjustment)183         public void setDeviceAbsoluteVolumeBehavior(
184                 @NonNull AudioDeviceAttributes device,
185                 @NonNull VolumeInfo volume,
186                 @NonNull @CallbackExecutor Executor executor,
187                 @NonNull OnAudioDeviceVolumeChangedListener vclistener,
188                 boolean handlesVolumeAdjustment) {
189             setVolumeBehaviorHelper(device, AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE);
190         }
191 
192         @Override
setDeviceAbsoluteVolumeAdjustOnlyBehavior( @onNull AudioDeviceAttributes device, @NonNull VolumeInfo volume, @NonNull @CallbackExecutor Executor executor, @NonNull OnAudioDeviceVolumeChangedListener vclistener, boolean handlesVolumeAdjustment)193         public void setDeviceAbsoluteVolumeAdjustOnlyBehavior(
194                 @NonNull AudioDeviceAttributes device,
195                 @NonNull VolumeInfo volume,
196                 @NonNull @CallbackExecutor Executor executor,
197                 @NonNull OnAudioDeviceVolumeChangedListener vclistener,
198                 boolean handlesVolumeAdjustment) {
199             setVolumeBehaviorHelper(device,
200                     AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_ADJUST_ONLY);
201         }
202     }
203 
204     /**
205      * Allows tests to manipulate the return value of
206      * {@link FakeAudioManagerWrapper#getDevicesForAttributes}
207      */
setDevicesForAttributes(AudioAttributes attributes, List<AudioDeviceAttributes> devices)208     public void setDevicesForAttributes(AudioAttributes attributes,
209             List<AudioDeviceAttributes> devices) {
210         mDevicesForAttributes.put(attributes, devices);
211     }
212 
213     /**
214      * Allows tests to manipulate the return value of
215      * {@link FakeAudioManagerWrapper#getStreamMaxVolume}
216      */
setStreamMaxVolume(int streamType, int maxVolume)217     public void setStreamMaxVolume(int streamType, int maxVolume) {
218         mStreamMaxVolumes.put(streamType, maxVolume);
219     }
220 
221     /**
222      * Helper method for changing an audio device's volume behavior. Notifies listeners.
223      */
setVolumeBehaviorHelper(AudioDeviceAttributes device, @AudioManager.DeviceVolumeBehavior int newVolumeBehavior)224     private void setVolumeBehaviorHelper(AudioDeviceAttributes device,
225             @AudioManager.DeviceVolumeBehavior int newVolumeBehavior) {
226 
227         int currentVolumeBehavior = mDeviceVolumeBehaviors.getOrDefault(
228                 device, DEFAULT_DEVICE_VOLUME_BEHAVIOR);
229 
230         mDeviceVolumeBehaviors.put(device, newVolumeBehavior);
231 
232         if (newVolumeBehavior != currentVolumeBehavior) {
233             // Notify volume behavior listeners
234             for (OnDeviceVolumeBehaviorChangedListener listener : mVolumeBehaviorListeners) {
235                 listener.onDeviceVolumeBehaviorChanged(device, newVolumeBehavior);
236             }
237         }
238     }
239 }
240