1 /* 2 * Copyright (C) 2022 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.car.audio; 18 19 import static android.car.oem.CarAudioFeaturesInfo.AUDIO_FEATURE_NO_FEATURE; 20 import static android.media.AudioAttributes.USAGE_ALARM; 21 import static android.media.AudioAttributes.USAGE_ANNOUNCEMENT; 22 import static android.media.AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY; 23 import static android.media.AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; 24 import static android.media.AudioAttributes.USAGE_ASSISTANCE_SONIFICATION; 25 import static android.media.AudioAttributes.USAGE_EMERGENCY; 26 import static android.media.AudioAttributes.USAGE_MEDIA; 27 import static android.media.AudioAttributes.USAGE_NOTIFICATION; 28 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; 29 import static android.media.AudioAttributes.USAGE_SAFETY; 30 import static android.media.AudioAttributes.USAGE_VEHICLE_STATUS; 31 import static android.media.AudioAttributes.USAGE_VIRTUAL_SOURCE; 32 import static android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION; 33 import static android.media.AudioManager.AUDIOFOCUS_GAIN; 34 import static android.media.AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 35 import static android.media.AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 36 37 import static com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport.BOILERPLATE_CODE; 38 39 import static org.mockito.ArgumentMatchers.anyInt; 40 import static org.mockito.ArgumentMatchers.eq; 41 import static org.mockito.Mockito.never; 42 import static org.mockito.Mockito.verify; 43 import static org.mockito.Mockito.when; 44 45 import android.car.media.CarAudioManager; 46 import android.car.oem.AudioFocusEntry; 47 import android.car.oem.CarAudioFeaturesInfo; 48 import android.car.oem.OemCarAudioFocusResult; 49 import android.content.ContentResolver; 50 import android.content.pm.PackageManager; 51 import android.media.AudioFocusInfo; 52 import android.media.audiopolicy.AudioPolicy; 53 import android.util.SparseArray; 54 55 import com.android.car.CarLocalServices; 56 import com.android.car.internal.ExcludeFromCodeCoverageGeneratedReport; 57 import com.android.car.oem.CarOemAudioFocusProxyService; 58 import com.android.car.oem.CarOemProxyService; 59 60 import org.mockito.Mock; 61 62 import java.util.List; 63 64 abstract class CarZonesAudioFocusTestBase { 65 protected static final String INVALID_CLIENT_ID = "invalid-client-id"; 66 protected static final String INVALID_CLIENT_ID_2 = "invalid-client2-id"; 67 protected static final String MEDIA_CLIENT_ID = "media-client-id"; 68 protected static final String MEDIA_CLIENT_ID_2 = "media-client2-id"; 69 protected static final String NAVIGATION_CLIENT_ID = "nav-client-id"; 70 protected static final String NAVIGATION_CLIENT_ID_2 = "nav-client2-id"; 71 protected static final String VOICE_COMMAND_CLIENT_ID = "voice-cmd-client-id"; 72 protected static final String VOICE_COMMAND_CLIENT_ID_2 = "voice-cmd-client2-id"; 73 protected static final String CALL_RING_CLIENT_ID = "call-ring-client-id"; 74 protected static final String CALL_RING_CLIENT_ID_2 = "call-ring-client2-id"; 75 protected static final String CALL_CLIENT_ID = "call-client-id"; 76 protected static final String CALL_CLIENT_ID_2 = "call-client2-id"; 77 protected static final String ALARM_CLIENT_ID = "alarm-client-id"; 78 protected static final String ALARM_CLIENT_ID_2 = "alarm-client2-id"; 79 protected static final String NOTIFICATION_CLIENT_ID = "notification-client-id"; 80 protected static final String NOTIFICATION_CLIENT_ID_2 = "notification-client2-id"; 81 protected static final String SYSTEM_SOUND_CLIENT_ID = "sys-sound-client-id"; 82 protected static final String SYSTEM_SOUND_CLIENT_ID_2 = "sys-sound-client2-id"; 83 protected static final String EMERGENCY_CLIENT_ID = "emergency-client-id"; 84 protected static final String EMERGENCY_CLIENT_ID_2 = "emergency-client2-id"; 85 protected static final String SAFETY_CLIENT_ID = "safety-client-id"; 86 protected static final String SAFETY_CLIENT_ID_2 = "safety-client2-id"; 87 protected static final String VEHICLE_STATUS_CLIENT_ID = "vehicle-status-client-id"; 88 protected static final String VEHICLE_STATUS_CLIENT_ID_2 = "vehicle-status-client2-id"; 89 protected static final String ANNOUNCEMENT_CLIENT_ID = "announcement-client-id"; 90 protected static final String ANNOUNCEMENT_CLIENT_ID_2 = "announcement-client2-id"; 91 92 protected static final int PRIMARY_ZONE_ID = CarAudioManager.PRIMARY_AUDIO_ZONE; 93 protected static final int SECONDARY_ZONE_ID = CarAudioManager.PRIMARY_AUDIO_ZONE + 1; 94 protected static final int TEST_USER_ID = 10; 95 protected static final int INVALID_CLIENT_UID_1 = 1000005; 96 protected static final int INVALID_CLIENT_UID_2 = 1000007; 97 protected static final int MEDIA_CLIENT_UID_1 = 1086753; 98 protected static final int MEDIA_CLIENT_UID_2 = 1000009; 99 protected static final int NAVIGATION_CLIENT_UID_1 = 1010101; 100 protected static final int NAVIGATION_CLIENT_UID_2 = 1000207; 101 protected static final int VOICE_COMMAND_CLIENT_UID_1 = 1000305; 102 protected static final int VOICE_COMMAND_CLIENT_UID_2 = 1000307; 103 protected static final int CALL_RING_CLIENT_UID_1 = 1000405; 104 protected static final int CALL_RING_CLIENT_UID_2 = 1000407; 105 protected static final int CALL_CLIENT_UID_1 = 1086753; 106 protected static final int CALL_CLIENT_UID_2 = 1000507; 107 protected static final int ALARM_CLIENT_UID_1 = 1000605; 108 protected static final int ALARM_CLIENT_UID_2 = 1000607; 109 protected static final int NOTIFICATION_CLIENT_UID_1 = 1000705; 110 protected static final int NOTIFICATION_CLIENT_UID_2 = 1000707; 111 protected static final int SYSTEM_SOUND_CLIENT_UID_1 = 1000805; 112 protected static final int SYSTEM_SOUND_CLIENT_UID_2 = 1000807; 113 protected static final int EMERGENCY_CLIENT_UID_1 = 1000905; 114 protected static final int EMERGENCY_CLIENT_UID_2 = 1000907; 115 protected static final int SAFETY_CLIENT_UID_1 = 1001005; 116 protected static final int SAFETY_CLIENT_UID_2 = 1001007; 117 protected static final int VEHICLE_STATUS_CLIENT_UID_1 = 1001105; 118 protected static final int VEHICLE_STATUS_CLIENT_UID_2 = 1001107; 119 protected static final int ANNOUNCEMENT_CLIENT_UID_1 = 1001205; 120 protected static final int ANNOUNCEMENT_CLIENT_UID_2 = 1001207; 121 122 protected static final AudioClientInfo INVALID_SOUND_INFO_1 = new AudioClientInfo( 123 USAGE_VIRTUAL_SOURCE, INVALID_CLIENT_UID_1, INVALID_CLIENT_ID); 124 protected static final AudioClientInfo INVALID_SOUND_INFO_2 = new AudioClientInfo( 125 USAGE_VIRTUAL_SOURCE, INVALID_CLIENT_UID_2, INVALID_CLIENT_ID_2); 126 protected static final AudioClientInfo MEDIA_INFO_1 = new AudioClientInfo( 127 USAGE_MEDIA, MEDIA_CLIENT_UID_1, MEDIA_CLIENT_ID); 128 protected static final AudioClientInfo MEDIA_INFO_2 = new AudioClientInfo( 129 USAGE_MEDIA, MEDIA_CLIENT_UID_2, MEDIA_CLIENT_ID_2); 130 protected static final AudioClientInfo NAVIGATION_INFO_1 = new AudioClientInfo( 131 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, NAVIGATION_CLIENT_UID_1, NAVIGATION_CLIENT_ID); 132 protected static final AudioClientInfo NAVIGATION_INFO_2 = new AudioClientInfo( 133 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, NAVIGATION_CLIENT_UID_2, NAVIGATION_CLIENT_ID_2); 134 protected static final AudioClientInfo VOICE_COMMAND_INFO_1 = new AudioClientInfo( 135 USAGE_ASSISTANCE_ACCESSIBILITY, VOICE_COMMAND_CLIENT_UID_1, VOICE_COMMAND_CLIENT_ID); 136 protected static final AudioClientInfo VOICE_COMMAND_INFO_2 = new AudioClientInfo( 137 USAGE_ASSISTANCE_ACCESSIBILITY, VOICE_COMMAND_CLIENT_UID_2, VOICE_COMMAND_CLIENT_ID_2); 138 protected static final AudioClientInfo CALL_RING_INFO_1 = new AudioClientInfo( 139 USAGE_NOTIFICATION_RINGTONE, CALL_RING_CLIENT_UID_1, CALL_RING_CLIENT_ID); 140 protected static final AudioClientInfo CALL_RING_INFO_2 = new AudioClientInfo( 141 USAGE_NOTIFICATION_RINGTONE, CALL_RING_CLIENT_UID_2, CALL_RING_CLIENT_ID_2); 142 protected static final AudioClientInfo CALL_INFO_1 = new AudioClientInfo( 143 USAGE_VOICE_COMMUNICATION, CALL_CLIENT_UID_1, CALL_CLIENT_ID); 144 protected static final AudioClientInfo CALL_INFO_2 = new AudioClientInfo( 145 USAGE_VOICE_COMMUNICATION, CALL_CLIENT_UID_2, CALL_CLIENT_ID_2); 146 protected static final AudioClientInfo ALARM_INFO_1 = new AudioClientInfo( 147 USAGE_ALARM, ALARM_CLIENT_UID_1, ALARM_CLIENT_ID); 148 protected static final AudioClientInfo ALARM_INFO_2 = new AudioClientInfo( 149 USAGE_ALARM, ALARM_CLIENT_UID_2, ALARM_CLIENT_ID_2); 150 protected static final AudioClientInfo NOTIFICATION_INFO_1 = new AudioClientInfo( 151 USAGE_NOTIFICATION, NOTIFICATION_CLIENT_UID_1, NOTIFICATION_CLIENT_ID); 152 protected static final AudioClientInfo NOTIFICATION_INFO_2 = new AudioClientInfo( 153 USAGE_NOTIFICATION, NOTIFICATION_CLIENT_UID_2, NOTIFICATION_CLIENT_ID_2); 154 protected static final AudioClientInfo SYSTEM_SOUND_INFO_1 = new AudioClientInfo( 155 USAGE_ASSISTANCE_SONIFICATION, SYSTEM_SOUND_CLIENT_UID_1, SYSTEM_SOUND_CLIENT_ID); 156 protected static final AudioClientInfo SYSTEM_SOUND_INFO_2 = new AudioClientInfo( 157 USAGE_ASSISTANCE_SONIFICATION, SYSTEM_SOUND_CLIENT_UID_2, SYSTEM_SOUND_CLIENT_ID_2); 158 protected static final AudioClientInfo EMERGENCY_INFO_1 = new AudioClientInfo( 159 USAGE_EMERGENCY, EMERGENCY_CLIENT_UID_1, EMERGENCY_CLIENT_ID); 160 protected static final AudioClientInfo EMERGENCY_INFO_2 = new AudioClientInfo( 161 USAGE_EMERGENCY, EMERGENCY_CLIENT_UID_2, EMERGENCY_CLIENT_ID_2); 162 protected static final AudioClientInfo SAFETY_INFO_1 = new AudioClientInfo( 163 USAGE_SAFETY, SAFETY_CLIENT_UID_1, SAFETY_CLIENT_ID); 164 protected static final AudioClientInfo SAFETY_INFO_2 = new AudioClientInfo( 165 USAGE_SAFETY, SAFETY_CLIENT_UID_2, SAFETY_CLIENT_ID_2); 166 protected static final AudioClientInfo VEHICLE_STATUS_INFO_1 = new AudioClientInfo( 167 USAGE_VEHICLE_STATUS, VEHICLE_STATUS_CLIENT_UID_1, VEHICLE_STATUS_CLIENT_ID); 168 protected static final AudioClientInfo VEHICLE_STATUS_INFO_2 = new AudioClientInfo( 169 USAGE_VEHICLE_STATUS, VEHICLE_STATUS_CLIENT_UID_2, VEHICLE_STATUS_CLIENT_ID_2); 170 protected static final AudioClientInfo ANNOUNCEMENT_INFO_1 = new AudioClientInfo( 171 USAGE_ANNOUNCEMENT, ANNOUNCEMENT_CLIENT_UID_1, ANNOUNCEMENT_CLIENT_ID); 172 protected static final AudioClientInfo ANNOUNCEMENT_INFO_2 = new AudioClientInfo( 173 USAGE_ANNOUNCEMENT, ANNOUNCEMENT_CLIENT_UID_2, ANNOUNCEMENT_CLIENT_ID_2); 174 175 @Mock 176 protected AudioManagerWrapper mMockAudioManager; 177 @Mock 178 protected AudioPolicy mAudioPolicy; 179 @Mock 180 protected CarAudioService mCarAudioService; 181 @Mock 182 protected CarZonesAudioFocus.CarFocusCallback mMockCarFocusCallback; 183 @Mock 184 protected CarOemProxyService mMockCarOemProxyService; 185 @Mock 186 protected CarOemAudioFocusProxyService mMockCarOemAudioFocusProxyService; 187 @Mock 188 private ContentResolver mContentResolver; 189 @Mock 190 private CarAudioSettings mCarAudioSettings; 191 @Mock 192 private PackageManager mMockPackageManager; 193 @Mock 194 private CarVolumeInfoWrapper mMockCarVolumeInfoWrapper; 195 196 protected SparseArray<CarAudioZone> mCarAudioZones; 197 setUp()198 public void setUp() { 199 mCarAudioZones = generateAudioZones(); 200 CarLocalServices.removeServiceForTest(CarOemProxyService.class); 201 CarLocalServices.addService(CarOemProxyService.class, mMockCarOemProxyService); 202 when(mMockCarOemProxyService.isOemServiceReady()).thenReturn(false); 203 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(false); 204 } 205 tearDown()206 public void tearDown() { 207 CarLocalServices.removeServiceForTest(CarOemProxyService.class); 208 } 209 generateCallRequestForPrimaryZone()210 protected AudioFocusInfo generateCallRequestForPrimaryZone() { 211 return new AudioFocusInfoBuilder().setUsage(USAGE_VOICE_COMMUNICATION) 212 .setGainRequest(AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK) 213 .setClientId(CALL_CLIENT_ID) 214 .setClientUid(CALL_CLIENT_UID_1).createAudioFocusInfo(); 215 } 216 generateMediaRequestForPrimaryZone(boolean isDelayedFocusEnabled)217 protected AudioFocusInfo generateMediaRequestForPrimaryZone(boolean isDelayedFocusEnabled) { 218 return new AudioFocusInfoBuilder().setUsage(USAGE_MEDIA) 219 .setGainRequest(AUDIOFOCUS_GAIN) 220 .setClientId(MEDIA_CLIENT_ID) 221 .setDelayedFocusRequestEnable(isDelayedFocusEnabled) 222 .setClientUid(MEDIA_CLIENT_UID_1).createAudioFocusInfo(); 223 } 224 requestFocusAndAssertIfRequestNotGranted(CarZonesAudioFocus carZonesAudioFocus, AudioFocusInfo audioFocusClient)225 protected void requestFocusAndAssertIfRequestNotGranted(CarZonesAudioFocus carZonesAudioFocus, 226 AudioFocusInfo audioFocusClient) { 227 requestFocusAndAssertIfRequestDiffers(carZonesAudioFocus, audioFocusClient, 228 AUDIOFOCUS_REQUEST_GRANTED); 229 } 230 requestFocusAndAssertIfRequestDiffers(CarZonesAudioFocus carZonesAudioFocus, AudioFocusInfo audioFocusClient, int expectedAudioFocusResults)231 private void requestFocusAndAssertIfRequestDiffers(CarZonesAudioFocus carZonesAudioFocus, 232 AudioFocusInfo audioFocusClient, int expectedAudioFocusResults) { 233 carZonesAudioFocus.onAudioFocusRequest(audioFocusClient, expectedAudioFocusResults); 234 verify(mMockAudioManager) 235 .setFocusRequestResult(audioFocusClient, expectedAudioFocusResults, mAudioPolicy); 236 } 237 abandonFocusAndAssertIfAbandonNotGranted(CarZonesAudioFocus carZonesAudioFocus, AudioFocusInfo audioFocusClient)238 protected void abandonFocusAndAssertIfAbandonNotGranted(CarZonesAudioFocus carZonesAudioFocus, 239 AudioFocusInfo audioFocusClient) { 240 carZonesAudioFocus.onAudioFocusAbandon(audioFocusClient); 241 verify(mMockAudioManager, never()).dispatchAudioFocusChange(eq(audioFocusClient), 242 anyInt(), eq(mAudioPolicy)); 243 } 244 generateAudioZones()245 protected SparseArray<CarAudioZone> generateAudioZones() { 246 int testZoneConfigId = 0; 247 SparseArray<CarAudioZone> zones = new SparseArray<>(2); 248 CarAudioContext testCarAudioContext = 249 new CarAudioContext(CarAudioContext.getAllContextsInfo(), 250 /* useCoreAudioRouting= */ false); 251 CarAudioZone primaryZone = new CarAudioZone(testCarAudioContext, "Primary zone", 252 PRIMARY_ZONE_ID); 253 CarAudioZone secondaryZone = new CarAudioZone(testCarAudioContext, "Secondary zone", 254 SECONDARY_ZONE_ID); 255 CarAudioZoneConfig primaryZoneConfig = 256 new CarAudioZoneConfig.Builder("Primary zone config", PRIMARY_ZONE_ID, 257 testZoneConfigId, /* isDefault= */ true).build(); 258 CarAudioZoneConfig secondaryZoneConfig = 259 new CarAudioZoneConfig.Builder("Secondary zone config", SECONDARY_ZONE_ID, 260 testZoneConfigId, /* isDefault= */ true).build(); 261 primaryZone.addZoneConfig(primaryZoneConfig); 262 secondaryZone.addZoneConfig(secondaryZoneConfig); 263 zones.put(PRIMARY_ZONE_ID, primaryZone); 264 zones.put(SECONDARY_ZONE_ID, secondaryZone); 265 return zones; 266 } 267 getCarZonesAudioFocus(CarZonesAudioFocus.CarFocusCallback carFocusCallback)268 protected CarZonesAudioFocus getCarZonesAudioFocus(CarZonesAudioFocus.CarFocusCallback 269 carFocusCallback) { 270 CarZonesAudioFocus carZonesAudioFocus = 271 CarZonesAudioFocus.createCarZonesAudioFocus(mMockAudioManager, 272 mMockPackageManager, mCarAudioZones, mCarAudioSettings, carFocusCallback, 273 mMockCarVolumeInfoWrapper, new CarAudioFeaturesInfo.Builder( 274 AUDIO_FEATURE_NO_FEATURE).build()); 275 carZonesAudioFocus.setOwningPolicy(mCarAudioService, mAudioPolicy); 276 277 return carZonesAudioFocus; 278 } 279 getCarZonesAudioFocus()280 protected CarZonesAudioFocus getCarZonesAudioFocus() { 281 return getCarZonesAudioFocus(mMockCarFocusCallback); 282 } 283 setUpRejectNavigationOnCallValue(boolean rejectNavigationOnCall)284 protected void setUpRejectNavigationOnCallValue(boolean rejectNavigationOnCall) { 285 when(mCarAudioSettings.getContentResolverForUser(TEST_USER_ID)) 286 .thenReturn(mContentResolver); 287 when(mCarAudioSettings.isRejectNavigationOnCallEnabledInSettings(TEST_USER_ID)) 288 .thenReturn(rejectNavigationOnCall); 289 } 290 getAudioFocusResults(AudioFocusEntry entry, List<AudioFocusEntry> lostEntries, List<AudioFocusEntry> blockedEntries, int results)291 protected OemCarAudioFocusResult getAudioFocusResults(AudioFocusEntry entry, 292 List<AudioFocusEntry> lostEntries, List<AudioFocusEntry> blockedEntries, int results) { 293 return new OemCarAudioFocusResult.Builder(lostEntries, blockedEntries, results) 294 .setAudioFocusEntry(entry).build(); 295 } 296 297 @ExcludeFromCodeCoverageGeneratedReport(reason = BOILERPLATE_CODE) 298 public static final class AudioClientInfo { 299 private final int mUsage; 300 private final int mClientUid; 301 private final String mClientId; 302 AudioClientInfo(int usage, int clientUid, String clientId)303 AudioClientInfo(int usage, int clientUid, String clientId) { 304 mUsage = usage; 305 mClientUid = clientUid; 306 mClientId = clientId; 307 } 308 getUsage()309 public int getUsage() { 310 return mUsage; 311 } 312 getClientUid()313 public int getClientUid() { 314 return mClientUid; 315 } 316 getClientId()317 public String getClientId() { 318 return mClientId; 319 } 320 } 321 } 322