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.Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS; 20 import static android.car.Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME; 21 import static android.car.PlatformVersion.VERSION_CODES.UPSIDE_DOWN_CAKE_0; 22 import static android.car.media.CarAudioManager.AUDIO_FEATURE_AUDIO_MIRRORING; 23 import static android.car.media.CarAudioManager.AUDIO_FEATURE_DYNAMIC_ROUTING; 24 import static android.car.media.CarAudioManager.AUDIO_FEATURE_MIN_MAX_ACTIVATION_VOLUME; 25 import static android.car.media.CarAudioManager.AUDIO_FEATURE_OEM_AUDIO_SERVICE; 26 import static android.car.media.CarAudioManager.AUDIO_FEATURE_PERSIST_FADE_BALANCE_VALUES; 27 import static android.car.media.CarAudioManager.AUDIO_FEATURE_VOLUME_GROUP_EVENTS; 28 import static android.car.media.CarAudioManager.AUDIO_FEATURE_VOLUME_GROUP_MUTING; 29 import static android.car.media.CarAudioManager.AUDIO_MIRROR_CAN_ENABLE; 30 import static android.car.media.CarAudioManager.AUDIO_MIRROR_OUT_OF_OUTPUT_DEVICES; 31 import static android.car.media.CarAudioManager.CONFIG_STATUS_AUTO_SWITCHED; 32 import static android.car.media.CarAudioManager.CONFIG_STATUS_CHANGED; 33 import static android.car.media.CarAudioManager.INVALID_AUDIO_ZONE; 34 import static android.car.media.CarAudioManager.INVALID_REQUEST_ID; 35 import static android.car.media.CarAudioManager.INVALID_VOLUME_GROUP_ID; 36 import static android.car.media.CarAudioManager.PRIMARY_AUDIO_ZONE; 37 import static android.car.test.mocks.AndroidMockitoHelper.mockCarGetPlatformVersion; 38 import static android.car.test.mocks.AndroidMockitoHelper.mockContextCheckCallingOrSelfPermission; 39 import static android.content.pm.PackageManager.PERMISSION_DENIED; 40 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 41 import static android.media.AudioAttributes.USAGE_ALARM; 42 import static android.media.AudioAttributes.USAGE_ANNOUNCEMENT; 43 import static android.media.AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY; 44 import static android.media.AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; 45 import static android.media.AudioAttributes.USAGE_ASSISTANCE_SONIFICATION; 46 import static android.media.AudioAttributes.USAGE_ASSISTANT; 47 import static android.media.AudioAttributes.USAGE_CALL_ASSISTANT; 48 import static android.media.AudioAttributes.USAGE_EMERGENCY; 49 import static android.media.AudioAttributes.USAGE_GAME; 50 import static android.media.AudioAttributes.USAGE_MEDIA; 51 import static android.media.AudioAttributes.USAGE_NOTIFICATION; 52 import static android.media.AudioAttributes.USAGE_NOTIFICATION_EVENT; 53 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; 54 import static android.media.AudioAttributes.USAGE_SAFETY; 55 import static android.media.AudioAttributes.USAGE_UNKNOWN; 56 import static android.media.AudioAttributes.USAGE_VEHICLE_STATUS; 57 import static android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION; 58 import static android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING; 59 import static android.media.AudioDeviceInfo.TYPE_BUILTIN_MIC; 60 import static android.media.AudioDeviceInfo.TYPE_FM_TUNER; 61 import static android.media.AudioManager.AUDIOFOCUS_GAIN; 62 import static android.media.AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 63 import static android.media.AudioManager.AUDIOFOCUS_LOSS; 64 import static android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT; 65 import static android.media.AudioManager.AUDIOFOCUS_NONE; 66 import static android.media.AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 67 import static android.media.AudioManager.ERROR; 68 import static android.media.AudioManager.EXTRA_VOLUME_STREAM_TYPE; 69 import static android.media.AudioManager.FLAG_FROM_KEY; 70 import static android.media.AudioManager.FLAG_PLAY_SOUND; 71 import static android.media.AudioManager.FLAG_SHOW_UI; 72 import static android.media.AudioManager.MASTER_MUTE_CHANGED_ACTION; 73 import static android.media.AudioManager.STREAM_MUSIC; 74 import static android.media.AudioManager.SUCCESS; 75 import static android.media.AudioManager.VOLUME_CHANGED_ACTION; 76 import static android.media.audio.common.AudioDeviceDescription.CONNECTION_BUS; 77 import static android.media.audio.common.AudioDeviceType.OUT_DEVICE; 78 import static android.media.audio.common.AudioGainMode.JOINT; 79 import static android.media.audiopolicy.Flags.FLAG_ENABLE_FADE_MANAGER_CONFIGURATION; 80 import static android.os.Build.VERSION.SDK_INT; 81 import static android.view.KeyEvent.ACTION_DOWN; 82 import static android.view.KeyEvent.ACTION_UP; 83 import static android.view.KeyEvent.KEYCODE_UNKNOWN; 84 import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN; 85 import static android.view.KeyEvent.KEYCODE_VOLUME_MUTE; 86 import static android.view.KeyEvent.KEYCODE_VOLUME_UP; 87 88 import static com.android.car.R.bool.audioEnableVolumeKeyEventsToDynamicDevices; 89 import static com.android.car.R.bool.audioPersistFadeBalanceLevels; 90 import static com.android.car.R.bool.audioPersistMasterMuteState; 91 import static com.android.car.R.bool.audioUseCarVolumeGroupEvent; 92 import static com.android.car.R.bool.audioUseCarVolumeGroupMuting; 93 import static com.android.car.R.bool.audioUseCoreRouting; 94 import static com.android.car.R.bool.audioUseCoreVolume; 95 import static com.android.car.R.bool.audioUseDynamicRouting; 96 import static com.android.car.R.bool.audioUseFadeManagerConfiguration; 97 import static com.android.car.R.bool.audioUseHalDuckingSignals; 98 import static com.android.car.R.bool.audioUseMinMaxActivationVolume; 99 import static com.android.car.R.integer.audioVolumeAdjustmentContextsVersion; 100 import static com.android.car.R.integer.audioVolumeKeyEventTimeoutMs; 101 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.CALL_TEST_DEVICE; 102 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.MEDIA_TEST_DEVICE; 103 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.MIRROR_TEST_DEVICE; 104 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.NAVIGATION_TEST_DEVICE; 105 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.SECONDARY_TEST_DEVICE_CONFIG_0; 106 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.SECONDARY_TEST_DEVICE_CONFIG_1_0; 107 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.TERTIARY_TEST_DEVICE_1; 108 import static com.android.car.audio.CarAudioDeviceInfoTestUtils.VOICE_TEST_DEVICE; 109 import static com.android.car.audio.CarAudioService.CAR_DEFAULT_AUDIO_ATTRIBUTE; 110 import static com.android.car.audio.CarAudioTestUtils.PRIMARY_OCCUPANT_ID; 111 import static com.android.car.audio.CarAudioTestUtils.QUATERNARY_OCCUPANT_ID; 112 import static com.android.car.audio.CarAudioTestUtils.QUATERNARY_ZONE_ID; 113 import static com.android.car.audio.CarAudioTestUtils.SECONDARY_OCCUPANT_ID; 114 import static com.android.car.audio.CarAudioTestUtils.SECONDARY_ZONE_CONFIG_NAME_1; 115 import static com.android.car.audio.CarAudioTestUtils.SECONDARY_ZONE_CONFIG_NAME_2; 116 import static com.android.car.audio.CarAudioTestUtils.SECONDARY_ZONE_ID; 117 import static com.android.car.audio.CarAudioTestUtils.SECONDARY_ZONE_VOLUME_GROUP_COUNT; 118 import static com.android.car.audio.CarAudioTestUtils.SECONDARY_ZONE_VOLUME_GROUP_ID; 119 import static com.android.car.audio.CarAudioTestUtils.TERTIARY_OCCUPANT_ID; 120 import static com.android.car.audio.CarAudioTestUtils.TERTIARY_ZONE_ID; 121 import static com.android.car.audio.CarAudioTestUtils.TEST_SECONDARY_ZONE_GROUP_0; 122 import static com.android.car.audio.CarAudioTestUtils.TEST_SECONDARY_ZONE_GROUP_1; 123 import static com.android.car.audio.CarAudioTestUtils.createAudioServiceAudioZones; 124 import static com.android.car.audio.CarHalAudioUtils.usageToMetadata; 125 import static com.android.car.audio.GainBuilder.DEFAULT_GAIN; 126 import static com.android.car.audio.GainBuilder.MAX_GAIN; 127 import static com.android.car.audio.GainBuilder.MIN_GAIN; 128 import static com.android.car.audio.GainBuilder.STEP_SIZE; 129 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 130 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 131 132 import static com.google.common.truth.Truth.assertWithMessage; 133 134 import static org.junit.Assert.assertThrows; 135 import static org.mockito.ArgumentMatchers.any; 136 import static org.mockito.ArgumentMatchers.anyBoolean; 137 import static org.mockito.ArgumentMatchers.anyInt; 138 import static org.mockito.ArgumentMatchers.anyString; 139 import static org.mockito.ArgumentMatchers.eq; 140 import static org.mockito.Mockito.atLeastOnce; 141 import static org.mockito.Mockito.mock; 142 import static org.mockito.Mockito.never; 143 import static org.mockito.Mockito.reset; 144 import static org.mockito.Mockito.timeout; 145 import static org.mockito.Mockito.times; 146 import static org.mockito.Mockito.when; 147 148 import android.annotation.NonNull; 149 import android.car.Car; 150 import android.car.CarOccupantZoneManager; 151 import android.car.ICarOccupantZoneCallback; 152 import android.car.VehicleAreaSeat; 153 import android.car.builtin.media.AudioManagerHelper; 154 import android.car.builtin.media.AudioManagerHelper.AudioPatchInfo; 155 import android.car.builtin.os.UserManagerHelper; 156 import android.car.feature.Flags; 157 import android.car.media.CarAudioManager; 158 import android.car.media.CarAudioPatchHandle; 159 import android.car.media.CarAudioZoneConfigInfo; 160 import android.car.media.CarVolumeGroupEvent; 161 import android.car.media.CarVolumeGroupInfo; 162 import android.car.media.IAudioZoneConfigurationsChangeCallback; 163 import android.car.media.IAudioZonesMirrorStatusCallback; 164 import android.car.media.IMediaAudioRequestStatusCallback; 165 import android.car.media.IPrimaryZoneMediaAudioRequestCallback; 166 import android.car.media.ISwitchAudioZoneConfigCallback; 167 import android.car.settings.CarSettings; 168 import android.car.test.mocks.AbstractExtendedMockitoTestCase; 169 import android.car.test.mocks.MockSettings; 170 import android.car.test.util.TemporaryFile; 171 import android.content.AttributionSource; 172 import android.content.BroadcastReceiver; 173 import android.content.ContentResolver; 174 import android.content.Context; 175 import android.content.Intent; 176 import android.content.pm.PackageManager; 177 import android.content.res.Resources; 178 import android.hardware.automotive.audiocontrol.AudioDeviceConfiguration; 179 import android.hardware.automotive.audiocontrol.AudioGainConfigInfo; 180 import android.hardware.automotive.audiocontrol.IAudioControl; 181 import android.hardware.automotive.audiocontrol.Reasons; 182 import android.hardware.automotive.audiocontrol.RoutingDeviceConfiguration; 183 import android.media.AudioAttributes; 184 import android.media.AudioDeviceAttributes; 185 import android.media.AudioDeviceCallback; 186 import android.media.AudioDeviceInfo; 187 import android.media.AudioFocusInfo; 188 import android.media.AudioManager; 189 import android.media.AudioManager.AudioPlaybackCallback; 190 import android.media.AudioManager.AudioServerStateCallback; 191 import android.media.AudioPlaybackConfiguration; 192 import android.media.IAudioService; 193 import android.media.audio.common.AudioDevice; 194 import android.media.audio.common.AudioDeviceAddress; 195 import android.media.audio.common.AudioDeviceDescription; 196 import android.media.audio.common.AudioPort; 197 import android.media.audio.common.AudioPortDeviceExt; 198 import android.media.audio.common.AudioPortExt; 199 import android.media.audiopolicy.AudioPolicy; 200 import android.net.Uri; 201 import android.os.Binder; 202 import android.os.Build; 203 import android.os.Handler; 204 import android.os.HandlerThread; 205 import android.os.IBinder; 206 import android.os.RemoteException; 207 import android.os.ServiceManager; 208 import android.os.SystemProperties; 209 import android.os.UserHandle; 210 import android.platform.test.annotations.DisableFlags; 211 import android.platform.test.annotations.EnableFlags; 212 import android.platform.test.flag.junit.SetFlagsRule; 213 import android.provider.Settings; 214 import android.telephony.SubscriptionManager; 215 import android.telephony.TelephonyCallback; 216 import android.telephony.TelephonyManager; 217 import android.util.Log; 218 import android.util.NoSuchPropertyException; 219 import android.util.SparseArray; 220 import android.util.SparseIntArray; 221 import android.view.KeyEvent; 222 223 import androidx.test.core.app.ApplicationProvider; 224 225 import com.android.car.CarInputService; 226 import com.android.car.CarInputService.KeyEventListener; 227 import com.android.car.CarLocalServices; 228 import com.android.car.CarOccupantZoneService; 229 import com.android.car.CarServiceUtils; 230 import com.android.car.R; 231 import com.android.car.audio.hal.AudioControlFactory; 232 import com.android.car.audio.hal.AudioControlWrapper; 233 import com.android.car.audio.hal.AudioControlWrapper.AudioControlDeathRecipient; 234 import com.android.car.audio.hal.AudioControlWrapperAidl; 235 import com.android.car.audio.hal.HalAudioDeviceInfo; 236 import com.android.car.audio.hal.HalAudioGainCallback; 237 import com.android.car.audio.hal.HalAudioModuleChangeCallback; 238 import com.android.car.audio.hal.HalFocusListener; 239 import com.android.car.oem.CarOemAudioDuckingProxyService; 240 import com.android.car.oem.CarOemAudioFocusProxyService; 241 import com.android.car.oem.CarOemAudioVolumeProxyService; 242 import com.android.car.oem.CarOemProxyService; 243 import com.android.car.power.CarPowerManagementService; 244 245 import org.junit.After; 246 import org.junit.Before; 247 import org.junit.Rule; 248 import org.junit.Test; 249 import org.mockito.ArgumentCaptor; 250 import org.mockito.Captor; 251 import org.mockito.Mock; 252 253 import java.io.InputStream; 254 import java.util.ArrayList; 255 import java.util.Arrays; 256 import java.util.Collections; 257 import java.util.List; 258 import java.util.concurrent.CountDownLatch; 259 import java.util.concurrent.TimeUnit; 260 261 public final class CarAudioServiceUnitTest extends AbstractExtendedMockitoTestCase { 262 private static final String TAG = CarAudioServiceUnitTest.class.getSimpleName(); 263 private static final long TEST_CALLBACK_TIMEOUT_MS = 100; 264 private static final long TEST_ZONE_CONFIG_CALLBACK_TIMEOUT_MS = 500; 265 private static final int VOLUME_KEY_EVENT_TIMEOUT_MS = 3000; 266 private static final int INIT_TIMEOUT_MS = 10_000; 267 private static final int AUDIO_CONTEXT_PRIORITY_LIST_VERSION_ONE = 1; 268 private static final int AUDIO_CONTEXT_PRIORITY_LIST_VERSION_TWO = 2; 269 private static final String PRIMARY_ZONE_MICROPHONE_ADDRESS = "Built-In Mic"; 270 private static final String PRIMARY_ZONE_FM_TUNER_ADDRESS = "FM Tuner"; 271 public static final String SECONDARY_ZONE_BT_CONFIG_NAME = "secondary BT zone config 0"; 272 private static final String DEFAULT_CONFIG_NAME_DYNAMIC_DEVICES = "primary zone config 0"; 273 private static final String PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES = "primary zone BT media"; 274 private static final String TERTIARY_CONFIG_NAME_DYNAMIC_DEVICES = 275 "primary zone headphones media"; 276 private static final String MIRROR_OFF_SIGNAL = "mirroring=off"; 277 // From the car audio configuration file in /res/raw/car_audio_configuration.xml 278 private static final int TEST_REAR_LEFT_ZONE_ID = 1; 279 private static final int TEST_REAR_RIGHT_ZONE_ID = 2; 280 private static final int TEST_FRONT_ZONE_ID = 3; 281 private static final int TEST_REAR_ROW_3_ZONE_ID = 4; 282 public static final int[] TEST_MIRROR_AUDIO_ZONES = new int[]{TEST_REAR_LEFT_ZONE_ID, 283 TEST_REAR_RIGHT_ZONE_ID}; 284 private static final int OUT_OF_RANGE_ZONE = TEST_REAR_ROW_3_ZONE_ID + 1; 285 private static final int PRIMARY_ZONE_VOLUME_GROUP_COUNT = 4; 286 private static final int TEST_PRIMARY_ZONE_GROUP_0 = 0; 287 private static final int TEST_PRIMARY_ZONE_GROUP_1 = 1; 288 private static final int TEST_PRIMARY_ZONE_GROUP_2 = 2; 289 private static final int TEST_FLAGS = 0; 290 private static final float TEST_VALUE = -.75f; 291 private static final float INVALID_TEST_VALUE = -1.5f; 292 private static final int TEST_DISPLAY_TYPE = 2; 293 private static final int TEST_SEAT = 2; 294 private static final int PRIMARY_OCCUPANT_ZONE = 0; 295 private static final int INVALID_STATUS = 0; 296 297 private static final int TEST_DRIVER_OCCUPANT_ZONE_ID = 1; 298 private static final int TEST_REAR_LEFT_OCCUPANT_ZONE_ID = 2; 299 private static final int TEST_REAR_RIGHT_OCCUPANT_ZONE_ID = 3; 300 private static final int TEST_FRONT_OCCUPANT_ZONE_ID = 4; 301 private static final int TEST_REAR_ROW_3_OCCUPANT_ZONE_ID = 5; 302 private static final int TEST_UNASSIGNED_OCCUPANT_ZONE_ID = 6; 303 304 private static final int TEST_MEDIA_PORT_ID = 0; 305 private static final int TEST_NAV_PORT_ID = 1; 306 private static final String TEST_MEDIA_PORT_NAME = "Media bus"; 307 private static final String TEST_NAV_PORT_NAME = "Nav bus"; 308 private static final int TEST_GAIN_MIN_VALUE = -3000; 309 private static final int TEST_GAIN_MAX_VALUE = -1000; 310 private static final int TEST_GAIN_DEFAULT_VALUE = -2000; 311 private static final int TEST_GAIN_STEP_VALUE = 2; 312 313 private static final String TEST_LEGACY_VOLUME_GROUP_NAME = "legacy_zone0"; 314 private static final int TEST_STREAM_MIN_VOLUME = 0; 315 private static final int TEST_STREAM_MAX_VOLUME = 25; 316 private static final int TEST_STREAM_VOLUME = 10; 317 318 private static final int TEST_PLAYBACK_UID = 10101; 319 320 private static final CarOccupantZoneManager.OccupantZoneInfo TEST_DRIVER_OCCUPANT = 321 getOccupantInfo(TEST_DRIVER_OCCUPANT_ZONE_ID, 322 CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER, 323 VehicleAreaSeat.SEAT_ROW_1_LEFT); 324 private static final CarOccupantZoneManager.OccupantZoneInfo 325 TEST_REAR_RIGHT_PASSENGER_OCCUPANT = 326 getOccupantInfo(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID, 327 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 328 VehicleAreaSeat.SEAT_ROW_2_RIGHT); 329 private static final CarOccupantZoneManager.OccupantZoneInfo 330 TEST_FRONT_PASSENGER_OCCUPANT = 331 getOccupantInfo(TEST_FRONT_OCCUPANT_ZONE_ID, 332 CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER, 333 VehicleAreaSeat.SEAT_ROW_1_RIGHT); 334 private static final CarOccupantZoneManager.OccupantZoneInfo 335 TEST_REAR_LEFT_PASSENGER_OCCUPANT = 336 getOccupantInfo(TEST_REAR_LEFT_OCCUPANT_ZONE_ID, 337 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 338 VehicleAreaSeat.SEAT_ROW_2_LEFT); 339 340 private static final CarOccupantZoneManager.OccupantZoneInfo 341 TEST_REAR_ROW_3_PASSENGER_OCCUPANT = 342 getOccupantInfo(TEST_REAR_ROW_3_OCCUPANT_ZONE_ID, 343 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 344 VehicleAreaSeat.SEAT_ROW_3_LEFT); 345 346 private static final String PROPERTY_RO_ENABLE_AUDIO_PATCH = 347 "ro.android.car.audio.enableaudiopatch"; 348 349 private static final int MEDIA_APP_UID = 1086753; 350 private static final int TEST_REAR_RIGHT_UID = 1286753; 351 private static final String MEDIA_CLIENT_ID = "media-client-id"; 352 private static final String MEDIA_PACKAGE_NAME = "com.android.car.audio"; 353 private static final int MEDIA_EMPTY_FLAG = 0; 354 private static final String REGISTRATION_ID = "meh"; 355 private static final int MEDIA_VOLUME_GROUP_ID = 0; 356 private static final int NAVIGATION_VOLUME_GROUP_ID = 1; 357 private static final int INVALID_USAGE = -1; 358 private static final int INVALID_AUDIO_FEATURE = -1; 359 private static final int TEST_DRIVER_USER_ID = 10; 360 private static final int TEST_REAR_LEFT_USER_ID = 11; 361 private static final int TEST_REAR_RIGHT_USER_ID = 12; 362 private static final int TEST_FRONT_PASSENGER_USER_ID = 13; 363 private static final int TEST_REAR_ROW_3_PASSENGER_USER_ID = 14; 364 private static final int TEST_GAIN_INDEX = 4; 365 366 // TODO(b/273800524): create a utility test class for audio attributes. 367 private static final AudioAttributes ATTRIBUTES_UNKNOWN = 368 CarAudioContext.getAudioAttributeFromUsage(USAGE_UNKNOWN); 369 private static final AudioAttributes ATTRIBUTES_GAME = 370 CarAudioContext.getAudioAttributeFromUsage(USAGE_GAME); 371 private static final AudioAttributes ATTRIBUTES_MEDIA = 372 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA); 373 private static final AudioAttributes ATTRIBUTES_NOTIFICATION = 374 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION); 375 private static final AudioAttributes ATTRIBUTES_NOTIFICATION_EVENT = 376 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION_EVENT); 377 private static final AudioAttributes ATTRIBUTES_ANNOUNCEMENT = 378 CarAudioContext.getAudioAttributeFromUsage(USAGE_ANNOUNCEMENT); 379 private static final AudioAttributes ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE = 380 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE); 381 private static final AudioAttributes ATTRIBUTES_ASSISTANCE_ACCESSIBILITY = 382 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANCE_ACCESSIBILITY); 383 private static final AudioAttributes ATTRIBUTES_ASSISTANT = 384 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANT); 385 private static final AudioAttributes ATTRIBUTES_NOTIFICATION_RINGTONE = 386 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION_RINGTONE); 387 private static final AudioAttributes ATTRIBUTES_VOICE_COMMUNICATION = 388 CarAudioContext.getAudioAttributeFromUsage(USAGE_VOICE_COMMUNICATION); 389 private static final AudioAttributes ATTRIBUTES_CALL_ASSISTANT = 390 CarAudioContext.getAudioAttributeFromUsage(USAGE_CALL_ASSISTANT); 391 private static final AudioAttributes ATTRIBUTES_VOICE_COMMUNICATION_SIGNALLING = 392 CarAudioContext.getAudioAttributeFromUsage(USAGE_VOICE_COMMUNICATION_SIGNALLING); 393 private static final AudioAttributes ATTRIBUTES_ALARM = 394 CarAudioContext.getAudioAttributeFromUsage(USAGE_ALARM); 395 private static final AudioAttributes ATTRIBUTES_ASSISTANCE_SONIFICATION = 396 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANCE_SONIFICATION); 397 private static final AudioAttributes ATTRIBUTES_EMERGENCY = 398 CarAudioContext.getAudioAttributeFromUsage(USAGE_EMERGENCY); 399 private static final AudioAttributes ATTRIBUTES_SAFETY = 400 CarAudioContext.getAudioAttributeFromUsage(USAGE_SAFETY); 401 private static final AudioAttributes ATTRIBUTES_VEHICLE_STATUS = 402 CarAudioContext.getAudioAttributeFromUsage(USAGE_VEHICLE_STATUS); 403 404 private static final List<AudioAttributes> TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_0 = List.of( 405 ATTRIBUTES_UNKNOWN, ATTRIBUTES_GAME, ATTRIBUTES_MEDIA, ATTRIBUTES_NOTIFICATION, 406 ATTRIBUTES_NOTIFICATION_EVENT, ATTRIBUTES_ANNOUNCEMENT); 407 408 private static final List<AudioAttributes> TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_1 = List.of( 409 ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE, ATTRIBUTES_ASSISTANCE_ACCESSIBILITY, 410 ATTRIBUTES_ASSISTANT); 411 412 private static final List<AudioAttributes> TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_DEFAULT = 413 List.of(ATTRIBUTES_UNKNOWN, ATTRIBUTES_GAME, ATTRIBUTES_MEDIA, 414 ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE, ATTRIBUTES_ASSISTANCE_ACCESSIBILITY, 415 ATTRIBUTES_ASSISTANT, ATTRIBUTES_NOTIFICATION_RINGTONE, 416 ATTRIBUTES_VOICE_COMMUNICATION, ATTRIBUTES_CALL_ASSISTANT, 417 ATTRIBUTES_VOICE_COMMUNICATION_SIGNALLING, ATTRIBUTES_ALARM, 418 ATTRIBUTES_NOTIFICATION, ATTRIBUTES_NOTIFICATION_EVENT, 419 ATTRIBUTES_ASSISTANCE_SONIFICATION, ATTRIBUTES_EMERGENCY, ATTRIBUTES_SAFETY, 420 ATTRIBUTES_VEHICLE_STATUS, ATTRIBUTES_ANNOUNCEMENT); 421 422 private static final List<AudioAttributes> TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_0 = List.of( 423 ATTRIBUTES_UNKNOWN, ATTRIBUTES_GAME, ATTRIBUTES_MEDIA, 424 ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE, ATTRIBUTES_ASSISTANCE_ACCESSIBILITY, 425 ATTRIBUTES_ASSISTANT, ATTRIBUTES_NOTIFICATION, ATTRIBUTES_NOTIFICATION_EVENT, 426 ATTRIBUTES_ANNOUNCEMENT); 427 428 private static final List<AudioAttributes> TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_1 = List.of( 429 ATTRIBUTES_NOTIFICATION_RINGTONE, ATTRIBUTES_VOICE_COMMUNICATION, 430 ATTRIBUTES_CALL_ASSISTANT, ATTRIBUTES_VOICE_COMMUNICATION_SIGNALLING, ATTRIBUTES_ALARM, 431 ATTRIBUTES_ASSISTANCE_SONIFICATION, ATTRIBUTES_EMERGENCY, ATTRIBUTES_SAFETY, 432 ATTRIBUTES_VEHICLE_STATUS); 433 434 private static final AudioFocusInfo TEST_AUDIO_FOCUS_INFO = 435 new AudioFocusInfo(CarAudioContext 436 .getAudioAttributeFromUsage(USAGE_VOICE_COMMUNICATION), MEDIA_APP_UID, 437 MEDIA_CLIENT_ID, "com.android.car.audio", 438 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, AUDIOFOCUS_NONE, /* flags= */ 0, 439 Build.VERSION.SDK_INT); 440 441 private static final AudioFocusInfo TEST_REAR_RIGHT_AUDIO_FOCUS_INFO = 442 new AudioFocusInfo(CarAudioContext 443 .getAudioAttributeFromUsage(USAGE_MEDIA), TEST_REAR_RIGHT_UID, 444 MEDIA_CLIENT_ID, "com.android.car.audio", 445 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, AUDIOFOCUS_NONE, /* flags= */ 0, 446 Build.VERSION.SDK_INT); 447 448 private static final int AUDIO_SERVICE_POLICY_REGISTRATIONS = 3; 449 private static final int AUDIO_SERVICE_POLICY_REGISTRATIONS_WITH_FADE_MANAGER = 4; 450 private static final int AUDIO_SERVICE_CALLBACKS_REGISTRATION = 1; 451 452 private HandlerThread mHandlerThread; 453 private Handler mHandler; 454 455 @Mock 456 private Context mMockContext; 457 @Mock 458 private TelephonyManager mMockTelephonyManagerWithoutSubscriptionId; 459 @Mock 460 private TelephonyManager mMockTelephonyManager; 461 @Mock 462 private AudioManagerWrapper mAudioManager; 463 @Mock 464 private Resources mMockResources; 465 @Mock 466 private ContentResolver mMockContentResolver; 467 @Mock 468 private AttributionSource mMockAttributionSource; 469 @Mock 470 IBinder mBinder; 471 @Mock 472 IBinder mVolumeCallbackBinder; 473 @Mock 474 IAudioControl mAudioControl; 475 @Mock 476 private PackageManager mMockPackageManager; 477 @Mock 478 private CarOccupantZoneService mMockOccupantZoneService; 479 @Mock 480 private CarOemProxyService mMockCarOemProxyService; 481 @Mock 482 private IAudioService mMockAudioService; 483 @Mock 484 private Uri mNavSettingUri; 485 @Mock 486 private AudioControlWrapperAidl mAudioControlWrapperAidl; 487 @Mock 488 private CarVolumeCallbackHandler mCarVolumeCallbackHandler; 489 @Mock 490 private CarInputService mMockCarInputService; 491 @Mock 492 private CarPowerManagementService mMockPowerService; 493 494 // Not used directly, but sets proper mockStatic() expectations on Settings 495 @SuppressWarnings("UnusedVariable") 496 private MockSettings mMockSettings; 497 498 private boolean mPersistMasterMute = true; 499 private boolean mUseDynamicRouting = true; 500 private boolean mUseHalAudioDucking = true; 501 private boolean mUseCarVolumeGroupMuting = true; 502 private boolean mUseCarVolumeGroupEvents = true; 503 private boolean mUseMinMaxActivationVolume = true; 504 private boolean mEnableVolumeKeyEventsToDynamicDevices = false; 505 private boolean mPersistFadeBalanceValues = true; 506 507 508 private TemporaryFile mTempCarAudioConfigFile; 509 private TemporaryFile mTempCarAudioFadeConfigFile; 510 511 private Context mContext; 512 private AudioDeviceInfo mMicrophoneInputDevice; 513 private AudioDeviceInfo mFmTunerInputDevice; 514 515 private CarVolumeGroupInfo mTestPrimaryZoneVolumeInfo0; 516 private CarVolumeGroupInfo mTestPrimaryZoneUmMutedVolueInfo0; 517 private CarVolumeGroupInfo mTestPrimaryZoneVolumeInfo1; 518 private CarVolumeGroupInfo mTestSecondaryConfig0VolumeGroup0Info; 519 private CarVolumeGroupInfo mTestSecondaryZoneConfig1VolumeInfo0; 520 private CarVolumeGroupInfo mTestSecondaryZoneConfig1VolumeInfo1; 521 522 private CarVolumeGroupEvent mTestCarVolumeGroupEvent; 523 private CarVolumeGroupEvent mTestCarMuteGroupEvent; 524 private CarVolumeGroupEvent mTestCarZoneReconfigurationEvent; 525 526 @Captor 527 private ArgumentCaptor<BroadcastReceiver> mVolumeReceiverCaptor; 528 529 private int mRegistrationCount = 0; 530 private List<Integer> mAudioPolicyRegistrationStatus = new ArrayList<>(); 531 532 @Rule 533 public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 534 535 private CarAudioDeviceInfoTestUtils mCarAudioDeviceUtils; 536 CarAudioServiceUnitTest()537 public CarAudioServiceUnitTest() { 538 super(CarAudioService.TAG); 539 } 540 541 @Override onSessionBuilder(CustomMockitoSessionBuilder session)542 protected void onSessionBuilder(CustomMockitoSessionBuilder session) { 543 mMockSettings = new MockSettings(session); 544 session 545 .spyStatic(SubscriptionManager.class) 546 .spyStatic(AudioManagerWrapper.class) 547 .spyStatic(AudioManagerHelper.class) 548 .spyStatic(AudioControlWrapperAidl.class) 549 .spyStatic(CoreAudioHelper.class) 550 .spyStatic(AudioControlFactory.class) 551 .spyStatic(SystemProperties.class) 552 .spyStatic(ServiceManager.class) 553 .spyStatic(Car.class); 554 } 555 556 @Before setUp()557 public void setUp() throws Exception { 558 mHandlerThread = CarServiceUtils.getHandlerThread(CarAudioService.class.getSimpleName()); 559 mHandler = new Handler(mHandlerThread.getLooper()); 560 mContext = ApplicationProvider.getApplicationContext(); 561 562 mockCarGetPlatformVersion(UPSIDE_DOWN_CAKE_0); 563 564 mockCoreAudioRoutingAndVolume(); 565 mockGrantCarControlAudioSettingsPermission(); 566 567 setUpAudioControlHAL(); 568 setUpService(); 569 570 when(Settings.Secure.getUriFor( 571 CarSettings.Secure.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL)) 572 .thenReturn(mNavSettingUri); 573 } 574 575 @After tearDown()576 public void tearDown() throws Exception { 577 if (mTempCarAudioConfigFile != null) { 578 mTempCarAudioConfigFile.close(); 579 } 580 if (mTempCarAudioFadeConfigFile != null) { 581 mTempCarAudioFadeConfigFile.close(); 582 } 583 CarLocalServices.removeServiceForTest(CarOemProxyService.class); 584 CarLocalServices.removeServiceForTest(CarOccupantZoneService.class); 585 CarLocalServices.removeServiceForTest(CarPowerManagementService.class); 586 } 587 setUpAudioControlHAL()588 private void setUpAudioControlHAL() { 589 when(mBinder.queryLocalInterface(anyString())).thenReturn(mAudioControl); 590 doReturn(mBinder).when(AudioControlWrapperAidl::getService); 591 when(mAudioControlWrapperAidl.supportsFeature( 592 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_DUCKING)).thenReturn(true); 593 when(mAudioControlWrapperAidl.supportsFeature( 594 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_FOCUS)).thenReturn(true); 595 when(mAudioControlWrapperAidl.supportsFeature( 596 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_GAIN_CALLBACK)).thenReturn(true); 597 when(mAudioControlWrapperAidl.supportsFeature( 598 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_GROUP_MUTING)).thenReturn(true); 599 when(mAudioControlWrapperAidl.supportsFeature( 600 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_MODULE_CALLBACK)).thenReturn(true); 601 doReturn(mAudioControlWrapperAidl) 602 .when(AudioControlFactory::newAudioControl); 603 } 604 setUpService()605 private void setUpService() throws Exception { 606 doReturn(0).when(() -> SubscriptionManager.getDefaultDataSubscriptionId()); 607 when(mMockContext.getSystemService(TelephonyManager.class)) 608 .thenReturn(mMockTelephonyManagerWithoutSubscriptionId); 609 when(mMockTelephonyManagerWithoutSubscriptionId.createForSubscriptionId(anyInt())) 610 .thenReturn(mMockTelephonyManager); 611 612 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); 613 when(mMockContext.getAttributionSource()).thenReturn(mMockAttributionSource); 614 doReturn(true) 615 .when(() -> AudioManagerHelper 616 .setAudioDeviceGain(any(), any(), anyInt(), anyBoolean())); 617 doReturn(true) 618 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, false)); 619 620 when(mMockOccupantZoneService.getUserForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 621 .thenReturn(TEST_DRIVER_USER_ID); 622 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 623 .thenReturn(PRIMARY_AUDIO_ZONE); 624 when(mMockOccupantZoneService.getOccupantZoneForUser(UserHandle.of(TEST_DRIVER_USER_ID))) 625 .thenReturn(TEST_DRIVER_OCCUPANT); 626 627 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 628 .thenReturn(TEST_REAR_LEFT_USER_ID); 629 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 630 .thenReturn(TEST_REAR_RIGHT_USER_ID); 631 when(mMockOccupantZoneService.getUserForOccupant(TEST_FRONT_OCCUPANT_ZONE_ID)) 632 .thenReturn(TEST_FRONT_PASSENGER_USER_ID); 633 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_ROW_3_OCCUPANT_ZONE_ID)) 634 .thenReturn(TEST_REAR_ROW_3_PASSENGER_USER_ID); 635 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 636 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 637 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 638 .thenReturn(TEST_REAR_RIGHT_ZONE_ID); 639 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_FRONT_OCCUPANT_ZONE_ID)) 640 .thenReturn(TEST_FRONT_PASSENGER_USER_ID); 641 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_REAR_ROW_3_ZONE_ID)) 642 .thenReturn(TEST_REAR_ROW_3_PASSENGER_USER_ID); 643 when(mMockOccupantZoneService.getOccupantZoneForUser( 644 UserHandle.of(TEST_REAR_RIGHT_USER_ID))).thenReturn( 645 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 646 when(mMockOccupantZoneService.getOccupantZoneForUser( 647 UserHandle.of(TEST_FRONT_PASSENGER_USER_ID))).thenReturn( 648 TEST_FRONT_PASSENGER_OCCUPANT); 649 when(mMockOccupantZoneService.getOccupantZoneForUser( 650 UserHandle.of(TEST_REAR_LEFT_USER_ID))).thenReturn( 651 TEST_REAR_LEFT_PASSENGER_OCCUPANT); 652 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_REAR_ROW_3_ZONE_ID)) 653 .thenReturn(TEST_REAR_ROW_3_PASSENGER_OCCUPANT); 654 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_REAR_RIGHT_ZONE_ID)) 655 .thenReturn(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 656 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_FRONT_ZONE_ID)) 657 .thenReturn(TEST_FRONT_PASSENGER_OCCUPANT); 658 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_REAR_LEFT_ZONE_ID)) 659 .thenReturn(TEST_REAR_LEFT_PASSENGER_OCCUPANT); 660 661 // Initially set occupant zone service at uninitialized 662 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(UserHandle.USER_SYSTEM); 663 664 SparseArray<CarOccupantZoneManager.OccupantZoneInfo> configs = new SparseArray<>(); 665 configs.put(TEST_DRIVER_OCCUPANT_ZONE_ID, TEST_DRIVER_OCCUPANT); 666 configs.put(TEST_FRONT_OCCUPANT_ZONE_ID, TEST_FRONT_PASSENGER_OCCUPANT); 667 configs.put(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID, TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 668 configs.put(TEST_REAR_LEFT_OCCUPANT_ZONE_ID, TEST_REAR_LEFT_PASSENGER_OCCUPANT); 669 configs.put(TEST_REAR_ROW_3_OCCUPANT_ZONE_ID, TEST_REAR_ROW_3_PASSENGER_OCCUPANT); 670 671 when(mMockOccupantZoneService.getOccupantsConfig()).thenReturn(configs); 672 673 CarLocalServices.removeServiceForTest(CarOccupantZoneService.class); 674 CarLocalServices.addService(CarOccupantZoneService.class, mMockOccupantZoneService); 675 CarLocalServices.removeServiceForTest(CarInputService.class); 676 CarLocalServices.addService(CarInputService.class, mMockCarInputService); 677 CarLocalServices.removeServiceForTest(CarPowerManagementService.class); 678 CarLocalServices.addService(CarPowerManagementService.class, mMockPowerService); 679 680 CarLocalServices.removeServiceForTest(CarOemProxyService.class); 681 CarLocalServices.addService(CarOemProxyService.class, mMockCarOemProxyService); 682 683 setUpAudioManager(); 684 685 setUpResources(); 686 } 687 setUpAudioManager()688 private void setUpAudioManager() throws Exception { 689 mCarAudioDeviceUtils = new CarAudioDeviceInfoTestUtils(); 690 AudioDeviceInfo[] outputDevices = mCarAudioDeviceUtils.generateOutputDeviceInfos(); 691 AudioDeviceInfo[] inputDevices = generateInputDeviceInfos(); 692 mTestPrimaryZoneVolumeInfo0 = 693 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_PRIMARY_ZONE_GROUP_0, 694 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0).setMuted(true) 695 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 696 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 697 .setAudioAttributes(TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_0) 698 .setAudioDeviceAttributes(List.of(new AudioDeviceAttributes( 699 mCarAudioDeviceUtils.mNotificationOutputBus), 700 new AudioDeviceAttributes(mCarAudioDeviceUtils.mMediaOutputDevice))) 701 .setMinActivationVolumeGainIndex(0) 702 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 703 mTestPrimaryZoneUmMutedVolueInfo0 = 704 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_PRIMARY_ZONE_GROUP_0, 705 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0).setMuted(false) 706 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 707 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 708 .setAudioAttributes(TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_0) 709 .setAudioDeviceAttributes(List.of(new AudioDeviceAttributes( 710 mCarAudioDeviceUtils.mNotificationOutputBus), 711 new AudioDeviceAttributes(mCarAudioDeviceUtils.mMediaOutputDevice))) 712 .setMinActivationVolumeGainIndex(0) 713 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 714 mTestPrimaryZoneVolumeInfo1 = 715 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_PRIMARY_ZONE_GROUP_1, 716 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1).setMuted(true) 717 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 718 .setAudioAttributes(TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_1) 719 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 720 .setAudioDeviceAttributes(List.of( 721 new AudioDeviceAttributes(mCarAudioDeviceUtils.mVoiceOutputBus), 722 new AudioDeviceAttributes(mCarAudioDeviceUtils.mNavOutputDevice))) 723 .setMinActivationVolumeGainIndex(0) 724 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 725 mTestSecondaryConfig0VolumeGroup0Info = 726 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_SECONDARY_ZONE_GROUP_0, 727 TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_0) 728 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 729 .setAudioAttributes(TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_DEFAULT) 730 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 731 .setAudioDeviceAttributes(List.of( 732 new AudioDeviceAttributes(mCarAudioDeviceUtils 733 .mSecondaryConfigOutputDevice))) 734 .setMinActivationVolumeGainIndex(0) 735 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 736 mTestSecondaryZoneConfig1VolumeInfo0 = 737 new CarVolumeGroupInfo.Builder("config 1 group " + TEST_SECONDARY_ZONE_GROUP_0, 738 TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_0) 739 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 740 .setAudioAttributes(TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_0) 741 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 742 .setAudioDeviceAttributes(List.of(new AudioDeviceAttributes( 743 mCarAudioDeviceUtils.mSecondaryConfig1Group0Device))) 744 .setMinActivationVolumeGainIndex(0) 745 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 746 mTestSecondaryZoneConfig1VolumeInfo1 = 747 new CarVolumeGroupInfo.Builder("config 1 group " + TEST_SECONDARY_ZONE_GROUP_1, 748 TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_1) 749 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 750 .setAudioAttributes(TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_1) 751 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 752 .setAudioDeviceAttributes(List.of(new AudioDeviceAttributes( 753 mCarAudioDeviceUtils.mSecondaryConfig1Group1Device))) 754 .setMinActivationVolumeGainIndex(0) 755 .setMaxActivationVolumeGainIndex(MAX_GAIN / STEP_SIZE).build(); 756 mTestCarVolumeGroupEvent = 757 new CarVolumeGroupEvent.Builder(List.of(mTestPrimaryZoneUmMutedVolueInfo0), 758 CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED, 759 List.of(CarVolumeGroupEvent.EXTRA_INFO_VOLUME_INDEX_CHANGED_BY_UI)).build(); 760 mTestCarMuteGroupEvent = 761 new CarVolumeGroupEvent.Builder(List.of(mTestPrimaryZoneUmMutedVolueInfo0), 762 CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED, 763 List.of(CarVolumeGroupEvent.EXTRA_INFO_VOLUME_INDEX_CHANGED_BY_UI)).build(); 764 mTestCarZoneReconfigurationEvent = 765 new CarVolumeGroupEvent.Builder(List.of(mTestPrimaryZoneUmMutedVolueInfo0), 766 CarVolumeGroupEvent.EVENT_TYPE_ZONE_CONFIGURATION_CHANGED, 767 List.of(CarVolumeGroupEvent.EXTRA_INFO_VOLUME_INDEX_CHANGED_BY_UI)).build(); 768 when(mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)) 769 .thenReturn(outputDevices); 770 when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) 771 .thenReturn(inputDevices); 772 773 when(mAudioManager.registerAudioPolicy(any())).thenAnswer(invocation -> { 774 AudioPolicy policy = (AudioPolicy) invocation.getArguments()[0]; 775 policy.setRegistration(REGISTRATION_ID); 776 777 // Only return an specific result if testing failures at different phases. 778 return mAudioPolicyRegistrationStatus.isEmpty() 779 ? SUCCESS : mAudioPolicyRegistrationStatus.get(mRegistrationCount++); 780 }); 781 782 when(mAudioManager.getStreamMinVolume(anyInt())).thenReturn(TEST_STREAM_MIN_VOLUME); 783 when(mAudioManager.getStreamMaxVolume(anyInt())).thenReturn(TEST_STREAM_MAX_VOLUME); 784 when(mAudioManager.getStreamVolume(anyInt())).thenReturn(TEST_STREAM_VOLUME); 785 786 when(mAudioManager.isAudioServerRunning()).thenReturn(true); 787 788 // Needed by audio policy when setting UID device affinity 789 IBinder mockBinder = mock(IBinder.class); 790 when(mockBinder.queryLocalInterface(any())).thenReturn(mMockAudioService); 791 doReturn(mockBinder).when(() -> ServiceManager.getService(Context.AUDIO_SERVICE)); 792 } 793 setUpResources()794 private void setUpResources() { 795 when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); 796 when(mMockContext.createContextAsUser(any(), anyInt())).thenReturn(mMockContext); 797 when(mMockContext.getResources()).thenReturn(mMockResources); 798 when(mMockResources.getBoolean(audioUseDynamicRouting)).thenReturn(mUseDynamicRouting); 799 when(mMockResources.getInteger(audioVolumeKeyEventTimeoutMs)) 800 .thenReturn(VOLUME_KEY_EVENT_TIMEOUT_MS); 801 when(mMockResources.getBoolean(audioUseHalDuckingSignals)).thenReturn(mUseHalAudioDucking); 802 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)) 803 .thenReturn(mUseCarVolumeGroupMuting); 804 when(mMockResources.getBoolean(audioUseCarVolumeGroupEvent)) 805 .thenReturn(mUseCarVolumeGroupEvents); 806 when(mMockResources.getBoolean(audioUseMinMaxActivationVolume)) 807 .thenReturn(mUseMinMaxActivationVolume); 808 when(mMockResources.getInteger(audioVolumeAdjustmentContextsVersion)) 809 .thenReturn(AUDIO_CONTEXT_PRIORITY_LIST_VERSION_ONE); 810 when(mMockResources.getBoolean(audioPersistMasterMuteState)).thenReturn(mPersistMasterMute); 811 enableVolumeKeyEventsToDynamicDevices(mEnableVolumeKeyEventsToDynamicDevices); 812 when(mMockResources.getBoolean(audioPersistFadeBalanceLevels)) 813 .thenReturn(mPersistFadeBalanceValues); 814 } 815 enableVolumeKeyEventsToDynamicDevices(boolean enableVolumeKeyEvents)816 private void enableVolumeKeyEventsToDynamicDevices(boolean enableVolumeKeyEvents) { 817 when(mMockResources.getBoolean(audioEnableVolumeKeyEventsToDynamicDevices)) 818 .thenReturn(enableVolumeKeyEvents); 819 } 820 821 @Test constructor_withValidContext()822 public void constructor_withValidContext() { 823 AudioManager manager = mock(AudioManager.class); 824 when(mMockContext.getSystemService(AudioManager.class)).thenReturn(manager); 825 826 new CarAudioService(mMockContext); 827 828 verify(mMockContext).getSystemService(AudioManager.class); 829 verify(mMockContext).getSystemService(TelephonyManager.class); 830 } 831 832 @Test constructor_withNullContext_fails()833 public void constructor_withNullContext_fails() { 834 NullPointerException thrown = 835 assertThrows(NullPointerException.class, () -> new CarAudioService(null)); 836 837 expectWithMessage("Car Audio Service Construction Exception") 838 .that(thrown).hasMessageThat().contains("Context"); 839 } 840 841 @Test constructor_withNullContextAndNullPath_fails()842 public void constructor_withNullContextAndNullPath_fails() { 843 NullPointerException thrown = 844 assertThrows(NullPointerException.class, 845 () -> new CarAudioService(/* context= */null, 846 /* audioManagerWrapper= */ null, 847 /* audioConfigurationPath= */ null, 848 /* carVolumeCallbackHandler= */ null, 849 /* audioFadeConfigurationPath= */ null)); 850 851 expectWithMessage("Car Audio Service Construction") 852 .that(thrown).hasMessageThat().contains("Context"); 853 } 854 855 @Test constructor_withLegacyMode_enableFadeManagerConfiguration_fails()856 public void constructor_withLegacyMode_enableFadeManagerConfiguration_fails() 857 throws Exception { 858 mSetFlagsRule.enableFlags(FLAG_ENABLE_FADE_MANAGER_CONFIGURATION); 859 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_FADE_MANAGER_CONFIGURATION); 860 when(mMockResources.getBoolean(audioUseDynamicRouting)).thenReturn(false); 861 when(mMockResources.getBoolean(audioUseFadeManagerConfiguration)).thenReturn(true); 862 863 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 864 () -> setUpAudioServiceWithoutInit()); 865 866 expectWithMessage("Car audio service construction").that(thrown).hasMessageThat() 867 .containsMatch("Fade manager configuration feature can not"); 868 } 869 870 @Test 871 @DisableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withVolumeControlPolicyRegistrationError_fails()872 public void init_withVolumeControlPolicyRegistrationError_fails() throws Exception { 873 mAudioPolicyRegistrationStatus.add(ERROR); 874 CarAudioService service = setUpAudioServiceWithoutInit(); 875 876 IllegalStateException thrown = 877 assertThrows(IllegalStateException.class, () -> service.init()); 878 879 expectWithMessage("Audio control policy registration exception").that(thrown) 880 .hasMessageThat().containsMatch("car audio service's volume control audio policy"); 881 } 882 883 @Test 884 @EnableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withVolumeControlPolicyRegistrationError_fails_asyncInit()885 public void init_withVolumeControlPolicyRegistrationError_fails_asyncInit() throws Exception { 886 mAudioPolicyRegistrationStatus.add(ERROR); 887 CarAudioService service = setUpAudioServiceWithoutInit(); 888 889 service.init(); 890 891 expectWithMessage("waitForInitComplete succeeded").that( 892 service.waitForInitComplete(INIT_TIMEOUT_MS)).isFalse(); 893 } 894 895 @Test 896 @DisableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withRepeatedDynamicDevicesInConfig_fails()897 public void init_withRepeatedDynamicDevicesInConfig_fails() throws Exception { 898 setUpTempFileForAudioConfiguration( 899 R.raw.car_audio_configuration_with_repeated_dynamic_devices_in_config); 900 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 901 CarAudioService service = setUpAudioServiceWithDynamicDevices(mTempCarAudioConfigFile, 902 mTempCarAudioFadeConfigFile); 903 904 RuntimeException thrown = 905 assertThrows(RuntimeException.class, () -> service.init()); 906 907 expectWithMessage("Car audio zone config with multiple dynamic devices exception") 908 .that(thrown).hasMessageThat() 909 .containsMatch("Invalid zone configurations for zone"); 910 } 911 912 @Test 913 @EnableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withRepeatedDynamicDevicesInConfig_fails_asyncInit()914 public void init_withRepeatedDynamicDevicesInConfig_fails_asyncInit() throws Exception { 915 setUpTempFileForAudioConfiguration( 916 R.raw.car_audio_configuration_with_repeated_dynamic_devices_in_config); 917 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 918 CarAudioService service = setUpAudioServiceWithDynamicDevices(mTempCarAudioConfigFile, 919 mTempCarAudioFadeConfigFile); 920 921 service.init(); 922 923 expectWithMessage("waitForInitComplete succeeded").that( 924 service.waitForInitComplete(INIT_TIMEOUT_MS)).isFalse(); 925 } 926 927 @Test 928 @DisableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withFocusControlPolicyRegistrationError_fails()929 public void init_withFocusControlPolicyRegistrationError_fails() throws Exception { 930 mAudioPolicyRegistrationStatus.add(SUCCESS); 931 mAudioPolicyRegistrationStatus.add(ERROR); 932 CarAudioService service = setUpAudioServiceWithoutInit(); 933 934 IllegalStateException thrown = 935 assertThrows(IllegalStateException.class, () -> service.init()); 936 937 expectWithMessage("Audio control policy registration exception").that(thrown) 938 .hasMessageThat().containsMatch("car audio service's focus control audio policy"); 939 } 940 941 @Test 942 @EnableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withFocusControlPolicyRegistrationError_fails_asyncInit()943 public void init_withFocusControlPolicyRegistrationError_fails_asyncInit() throws Exception { 944 mAudioPolicyRegistrationStatus.add(SUCCESS); 945 mAudioPolicyRegistrationStatus.add(ERROR); 946 CarAudioService service = setUpAudioServiceWithoutInit(); 947 948 service.init(); 949 950 expectWithMessage("waitForInitComplete succeeded").that( 951 service.waitForInitComplete(INIT_TIMEOUT_MS)).isFalse(); 952 } 953 954 @Test 955 @DisableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withAudioRoutingPolicyRegistrationError_fails()956 public void init_withAudioRoutingPolicyRegistrationError_fails() throws Exception { 957 mAudioPolicyRegistrationStatus.add(SUCCESS); 958 mAudioPolicyRegistrationStatus.add(SUCCESS); 959 mAudioPolicyRegistrationStatus.add(ERROR); 960 CarAudioService service = setUpAudioServiceWithoutInit(); 961 962 IllegalStateException thrown = 963 assertThrows(IllegalStateException.class, () -> service.init()); 964 965 expectWithMessage("Audio routing policy registration exception").that(thrown) 966 .hasMessageThat().containsMatch("Audio routing policy registration"); 967 } 968 969 @Test 970 @EnableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withAudioRoutingPolicyRegistrationError_fails_asyncInit()971 public void init_withAudioRoutingPolicyRegistrationError_fails_asyncInit() throws Exception { 972 mAudioPolicyRegistrationStatus.add(SUCCESS); 973 mAudioPolicyRegistrationStatus.add(SUCCESS); 974 mAudioPolicyRegistrationStatus.add(ERROR); 975 CarAudioService service = setUpAudioServiceWithoutInit(); 976 977 service.init(); 978 979 expectWithMessage("waitForInitComplete succeeded").that( 980 service.waitForInitComplete(INIT_TIMEOUT_MS)).isFalse(); 981 } 982 983 @Test 984 @DisableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withFadeManagerConfigPolicyRegistrationError_fails()985 public void init_withFadeManagerConfigPolicyRegistrationError_fails() throws Exception { 986 mSetFlagsRule.enableFlags(FLAG_ENABLE_FADE_MANAGER_CONFIGURATION); 987 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_FADE_MANAGER_CONFIGURATION); 988 when(mMockResources.getBoolean(audioUseFadeManagerConfiguration)).thenReturn(true); 989 mAudioPolicyRegistrationStatus.add(SUCCESS); 990 mAudioPolicyRegistrationStatus.add(SUCCESS); 991 mAudioPolicyRegistrationStatus.add(SUCCESS); 992 mAudioPolicyRegistrationStatus.add(ERROR); 993 CarAudioService service = setUpAudioServiceWithoutInit(); 994 995 IllegalStateException thrown = 996 assertThrows(IllegalStateException.class, () -> service.init()); 997 998 expectWithMessage("Audio fade policy registration exception").that(thrown).hasMessageThat() 999 .containsMatch("car audio service's fade configuration audio policy"); 1000 } 1001 1002 @Test 1003 @EnableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withFadeManagerConfigPolicyRegistrationError_fails_asyncInit()1004 public void init_withFadeManagerConfigPolicyRegistrationError_fails_asyncInit() 1005 throws Exception { 1006 mSetFlagsRule.enableFlags(FLAG_ENABLE_FADE_MANAGER_CONFIGURATION); 1007 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_FADE_MANAGER_CONFIGURATION); 1008 when(mMockResources.getBoolean(audioUseFadeManagerConfiguration)).thenReturn(true); 1009 mAudioPolicyRegistrationStatus.add(SUCCESS); 1010 mAudioPolicyRegistrationStatus.add(SUCCESS); 1011 mAudioPolicyRegistrationStatus.add(SUCCESS); 1012 mAudioPolicyRegistrationStatus.add(ERROR); 1013 CarAudioService service = setUpAudioServiceWithoutInit(); 1014 1015 service.init(); 1016 1017 expectWithMessage("waitForInitComplete succeeded").that( 1018 service.waitForInitComplete(INIT_TIMEOUT_MS)).isFalse(); 1019 } 1020 1021 @Test init_initializesAudioServiceCallbacks()1022 public void init_initializesAudioServiceCallbacks() throws Exception { 1023 mSetFlagsRule.disableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1024 CarAudioService service = setUpAudioServiceWithoutInit(); 1025 1026 initServiceAndWaitForComplete(service); 1027 1028 verify(mAudioManager).setAudioServerStateCallback(any(), any()); 1029 verify(mAudioManager, never()).registerAudioDeviceCallback(any(), any()); 1030 } 1031 1032 @Test init_initializesAudioServiceCallbacks_withDynamicDevices()1033 public void init_initializesAudioServiceCallbacks_withDynamicDevices() throws Exception { 1034 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1035 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 1036 1037 initServiceAndWaitForComplete(service); 1038 1039 verify(mAudioManager).setAudioServerStateCallback(any(), any()); 1040 verify(mAudioManager).registerAudioDeviceCallback(any(), any()); 1041 } 1042 1043 @Test init_withDynamicDevices()1044 public void init_withDynamicDevices() throws Exception { 1045 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1046 CarAudioService audioServiceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 1047 1048 initServiceAndWaitForComplete(audioServiceWithDynamicDevices); 1049 1050 List<CarAudioZoneConfigInfo> zoneConfigInfos = 1051 audioServiceWithDynamicDevices.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 1052 List<String> names = zoneConfigInfos.stream().map(config -> config.getName()).toList(); 1053 expectWithMessage("Dynamic configuration names").that(names).containsExactly( 1054 DEFAULT_CONFIG_NAME_DYNAMIC_DEVICES, PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES, 1055 TERTIARY_CONFIG_NAME_DYNAMIC_DEVICES); 1056 CarAudioZoneConfigInfo btConfig = zoneConfigInfos.stream() 1057 .filter(config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 1058 .findFirst().orElseThrow(); 1059 expectWithMessage("Bluetooth configuration by default active status") 1060 .that(btConfig.isActive()).isFalse(); 1061 } 1062 1063 @Test 1064 @DisableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withAudioServerDown_noAsyncInit()1065 public void init_withAudioServerDown_noAsyncInit() throws Exception { 1066 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1067 when(mAudioManager.isAudioServerRunning()).thenReturn(false); 1068 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 1069 1070 service.init(); 1071 1072 verify(mAudioManager).setAudioServerStateCallback(any(), any()); 1073 verify(mAudioManager, never()).registerAudioDeviceCallback(any(), any()); 1074 } 1075 1076 @Test 1077 @EnableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withAudioServerDown_asyncInit()1078 public void init_withAudioServerDown_asyncInit() throws Exception { 1079 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1080 when(mAudioManager.isAudioServerRunning()).thenReturn(false); 1081 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 1082 1083 service.init(); 1084 1085 expectWithMessage("waitForInitComplete succeeded").that( 1086 service.waitForInitComplete(INIT_TIMEOUT_MS)).isTrue(); 1087 verify(mAudioManager).setAudioServerStateCallback(any(), any()); 1088 verify(mAudioManager, never()).registerAudioDeviceCallback(any(), any()); 1089 } 1090 1091 @Test 1092 @EnableFlags({Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withAudioServerDown_asyncInit_audioServerUpLater()1093 public void init_withAudioServerDown_asyncInit_audioServerUpLater() throws Exception { 1094 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1095 when(mAudioManager.isAudioServerRunning()).thenReturn(false); 1096 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 1097 1098 service.init(); 1099 1100 AudioServerStateCallback callback = getAudioServerStateCallback(); 1101 when(mAudioManager.isAudioServerRunning()).thenReturn(true); 1102 callback.onAudioServerUp(); 1103 1104 expectWithMessage("waitForInitComplete succeeded").that( 1105 service.waitForInitComplete(INIT_TIMEOUT_MS)).isTrue(); 1106 verify(mAudioManager, timeout(INIT_TIMEOUT_MS)).registerAudioDeviceCallback(any(), any()); 1107 } 1108 1109 @Test 1110 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS, Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withCoreVolumeMisconfigured()1111 public void init_withCoreVolumeMisconfigured() throws Exception { 1112 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(true); 1113 CarAudioService service = setUpAudioServiceWithoutInit(); 1114 1115 // Init should complete normally after vendor freeze improvements, since no exception will 1116 // be thrown. 1117 initServiceAndWaitForComplete(service); 1118 1119 verify(mAudioManager).setAudioServerStateCallback(any(), any()); 1120 verify(mAudioManager).registerAudioDeviceCallback(any(), any()); 1121 } 1122 1123 @Test 1124 @DisableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS, 1125 Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withCoreVolumeMisconfigured_failsOnInit()1126 public void init_withCoreVolumeMisconfigured_failsOnInit() throws Exception { 1127 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(true); 1128 CarAudioService service = setUpAudioServiceWithoutInit(); 1129 1130 IllegalArgumentException thrown = 1131 assertThrows(IllegalArgumentException.class, service::init); 1132 1133 expectWithMessage("Exception on service init with empty group and using core volume") 1134 .that(thrown).hasMessageThat().contains("group name attribute can not be empty when" 1135 + " relying on core volume groups"); 1136 } 1137 1138 @Test 1139 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS, Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withMissingOccupantZones_captureActiveZonesOnly()1140 public void init_withMissingOccupantZones_captureActiveZonesOnly() throws Exception { 1141 SparseArray<CarOccupantZoneManager.OccupantZoneInfo> configs = new SparseArray<>(); 1142 configs.put(TEST_DRIVER_OCCUPANT_ZONE_ID, TEST_DRIVER_OCCUPANT); 1143 when(mMockOccupantZoneService.getOccupantsConfig()).thenReturn(configs); 1144 CarAudioService service = setUpAudioServiceWithoutInit(); 1145 1146 // Init should complete normally after vendor freeze improvements, since no exception will 1147 // be thrown. 1148 initServiceAndWaitForComplete(service); 1149 1150 ArgumentCaptor<SparseIntArray> captor = 1151 ArgumentCaptor.forClass(SparseIntArray.class); 1152 verify(mMockOccupantZoneService).setAudioZoneIdsForOccupantZoneIds(captor.capture()); 1153 int[] audioZoneZones = captor.getValue().copyKeys(); 1154 expectWithMessage("Configured audio zones with missing occupant zones") 1155 .that(audioZoneZones).asList().containsExactly(PRIMARY_AUDIO_ZONE); 1156 } 1157 1158 @Test 1159 @EnableFlags({Flags.FLAG_AUDIO_CONTROL_HAL_CONFIGURATION}) init_withCarAudioControlHAL_initsHALZones()1160 public void init_withCarAudioControlHAL_initsHALZones() throws Exception { 1161 CarAudioService service = setupAudioServiceUsingAudioControlWithoutInit(); 1162 1163 initServiceAndWaitForComplete(service); 1164 1165 expectWithMessage("Audio control HAL configured status") 1166 .that(service.isConfiguredUsingAudioControlHAL()).isTrue(); 1167 expectWithMessage("Audio control HAL configured zones") 1168 .that(service.getAudioZoneIds()).asList().containsExactly(PRIMARY_AUDIO_ZONE, 1169 SECONDARY_ZONE_ID, TERTIARY_ZONE_ID, QUATERNARY_ZONE_ID); 1170 ArgumentCaptor<SparseIntArray> captor = ArgumentCaptor.forClass(SparseIntArray.class); 1171 verify(mMockOccupantZoneService).setAudioZoneIdsForOccupantZoneIds(captor.capture()); 1172 var map = new SparseIntArray(4); 1173 map.put(PRIMARY_AUDIO_ZONE, PRIMARY_OCCUPANT_ID); 1174 map.put(SECONDARY_ZONE_ID, SECONDARY_OCCUPANT_ID); 1175 map.put(TERTIARY_ZONE_ID, TERTIARY_OCCUPANT_ID); 1176 map.put(QUATERNARY_ZONE_ID, QUATERNARY_OCCUPANT_ID); 1177 var zoneIdOccupantZoneId = captor.getValue(); 1178 expectWithMessage("Audio control HAL configured size of mapped occupants") 1179 .that(zoneIdOccupantZoneId.size()).isEqualTo(map.size()); 1180 for (int c = 0; c < map.size(); c++) { 1181 int zoneId = map.keyAt(c); 1182 int occupantZoneId = map.get(zoneId); 1183 expectWithMessage("Occupant zone audio control HAL for zone id %s", zoneId) 1184 .that(zoneIdOccupantZoneId.get(zoneId)).isEqualTo(occupantZoneId); 1185 } 1186 } 1187 1188 @Test 1189 @DisableFlags({Flags.FLAG_AUDIO_CONTROL_HAL_CONFIGURATION}) init_withCarAudioControlHALDisabled_initsFileConfigZones()1190 public void init_withCarAudioControlHALDisabled_initsFileConfigZones() throws Exception { 1191 CarAudioService service = setupAudioServiceUsingAudioControlWithoutInit(); 1192 1193 initServiceAndWaitForComplete(service); 1194 1195 expectWithMessage("Car audio files configured status") 1196 .that(service.isConfiguredUsingAudioControlHAL()).isFalse(); 1197 expectWithMessage("Car audio zones configure using car audio configuration file") 1198 .that(service.getAudioZoneIds()).asList().containsExactly(PRIMARY_AUDIO_ZONE, 1199 SECONDARY_ZONE_ID); 1200 ArgumentCaptor<SparseIntArray> captor = ArgumentCaptor.forClass(SparseIntArray.class); 1201 verify(mMockOccupantZoneService).setAudioZoneIdsForOccupantZoneIds(captor.capture()); 1202 var zoneIdOccupantZoneId = captor.getValue(); 1203 expectWithMessage("Car audio file configured size of mapped occupants") 1204 .that(zoneIdOccupantZoneId.size()).isEqualTo(0); 1205 } 1206 1207 @Test 1208 @DisableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS, 1209 Flags.FLAG_ASYNC_AUDIO_SERVICE_INIT}) init_withMissingOccupantZones_captureActiveAllZones()1210 public void init_withMissingOccupantZones_captureActiveAllZones() throws Exception { 1211 SparseArray<CarOccupantZoneManager.OccupantZoneInfo> configs = new SparseArray<>(); 1212 configs.put(TEST_DRIVER_OCCUPANT_ZONE_ID, TEST_DRIVER_OCCUPANT); 1213 when(mMockOccupantZoneService.getOccupantsConfig()).thenReturn(configs); 1214 CarAudioService service = setUpAudioServiceWithoutInit(); 1215 1216 initServiceAndWaitForComplete(service); 1217 1218 ArgumentCaptor<SparseIntArray> captor = 1219 ArgumentCaptor.forClass(SparseIntArray.class); 1220 verify(mMockOccupantZoneService).setAudioZoneIdsForOccupantZoneIds(captor.capture()); 1221 int[] audioZoneZones = captor.getValue().copyKeys(); 1222 expectWithMessage("Configured audio zones with all audio zones").that(audioZoneZones) 1223 .asList().containsExactly(PRIMARY_AUDIO_ZONE, TEST_REAR_LEFT_ZONE_ID, 1224 TEST_REAR_RIGHT_ZONE_ID, TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID); 1225 } 1226 1227 @Test release_releasesAudioServiceCallbacks()1228 public void release_releasesAudioServiceCallbacks() throws Exception { 1229 mSetFlagsRule.disableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1230 CarAudioService service = setUpAudioService(); 1231 1232 service.release(); 1233 1234 verify(mAudioManager, never()).unregisterAudioDeviceCallback(any()); 1235 verify(mAudioManager).clearAudioServerStateCallback(); 1236 verify(mAudioControlWrapperAidl).clearModuleChangeCallback(); 1237 } 1238 1239 @Test release_releasesAudioServiceCallbacks_withDynamicDevices()1240 public void release_releasesAudioServiceCallbacks_withDynamicDevices() throws Exception { 1241 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 1242 initServiceAndWaitForComplete(service); 1243 1244 service.release(); 1245 1246 verify(mAudioManager).unregisterAudioDeviceCallback(any()); 1247 verify(mAudioManager).clearAudioServerStateCallback(); 1248 verify(mAudioControlWrapperAidl).clearModuleChangeCallback(); 1249 } 1250 1251 @Test release_withoutModuleChangeCallback()1252 public void release_withoutModuleChangeCallback() throws Exception { 1253 when(mAudioControlWrapperAidl.supportsFeature( 1254 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_MODULE_CALLBACK)).thenReturn(false); 1255 CarAudioService service = setUpAudioService(); 1256 1257 service.release(); 1258 1259 verify(mAudioControlWrapperAidl, never()).clearModuleChangeCallback(); 1260 } 1261 1262 @Test release_beforeInitComplete()1263 public void release_beforeInitComplete() throws Exception { 1264 mSetFlagsRule.disableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 1265 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration); 1266 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 1267 CarAudioService service = new CarAudioService(mMockContext, mAudioManager, 1268 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 1269 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 1270 service.init(); 1271 1272 service.release(); 1273 1274 verify(mAudioManager, never()).unregisterAudioDeviceCallback(any()); 1275 verify(mAudioManager).clearAudioServerStateCallback(); 1276 verify(mAudioControlWrapperAidl).clearModuleChangeCallback(); 1277 } 1278 1279 @Test getAudioZoneIds_withBaseConfiguration_returnAllTheZones()1280 public void getAudioZoneIds_withBaseConfiguration_returnAllTheZones() throws Exception { 1281 CarAudioService service = setUpAudioService(); 1282 1283 expectWithMessage("Car Audio Service Zones") 1284 .that(service.getAudioZoneIds()).asList() 1285 .containsExactly(PRIMARY_AUDIO_ZONE, TEST_REAR_LEFT_ZONE_ID, 1286 TEST_REAR_RIGHT_ZONE_ID, TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID); 1287 } 1288 1289 @Test getVolumeGroupCount_onPrimaryZone_returnsAllGroups()1290 public void getVolumeGroupCount_onPrimaryZone_returnsAllGroups() throws Exception { 1291 CarAudioService service = setUpAudioService(); 1292 1293 expectWithMessage("Primary zone car volume group count") 1294 .that(service.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 1295 .isEqualTo(PRIMARY_ZONE_VOLUME_GROUP_COUNT); 1296 } 1297 1298 @Test getVolumeGroupCount_onPrimaryZone_withNonDynamicRouting_returnsAllGroups()1299 public void getVolumeGroupCount_onPrimaryZone_withNonDynamicRouting_returnsAllGroups() 1300 throws Exception { 1301 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1302 1303 expectWithMessage("Non dynamic routing primary zone car volume group count") 1304 .that(nonDynamicAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 1305 .isEqualTo(CarAudioDynamicRouting.STREAM_TYPES.length); 1306 } 1307 1308 @Test getVolumeGroupIdForUsage_forMusicUsage()1309 public void getVolumeGroupIdForUsage_forMusicUsage() throws Exception { 1310 CarAudioService service = setUpAudioService(); 1311 1312 expectWithMessage("Primary zone's media car volume group id") 1313 .that(service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, USAGE_MEDIA)) 1314 .isEqualTo(MEDIA_VOLUME_GROUP_ID); 1315 } 1316 1317 @Test getVolumeGroupIdForUsage_withNonDynamicRouting_forMusicUsage()1318 public void getVolumeGroupIdForUsage_withNonDynamicRouting_forMusicUsage() throws Exception { 1319 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1320 1321 expectWithMessage("Non dynamic routing primary zone's media car volume group id") 1322 .that(nonDynamicAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 1323 USAGE_MEDIA)).isEqualTo(MEDIA_VOLUME_GROUP_ID); 1324 } 1325 1326 @Test getVolumeGroupIdForUsage_forNavigationUsage()1327 public void getVolumeGroupIdForUsage_forNavigationUsage() throws Exception { 1328 CarAudioService service = setUpAudioService(); 1329 1330 expectWithMessage("Primary zone's navigation car volume group id") 1331 .that(service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 1332 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)) 1333 .isEqualTo(NAVIGATION_VOLUME_GROUP_ID); 1334 } 1335 1336 @Test getVolumeGroupIdForUsage_withNonDynamicRouting_forNavigationUsage()1337 public void getVolumeGroupIdForUsage_withNonDynamicRouting_forNavigationUsage() 1338 throws Exception { 1339 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1340 1341 expectWithMessage("Non dynamic routing primary zone's navigation car volume group id") 1342 .that(nonDynamicAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 1343 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)) 1344 .isEqualTo(INVALID_VOLUME_GROUP_ID); 1345 } 1346 1347 @Test getVolumeGroupIdForUsage_forInvalidUsage_returnsInvalidGroupId()1348 public void getVolumeGroupIdForUsage_forInvalidUsage_returnsInvalidGroupId() throws Exception { 1349 CarAudioService service = setUpAudioService(); 1350 1351 expectWithMessage("Primary zone's invalid car volume group id") 1352 .that(service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, INVALID_USAGE)) 1353 .isEqualTo(INVALID_VOLUME_GROUP_ID); 1354 } 1355 1356 @Test 1357 public void getVolumeGroupIdForUsage_forInvalidUsage_withNonDynamicRouting_returnsInvalidGroupId()1358 getVolumeGroupIdForUsage_forInvalidUsage_withNonDynamicRouting_returnsInvalidGroupId() 1359 throws Exception { 1360 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1361 1362 expectWithMessage("Non dynamic routing primary zone's invalid car volume group id") 1363 .that(nonDynamicAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 1364 INVALID_USAGE)).isEqualTo(INVALID_VOLUME_GROUP_ID); 1365 } 1366 1367 @Test getVolumeGroupIdForUsage_forUnknownUsage_returnsMediaGroupId()1368 public void getVolumeGroupIdForUsage_forUnknownUsage_returnsMediaGroupId() throws Exception { 1369 CarAudioService service = setUpAudioService(); 1370 1371 expectWithMessage("Primary zone's unknown car volume group id") 1372 .that(service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, USAGE_UNKNOWN)) 1373 .isEqualTo(MEDIA_VOLUME_GROUP_ID); 1374 } 1375 1376 @Test getVolumeGroupIdForUsage_forVirtualUsage_returnsInvalidGroupId()1377 public void getVolumeGroupIdForUsage_forVirtualUsage_returnsInvalidGroupId() throws Exception { 1378 CarAudioService service = setUpAudioService(); 1379 1380 expectWithMessage("Primary zone's virtual car volume group id") 1381 .that(service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 1382 AudioManagerHelper.getUsageVirtualSource())) 1383 .isEqualTo(INVALID_VOLUME_GROUP_ID); 1384 } 1385 1386 @Test getVolumeGroupCount_onSecondaryZone_returnsAllGroups()1387 public void getVolumeGroupCount_onSecondaryZone_returnsAllGroups() throws Exception { 1388 CarAudioService service = setUpAudioService(); 1389 1390 expectWithMessage("Secondary Zone car volume group count") 1391 .that(service.getVolumeGroupCount(TEST_REAR_LEFT_ZONE_ID)) 1392 .isEqualTo(SECONDARY_ZONE_VOLUME_GROUP_COUNT); 1393 } 1394 1395 @Test getUsagesForVolumeGroupId_forMusicContext()1396 public void getUsagesForVolumeGroupId_forMusicContext() throws Exception { 1397 CarAudioService service = setUpAudioService(); 1398 1399 1400 expectWithMessage("Primary zone's music car volume group id usages") 1401 .that(service.getUsagesForVolumeGroupId(PRIMARY_AUDIO_ZONE, 1402 MEDIA_VOLUME_GROUP_ID)).asList() 1403 .containsExactly(USAGE_UNKNOWN, USAGE_GAME, USAGE_MEDIA, USAGE_ANNOUNCEMENT, 1404 USAGE_NOTIFICATION, USAGE_NOTIFICATION_EVENT); 1405 } 1406 1407 @Test getUsagesForVolumeGroupId_forSystemContext()1408 public void getUsagesForVolumeGroupId_forSystemContext() throws Exception { 1409 CarAudioService service = setUpAudioService(); 1410 int systemVolumeGroup = 1411 service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, USAGE_EMERGENCY); 1412 1413 expectWithMessage("Primary zone's system car volume group id usages") 1414 .that(service.getUsagesForVolumeGroupId(PRIMARY_AUDIO_ZONE, 1415 systemVolumeGroup)).asList().containsExactly(USAGE_ALARM, USAGE_EMERGENCY, 1416 USAGE_SAFETY, USAGE_VEHICLE_STATUS, USAGE_ASSISTANCE_SONIFICATION); 1417 } 1418 1419 @Test getUsagesForVolumeGroupId_onSecondaryZone_forSingleVolumeGroupId_returnAllUsages()1420 public void getUsagesForVolumeGroupId_onSecondaryZone_forSingleVolumeGroupId_returnAllUsages() 1421 throws Exception { 1422 CarAudioService service = setUpAudioService(); 1423 1424 expectWithMessage("Secondary Zone's car volume group id usages") 1425 .that(service.getUsagesForVolumeGroupId(TEST_REAR_LEFT_ZONE_ID, 1426 SECONDARY_ZONE_VOLUME_GROUP_ID)) 1427 .asList().containsExactly(USAGE_UNKNOWN, USAGE_MEDIA, 1428 USAGE_VOICE_COMMUNICATION, USAGE_VOICE_COMMUNICATION_SIGNALLING, 1429 USAGE_ALARM, USAGE_NOTIFICATION, USAGE_NOTIFICATION_RINGTONE, 1430 USAGE_NOTIFICATION_EVENT, USAGE_ASSISTANCE_ACCESSIBILITY, 1431 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, USAGE_ASSISTANCE_SONIFICATION, 1432 USAGE_GAME, USAGE_ASSISTANT, USAGE_CALL_ASSISTANT, USAGE_EMERGENCY, 1433 USAGE_ANNOUNCEMENT, USAGE_SAFETY, USAGE_VEHICLE_STATUS); 1434 } 1435 1436 @Test getUsagesForVolumeGroupId_withoutDynamicRouting()1437 public void getUsagesForVolumeGroupId_withoutDynamicRouting() throws Exception { 1438 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1439 1440 expectWithMessage("Media car volume group id without dynamic routing").that( 1441 nonDynamicAudioService.getUsagesForVolumeGroupId(PRIMARY_AUDIO_ZONE, 1442 MEDIA_VOLUME_GROUP_ID)).asList() 1443 .containsExactly(CarAudioDynamicRouting.STREAM_TYPE_USAGES[MEDIA_VOLUME_GROUP_ID]); 1444 } 1445 1446 @Test createAudioPatch_onMediaOutputDevice_failsForConfigurationMissing()1447 public void createAudioPatch_onMediaOutputDevice_failsForConfigurationMissing() 1448 throws Exception { 1449 CarAudioService service = setUpAudioService(); 1450 1451 doReturn(false) 1452 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, false)); 1453 1454 IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> 1455 service.createAudioPatch(PRIMARY_ZONE_FM_TUNER_ADDRESS, USAGE_MEDIA, DEFAULT_GAIN)); 1456 1457 expectWithMessage("FM and Media Audio Patch Exception") 1458 .that(thrown).hasMessageThat().contains("Audio Patch APIs not enabled"); 1459 } 1460 1461 @Test createAudioPatch_onMediaOutputDevice_failsForMissingPermission()1462 public void createAudioPatch_onMediaOutputDevice_failsForMissingPermission() throws Exception { 1463 CarAudioService service = setUpAudioService(); 1464 1465 mockDenyCarControlAudioSettingsPermission(); 1466 1467 SecurityException thrown = assertThrows(SecurityException.class, 1468 () -> service 1469 .createAudioPatch(PRIMARY_ZONE_FM_TUNER_ADDRESS, 1470 USAGE_MEDIA, DEFAULT_GAIN)); 1471 1472 expectWithMessage("FM and Media Audio Patch Permission Exception") 1473 .that(thrown).hasMessageThat().contains(PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 1474 } 1475 1476 @Test createAudioPatch_onMediaOutputDevice_succeeds()1477 public void createAudioPatch_onMediaOutputDevice_succeeds() throws Exception { 1478 CarAudioService service = setUpAudioService(); 1479 1480 mockGrantCarControlAudioSettingsPermission(); 1481 doReturn(false) 1482 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, true)); 1483 doReturn(new AudioPatchInfo(PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE, 0)) 1484 .when(() -> AudioManagerHelper.createAudioPatch(mFmTunerInputDevice, 1485 mCarAudioDeviceUtils.mMediaOutputDevice, DEFAULT_GAIN)); 1486 1487 CarAudioPatchHandle audioPatch = service 1488 .createAudioPatch(PRIMARY_ZONE_FM_TUNER_ADDRESS, USAGE_MEDIA, DEFAULT_GAIN); 1489 1490 expectWithMessage("Audio Patch Sink Address") 1491 .that(audioPatch.getSinkAddress()).isEqualTo(MEDIA_TEST_DEVICE); 1492 expectWithMessage("Audio Patch Source Address") 1493 .that(audioPatch.getSourceAddress()).isEqualTo(PRIMARY_ZONE_FM_TUNER_ADDRESS); 1494 expectWithMessage("Audio Patch Handle") 1495 .that(audioPatch.getHandleId()).isEqualTo(0); 1496 } 1497 1498 @Test releaseAudioPatch_failsForConfigurationMissing()1499 public void releaseAudioPatch_failsForConfigurationMissing() throws Exception { 1500 CarAudioService service = setUpAudioService(); 1501 1502 doReturn(false) 1503 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, false)); 1504 CarAudioPatchHandle carAudioPatchHandle = 1505 new CarAudioPatchHandle(0, PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE); 1506 1507 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1508 () -> service.releaseAudioPatch(carAudioPatchHandle)); 1509 1510 expectWithMessage("Release FM and Media Audio Patch Exception") 1511 .that(thrown).hasMessageThat().contains("Audio Patch APIs not enabled"); 1512 } 1513 1514 @Test releaseAudioPatch_failsForMissingPermission()1515 public void releaseAudioPatch_failsForMissingPermission() throws Exception { 1516 CarAudioService service = setUpAudioService(); 1517 1518 mockDenyCarControlAudioSettingsPermission(); 1519 CarAudioPatchHandle carAudioPatchHandle = 1520 new CarAudioPatchHandle(0, PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE); 1521 1522 SecurityException thrown = assertThrows(SecurityException.class, 1523 () -> service.releaseAudioPatch(carAudioPatchHandle)); 1524 1525 expectWithMessage("FM and Media Audio Patch Permission Exception") 1526 .that(thrown).hasMessageThat().contains(PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 1527 } 1528 1529 @Test releaseAudioPatch_forNullSourceAddress_throwsNullPointerException()1530 public void releaseAudioPatch_forNullSourceAddress_throwsNullPointerException() 1531 throws Exception { 1532 CarAudioService service = setUpAudioService(); 1533 mockGrantCarControlAudioSettingsPermission(); 1534 doReturn(new AudioPatchInfo(PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE, 0)) 1535 .when(() -> AudioManagerHelper.createAudioPatch(mFmTunerInputDevice, 1536 mCarAudioDeviceUtils.mMediaOutputDevice, DEFAULT_GAIN)); 1537 1538 CarAudioPatchHandle audioPatch = mock(CarAudioPatchHandle.class); 1539 when(audioPatch.getSourceAddress()).thenReturn(null); 1540 1541 NullPointerException thrown = assertThrows(NullPointerException.class, 1542 () -> service.releaseAudioPatch(audioPatch)); 1543 1544 expectWithMessage("Release audio patch for null source address " 1545 + "and sink address Null Exception") 1546 .that(thrown).hasMessageThat() 1547 .contains("Source Address can not be null for patch id 0"); 1548 } 1549 1550 @Test releaseAudioPatch_failsForNullPatch()1551 public void releaseAudioPatch_failsForNullPatch() throws Exception { 1552 CarAudioService service = setUpAudioService(); 1553 1554 assertThrows(NullPointerException.class, 1555 () -> service.releaseAudioPatch(null)); 1556 } 1557 1558 @Test setZoneIdForUid_withoutRoutingPermission_fails()1559 public void setZoneIdForUid_withoutRoutingPermission_fails() throws Exception { 1560 CarAudioService service = setUpAudioService(); 1561 1562 mockDenyCarControlAudioSettingsPermission(); 1563 1564 SecurityException thrown = assertThrows(SecurityException.class, 1565 () -> service.setZoneIdForUid(OUT_OF_RANGE_ZONE, MEDIA_APP_UID)); 1566 1567 expectWithMessage("Set Zone for UID Permission Exception") 1568 .that(thrown).hasMessageThat() 1569 .contains(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 1570 } 1571 1572 @Test setZoneIdForUid_withoutDynamicRouting_fails()1573 public void setZoneIdForUid_withoutDynamicRouting_fails() throws Exception { 1574 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1575 1576 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1577 () -> nonDynamicAudioService.setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID)); 1578 1579 expectWithMessage("Set Zone for UID Dynamic Configuration Exception") 1580 .that(thrown).hasMessageThat() 1581 .contains("Non legacy routing is required"); 1582 } 1583 1584 @Test setZoneIdForUid_withInvalidZone_fails()1585 public void setZoneIdForUid_withInvalidZone_fails() throws Exception { 1586 CarAudioService service = setUpAudioService(); 1587 1588 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 1589 () -> service.setZoneIdForUid(INVALID_AUDIO_ZONE, MEDIA_APP_UID)); 1590 1591 expectWithMessage("Set Zone for UID Invalid Zone Exception") 1592 .that(thrown).hasMessageThat() 1593 .contains("Invalid audio zone Id " + INVALID_AUDIO_ZONE); 1594 } 1595 1596 @Test setZoneIdForUid_withOutOfRangeZone_fails()1597 public void setZoneIdForUid_withOutOfRangeZone_fails() throws Exception { 1598 CarAudioService service = setUpAudioService(); 1599 1600 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 1601 () -> service.setZoneIdForUid(OUT_OF_RANGE_ZONE, MEDIA_APP_UID)); 1602 1603 expectWithMessage("Set Zone for UID Zone Out of Range Exception") 1604 .that(thrown).hasMessageThat() 1605 .contains("Invalid audio zone Id " + OUT_OF_RANGE_ZONE); 1606 } 1607 1608 @Test setZoneIdForUid_withZoneAudioMapping_fails()1609 public void setZoneIdForUid_withZoneAudioMapping_fails() throws Exception { 1610 CarAudioService service = setUpAudioService(); 1611 1612 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1613 () -> service.setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID)); 1614 1615 expectWithMessage("Set Zone for UID With Audio Zone Mapping Exception") 1616 .that(thrown).hasMessageThat() 1617 .contains("UID based routing is not supported while using occupant zone mapping"); 1618 } 1619 1620 @Test setZoneIdForUid_withValidZone_succeeds()1621 public void setZoneIdForUid_withValidZone_succeeds() throws Exception { 1622 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1623 1624 boolean results = noZoneMappingAudioService 1625 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1626 1627 expectWithMessage("Set Zone for UID Status").that(results).isTrue(); 1628 } 1629 1630 @Test setZoneIdForUid_onDifferentZones_succeeds()1631 public void setZoneIdForUid_onDifferentZones_succeeds() throws Exception { 1632 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1633 1634 noZoneMappingAudioService 1635 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1636 1637 boolean results = noZoneMappingAudioService 1638 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1639 1640 expectWithMessage("Set Zone for UID For Different Zone") 1641 .that(results).isTrue(); 1642 } 1643 1644 @Test setZoneIdForUid_onDifferentZones_withAudioFocus_succeeds()1645 public void setZoneIdForUid_onDifferentZones_withAudioFocus_succeeds() throws Exception { 1646 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1647 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(); 1648 1649 noZoneMappingAudioService 1650 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1651 1652 noZoneMappingAudioService 1653 .requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 1654 1655 boolean results = noZoneMappingAudioService 1656 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1657 1658 expectWithMessage("Set Zone for UID For Different Zone with Audio Focus") 1659 .that(results).isTrue(); 1660 } 1661 1662 @Test getZoneIdForUid_withoutMappedUid_succeeds()1663 public void getZoneIdForUid_withoutMappedUid_succeeds() throws Exception { 1664 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1665 1666 int zoneId = noZoneMappingAudioService 1667 .getZoneIdForUid(MEDIA_APP_UID); 1668 1669 expectWithMessage("Get Zone for Non Mapped UID") 1670 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1671 } 1672 1673 @Test getZoneIdForUid_succeeds()1674 public void getZoneIdForUid_succeeds() throws Exception { 1675 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1676 1677 noZoneMappingAudioService 1678 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1679 1680 int zoneId = noZoneMappingAudioService 1681 .getZoneIdForUid(MEDIA_APP_UID); 1682 1683 expectWithMessage("Get Zone for UID Zone Id") 1684 .that(zoneId).isEqualTo(TEST_REAR_LEFT_ZONE_ID); 1685 } 1686 1687 @Test getZoneIdForUid_afterSwitchingZones_succeeds()1688 public void getZoneIdForUid_afterSwitchingZones_succeeds() throws Exception { 1689 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1690 1691 noZoneMappingAudioService 1692 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1693 1694 noZoneMappingAudioService 1695 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1696 1697 int zoneId = noZoneMappingAudioService 1698 .getZoneIdForUid(MEDIA_APP_UID); 1699 1700 expectWithMessage("Get Zone for UID Zone Id") 1701 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1702 } 1703 1704 @Test clearZoneIdForUid_withoutRoutingPermission_fails()1705 public void clearZoneIdForUid_withoutRoutingPermission_fails() throws Exception { 1706 CarAudioService service = setUpAudioService(); 1707 1708 mockDenyCarControlAudioSettingsPermission(); 1709 1710 SecurityException thrown = assertThrows(SecurityException.class, 1711 () -> service.clearZoneIdForUid(MEDIA_APP_UID)); 1712 1713 expectWithMessage("Clear Zone for UID Permission Exception") 1714 .that(thrown).hasMessageThat() 1715 .contains(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 1716 } 1717 1718 @Test clearZoneIdForUid_withoutDynamicRouting_fails()1719 public void clearZoneIdForUid_withoutDynamicRouting_fails() throws Exception { 1720 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1721 1722 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1723 () -> nonDynamicAudioService.clearZoneIdForUid(MEDIA_APP_UID)); 1724 1725 expectWithMessage("Clear Zone for UID Dynamic Configuration Exception") 1726 .that(thrown).hasMessageThat() 1727 .contains("Non legacy routing is required"); 1728 } 1729 1730 @Test clearZoneIdForUid_withZoneAudioMapping_fails()1731 public void clearZoneIdForUid_withZoneAudioMapping_fails() throws Exception { 1732 CarAudioService service = setUpAudioService(); 1733 1734 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1735 () -> service.clearZoneIdForUid(MEDIA_APP_UID)); 1736 1737 expectWithMessage("Clear Zone for UID Audio Zone Mapping Exception") 1738 .that(thrown).hasMessageThat() 1739 .contains("UID based routing is not supported while using occupant zone mapping"); 1740 } 1741 1742 @Test clearZoneIdForUid_forNonMappedUid_succeeds()1743 public void clearZoneIdForUid_forNonMappedUid_succeeds() throws Exception { 1744 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1745 1746 boolean status = noZoneMappingAudioService 1747 .clearZoneIdForUid(MEDIA_APP_UID); 1748 1749 expectWithMessage("Clear Zone for UID Audio Zone without Mapping") 1750 .that(status).isTrue(); 1751 } 1752 1753 @Test clearZoneIdForUid_forMappedUid_succeeds()1754 public void clearZoneIdForUid_forMappedUid_succeeds() throws Exception { 1755 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1756 1757 noZoneMappingAudioService 1758 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1759 1760 boolean status = noZoneMappingAudioService.clearZoneIdForUid(MEDIA_APP_UID); 1761 1762 expectWithMessage("Clear Zone for UID Audio Zone with Mapping") 1763 .that(status).isTrue(); 1764 } 1765 1766 @Test getZoneIdForUid_afterClearedUidMapping_returnsDefaultZone()1767 public void getZoneIdForUid_afterClearedUidMapping_returnsDefaultZone() throws Exception { 1768 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1769 1770 noZoneMappingAudioService 1771 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1772 1773 noZoneMappingAudioService.clearZoneIdForUid(MEDIA_APP_UID); 1774 1775 int zoneId = noZoneMappingAudioService.getZoneIdForUid(MEDIA_APP_UID); 1776 1777 expectWithMessage("Get Zone for UID Audio Zone with Cleared Mapping") 1778 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1779 } 1780 1781 @Test getZoneIdForAudioFocusInfo_withoutMappedUid_succeeds()1782 public void getZoneIdForAudioFocusInfo_withoutMappedUid_succeeds() throws Exception { 1783 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1784 1785 int zoneId = noZoneMappingAudioService 1786 .getZoneIdForAudioFocusInfo(TEST_AUDIO_FOCUS_INFO); 1787 1788 expectWithMessage("Mapped audio focus info's zone") 1789 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1790 } 1791 1792 @Test getZoneIdForAudioFocusInfo_succeeds()1793 public void getZoneIdForAudioFocusInfo_succeeds() throws Exception { 1794 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1795 1796 noZoneMappingAudioService 1797 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1798 1799 int zoneId = noZoneMappingAudioService 1800 .getZoneIdForAudioFocusInfo(TEST_AUDIO_FOCUS_INFO); 1801 1802 expectWithMessage("Mapped audio focus info's zone") 1803 .that(zoneId).isEqualTo(TEST_REAR_LEFT_ZONE_ID); 1804 } 1805 1806 @Test getZoneIdForAudioFocusInfo_afterSwitchingZones_succeeds()1807 public void getZoneIdForAudioFocusInfo_afterSwitchingZones_succeeds() throws Exception { 1808 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 1809 noZoneMappingAudioService 1810 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1811 noZoneMappingAudioService 1812 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1813 1814 int zoneId = noZoneMappingAudioService 1815 .getZoneIdForAudioFocusInfo(TEST_AUDIO_FOCUS_INFO); 1816 1817 expectWithMessage("Remapped audio focus info's zone") 1818 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1819 } 1820 1821 @Test setGroupVolume_withoutPermission_fails()1822 public void setGroupVolume_withoutPermission_fails() throws Exception { 1823 CarAudioService service = setUpAudioService(); 1824 1825 mockDenyCarControlAudioVolumePermission(); 1826 1827 SecurityException thrown = assertThrows(SecurityException.class, 1828 () -> service.setGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1829 TEST_GAIN_INDEX, TEST_FLAGS)); 1830 1831 expectWithMessage("Set Volume Group Permission Exception") 1832 .that(thrown).hasMessageThat() 1833 .contains(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME); 1834 } 1835 1836 @Test setGroupVolume_withDynamicRoutingDisabled()1837 public void setGroupVolume_withDynamicRoutingDisabled() throws Exception { 1838 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1839 1840 nonDynamicAudioService.setGroupVolume( 1841 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, TEST_GAIN_INDEX, TEST_FLAGS); 1842 1843 verify(mAudioManager).setStreamVolume( 1844 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0], 1845 TEST_GAIN_INDEX, 1846 TEST_FLAGS); 1847 } 1848 1849 @Test setGroupVolume_verifyNoCallbacks()1850 public void setGroupVolume_verifyNoCallbacks() throws Exception { 1851 CarAudioService service = setUpAudioService(); 1852 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1853 /* mute= */ false, TEST_FLAGS); 1854 reset(mCarVolumeCallbackHandler); 1855 1856 service.setGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1857 TEST_GAIN_INDEX, TEST_FLAGS); 1858 1859 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 1860 } 1861 1862 @Test setGroupVolume_afterSetVolumeGroupMute()1863 public void setGroupVolume_afterSetVolumeGroupMute() throws Exception { 1864 CarAudioService service = setUpAudioService(); 1865 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1866 /* mute= */ true, TEST_FLAGS); 1867 reset(mCarVolumeCallbackHandler); 1868 1869 service.setGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1870 TEST_GAIN_INDEX, TEST_FLAGS); 1871 1872 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 1873 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 1874 } 1875 1876 @Test setGroupVolume_withVolumeGroupMutingDisabled_doesnotThrowException()1877 public void setGroupVolume_withVolumeGroupMutingDisabled_doesnotThrowException() 1878 throws Exception { 1879 CarAudioService nonVolumeGroupMutingAudioService = 1880 setUpAudioServiceWithDisabledResource(audioUseCarVolumeGroupMuting); 1881 HalAudioGainCallback callback = getHalAudioGainCallback(); 1882 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(PRIMARY_AUDIO_ZONE, 1883 MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 1884 callback.onAudioDeviceGainsChanged(List.of(Reasons.TCU_MUTE), List.of(carGain)); 1885 reset(mCarVolumeCallbackHandler); 1886 1887 nonVolumeGroupMutingAudioService.setGroupVolume( 1888 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, TEST_GAIN_INDEX, TEST_FLAGS); 1889 1890 // if an exception is thrown, the test automatically fails 1891 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 1892 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 1893 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 1894 } 1895 1896 @Test getOutputDeviceAddressForUsage_forMusicUsage()1897 public void getOutputDeviceAddressForUsage_forMusicUsage() throws Exception { 1898 CarAudioService service = setUpAudioService(); 1899 1900 String mediaDeviceAddress = 1901 service.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, USAGE_MEDIA); 1902 1903 expectWithMessage("Media usage audio device address") 1904 .that(mediaDeviceAddress).isEqualTo(MEDIA_TEST_DEVICE); 1905 } 1906 1907 @Test getOutputDeviceAddressForUsage_withNonDynamicRouting_forMediaUsage_fails()1908 public void getOutputDeviceAddressForUsage_withNonDynamicRouting_forMediaUsage_fails() 1909 throws Exception { 1910 when(mMockResources.getBoolean(audioUseCoreRouting)).thenReturn(false); 1911 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 1912 1913 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1914 () -> nonDynamicAudioService 1915 .getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, USAGE_MEDIA)); 1916 1917 expectWithMessage("Non dynamic routing media usage audio device address exception") 1918 .that(thrown).hasMessageThat().contains("Non legacy routing is required"); 1919 } 1920 1921 @Test getOutputDeviceAddressForUsage_forNavigationUsage()1922 public void getOutputDeviceAddressForUsage_forNavigationUsage() throws Exception { 1923 CarAudioService service = setUpAudioService(); 1924 1925 String mediaDeviceAddress = 1926 service.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, 1927 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE); 1928 1929 expectWithMessage("Navigation usage audio device address") 1930 .that(mediaDeviceAddress).isEqualTo(NAVIGATION_TEST_DEVICE); 1931 } 1932 1933 @Test getOutputDeviceAddressForUsage_forInvalidUsage_fails()1934 public void getOutputDeviceAddressForUsage_forInvalidUsage_fails() throws Exception { 1935 CarAudioService service = setUpAudioService(); 1936 1937 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> 1938 service.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, 1939 INVALID_USAGE)); 1940 1941 expectWithMessage("Invalid usage audio device address exception") 1942 .that(thrown).hasMessageThat().contains("Invalid audio attribute " + INVALID_USAGE); 1943 } 1944 1945 @Test getOutputDeviceAddressForUsage_forVirtualUsage_fails()1946 public void getOutputDeviceAddressForUsage_forVirtualUsage_fails() throws Exception { 1947 CarAudioService service = setUpAudioService(); 1948 1949 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> 1950 service.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, 1951 AudioManagerHelper.getUsageVirtualSource())); 1952 1953 expectWithMessage("Invalid context audio device address exception") 1954 .that(thrown).hasMessageThat() 1955 .contains("invalid"); 1956 } 1957 1958 @Test getOutputDeviceAddressForUsage_onSecondaryZone_forMusicUsage()1959 public void getOutputDeviceAddressForUsage_onSecondaryZone_forMusicUsage() throws Exception { 1960 CarAudioService service = setUpAudioService(); 1961 1962 String mediaDeviceAddress = service.getOutputDeviceAddressForUsage( 1963 TEST_REAR_LEFT_ZONE_ID, USAGE_MEDIA); 1964 1965 expectWithMessage("Media usage audio device address for secondary zone") 1966 .that(mediaDeviceAddress).isEqualTo(SECONDARY_TEST_DEVICE_CONFIG_0); 1967 } 1968 1969 @Test getSuggestedAudioContextForZone_inPrimaryZone()1970 public void getSuggestedAudioContextForZone_inPrimaryZone() throws Exception { 1971 CarAudioService service = setUpAudioService(); 1972 int defaultAudioContext = service.getCarAudioContext() 1973 .getContextForAudioAttribute(CAR_DEFAULT_AUDIO_ATTRIBUTE); 1974 1975 expectWithMessage("Suggested audio context for primary zone") 1976 .that(service.getSuggestedAudioContextForZone(PRIMARY_AUDIO_ZONE)) 1977 .isEqualTo(defaultAudioContext); 1978 } 1979 1980 @Test getSuggestedAudioContextForZone_inSecondaryZone()1981 public void getSuggestedAudioContextForZone_inSecondaryZone() throws Exception { 1982 CarAudioService service = setUpAudioService(); 1983 int defaultAudioContext = service.getCarAudioContext() 1984 .getContextForAudioAttribute(CAR_DEFAULT_AUDIO_ATTRIBUTE); 1985 1986 expectWithMessage("Suggested audio context for secondary zone") 1987 .that(service.getSuggestedAudioContextForZone(TEST_REAR_LEFT_ZONE_ID)) 1988 .isEqualTo(defaultAudioContext); 1989 } 1990 1991 @Test getSuggestedAudioContextForZone_inInvalidZone()1992 public void getSuggestedAudioContextForZone_inInvalidZone() throws Exception { 1993 CarAudioService service = setUpAudioService(); 1994 1995 expectWithMessage("Suggested audio context for invalid zone") 1996 .that(service.getSuggestedAudioContextForZone(INVALID_AUDIO_ZONE)) 1997 .isEqualTo(CarAudioContext.getInvalidContext()); 1998 } 1999 2000 @Test isVolumeGroupMuted_noSetVolumeGroupMute()2001 public void isVolumeGroupMuted_noSetVolumeGroupMute() throws Exception { 2002 CarAudioService service = setUpAudioService(); 2003 2004 expectWithMessage("Volume group mute for default state") 2005 .that(service.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 2006 TEST_PRIMARY_ZONE_GROUP_0)).isFalse(); 2007 } 2008 2009 @Test isVolumeGroupMuted_setVolumeGroupMuted_isFalse()2010 public void isVolumeGroupMuted_setVolumeGroupMuted_isFalse() throws Exception { 2011 CarAudioService service = setUpAudioService(); 2012 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 2013 /* mute= */ true, TEST_FLAGS); 2014 2015 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 2016 /* mute= */ false, TEST_FLAGS); 2017 2018 expectWithMessage("Volume group muted after mute and unmute") 2019 .that(service.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 2020 TEST_PRIMARY_ZONE_GROUP_0)).isFalse(); 2021 } 2022 2023 @Test isVolumeGroupMuted_setVolumeGroupMuted_isTrue()2024 public void isVolumeGroupMuted_setVolumeGroupMuted_isTrue() throws Exception { 2025 CarAudioService service = setUpAudioService(); 2026 2027 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 2028 /* mute= */ true, TEST_FLAGS); 2029 expectWithMessage("Volume group muted after mute") 2030 .that(service.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 2031 TEST_PRIMARY_ZONE_GROUP_0)).isTrue(); 2032 } 2033 2034 @Test isVolumeGroupMuted_withVolumeGroupMutingDisabled()2035 public void isVolumeGroupMuted_withVolumeGroupMutingDisabled() throws Exception { 2036 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)).thenReturn(false); 2037 CarAudioService nonVolumeGroupMutingAudioService = 2038 setUpAudioServiceWithDisabledResource(audioUseCarVolumeGroupMuting); 2039 2040 expectWithMessage("Volume group for disabled volume group muting") 2041 .that(nonVolumeGroupMutingAudioService.isVolumeGroupMuted( 2042 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 2043 .isFalse(); 2044 } 2045 2046 @Test getGroupMaxVolume_forPrimaryZone()2047 public void getGroupMaxVolume_forPrimaryZone() throws Exception { 2048 CarAudioService service = setUpAudioService(); 2049 2050 expectWithMessage("Group max volume for primary audio zone and group") 2051 .that(service.getGroupMaxVolume(PRIMARY_AUDIO_ZONE, 2052 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo((MAX_GAIN - MIN_GAIN) / STEP_SIZE); 2053 } 2054 2055 @Test getGroupMinVolume_forPrimaryZone()2056 public void getGroupMinVolume_forPrimaryZone() throws Exception { 2057 CarAudioService service = setUpAudioService(); 2058 2059 expectWithMessage("Group Min Volume for primary audio zone and group") 2060 .that(service.getGroupMinVolume(PRIMARY_AUDIO_ZONE, 2061 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(0); 2062 } 2063 2064 @Test getGroupCurrentVolume_forPrimaryZone()2065 public void getGroupCurrentVolume_forPrimaryZone() throws Exception { 2066 CarAudioService service = setUpAudioService(); 2067 2068 expectWithMessage("Current group volume for primary audio zone and group") 2069 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 2070 TEST_PRIMARY_ZONE_GROUP_0)) 2071 .isEqualTo((DEFAULT_GAIN - MIN_GAIN) / STEP_SIZE); 2072 } 2073 2074 @Test getGroupMaxVolume_withNoDynamicRouting()2075 public void getGroupMaxVolume_withNoDynamicRouting() throws Exception { 2076 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 2077 2078 nonDynamicAudioService.getGroupMaxVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 2079 2080 verify(mAudioManager).getStreamMaxVolume( 2081 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0]); 2082 } 2083 2084 @Test getGroupMinVolume_withNoDynamicRouting()2085 public void getGroupMinVolume_withNoDynamicRouting() throws Exception { 2086 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 2087 2088 nonDynamicAudioService.getGroupMinVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 2089 2090 verify(mAudioManager).getStreamMinVolume( 2091 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0]); 2092 } 2093 2094 @Test getGroupCurrentVolume_withNoDynamicRouting()2095 public void getGroupCurrentVolume_withNoDynamicRouting() throws Exception { 2096 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 2097 2098 nonDynamicAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 2099 2100 verify(mAudioManager).getStreamVolume( 2101 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0]); 2102 } 2103 2104 @Test setBalanceTowardRight_nonNullValue()2105 public void setBalanceTowardRight_nonNullValue() throws Exception { 2106 CarAudioService service = setUpAudioService(); 2107 2108 service.setBalanceTowardRight(TEST_VALUE); 2109 2110 verify(mAudioControlWrapperAidl).setBalanceTowardRight(TEST_VALUE); 2111 } 2112 2113 @Test setBalanceTowardRight_throws()2114 public void setBalanceTowardRight_throws() throws Exception { 2115 CarAudioService service = setUpAudioService(); 2116 2117 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () 2118 -> service.setBalanceTowardRight(INVALID_TEST_VALUE)); 2119 2120 expectWithMessage("Out of bounds balance") 2121 .that(thrown).hasMessageThat() 2122 .contains(String.format("Balance is out of range of [%f, %f]", -1f, 1f)); 2123 } 2124 2125 @Test setFadeTowardFront_nonNullValue()2126 public void setFadeTowardFront_nonNullValue() throws Exception { 2127 CarAudioService service = setUpAudioService(); 2128 2129 service.setFadeTowardFront(TEST_VALUE); 2130 2131 verify(mAudioControlWrapperAidl).setFadeTowardFront(TEST_VALUE); 2132 } 2133 2134 @Test setFadeTowardFront_throws()2135 public void setFadeTowardFront_throws() throws Exception { 2136 CarAudioService service = setUpAudioService(); 2137 2138 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () 2139 -> service.setFadeTowardFront(INVALID_TEST_VALUE)); 2140 2141 expectWithMessage("Out of bounds fade") 2142 .that(thrown).hasMessageThat() 2143 .contains(String.format("Fade is out of range of [%f, %f]", -1f, 1f)); 2144 } 2145 2146 @Test isAudioFeatureEnabled_forDynamicRouting()2147 public void isAudioFeatureEnabled_forDynamicRouting() throws Exception { 2148 CarAudioService service = setUpAudioService(); 2149 2150 expectWithMessage("Dynamic routing audio feature") 2151 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_DYNAMIC_ROUTING)) 2152 .isEqualTo(mUseDynamicRouting); 2153 } 2154 2155 @Test isAudioFeatureEnabled_forDisabledDynamicRouting()2156 public void isAudioFeatureEnabled_forDisabledDynamicRouting() throws Exception { 2157 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 2158 2159 expectWithMessage("Disabled dynamic routing audio feature") 2160 .that(nonDynamicAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_DYNAMIC_ROUTING)) 2161 .isFalse(); 2162 } 2163 2164 @Test isAudioFeatureEnabled_forVolumeGroupMuting()2165 public void isAudioFeatureEnabled_forVolumeGroupMuting() throws Exception { 2166 CarAudioService service = setUpAudioService(); 2167 2168 expectWithMessage("Group muting audio feature") 2169 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_MUTING)) 2170 .isEqualTo(mUseCarVolumeGroupMuting); 2171 } 2172 2173 @Test isAudioFeatureEnabled_forDisabledVolumeGroupMuting()2174 public void isAudioFeatureEnabled_forDisabledVolumeGroupMuting() throws Exception { 2175 CarAudioService nonVolumeGroupMutingAudioService = 2176 setUpAudioServiceWithDisabledResource(audioUseCarVolumeGroupMuting); 2177 2178 expectWithMessage("Disabled group muting audio feature") 2179 .that(nonVolumeGroupMutingAudioService 2180 .isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_MUTING)) 2181 .isFalse(); 2182 } 2183 2184 @Test isAudioFeatureEnabled_forVolumeGroupEvent()2185 public void isAudioFeatureEnabled_forVolumeGroupEvent() throws Exception { 2186 CarAudioService service = setUpAudioService(); 2187 2188 expectWithMessage("Group events audio feature") 2189 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_EVENTS)) 2190 .isEqualTo(mUseCarVolumeGroupEvents); 2191 } 2192 2193 @Test isAudioFeatureEnabled_forDisabledVolumeGroupEvent()2194 public void isAudioFeatureEnabled_forDisabledVolumeGroupEvent() throws Exception { 2195 CarAudioService nonVolumeGroupEventsAudioService = 2196 setUpAudioServiceWithDisabledResource(audioUseCarVolumeGroupEvent); 2197 2198 expectWithMessage("Disabled group event audio feature") 2199 .that(nonVolumeGroupEventsAudioService 2200 .isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_EVENTS)) 2201 .isFalse(); 2202 } 2203 2204 @Test isAudioFeatureEnabled_forUnrecognizableAudioFeature_throws()2205 public void isAudioFeatureEnabled_forUnrecognizableAudioFeature_throws() throws Exception { 2206 CarAudioService service = setUpAudioService(); 2207 2208 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 2209 () -> service.isAudioFeatureEnabled(INVALID_AUDIO_FEATURE)); 2210 2211 expectWithMessage("Unknown audio feature") 2212 .that(thrown).hasMessageThat() 2213 .contains("Unknown Audio Feature type: " + INVALID_AUDIO_FEATURE); 2214 } 2215 2216 @Test isAudioFeatureEnabled_forDisabledOemService()2217 public void isAudioFeatureEnabled_forDisabledOemService() throws Exception { 2218 CarAudioService service = setUpAudioService(); 2219 2220 boolean isEnabled = 2221 service.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 2222 2223 expectWithMessage("Oem service enabled with disabled oem service") 2224 .that(isEnabled).isFalse(); 2225 } 2226 2227 @Test isAudioFeatureEnabled_withEnabledFocusService()2228 public void isAudioFeatureEnabled_withEnabledFocusService() throws Exception { 2229 CarOemAudioFocusProxyService focusProxyService = mock(CarOemAudioFocusProxyService.class); 2230 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(true); 2231 when(mMockCarOemProxyService.getCarOemAudioFocusService()).thenReturn(focusProxyService); 2232 CarAudioService service = setUpAudioService(); 2233 2234 boolean isEnabled = 2235 service.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 2236 2237 expectWithMessage("Oem service enabled with enabled focus service") 2238 .that(isEnabled).isTrue(); 2239 } 2240 2241 @Test isAudioFeatureEnabled_withEnabledVolumeService()2242 public void isAudioFeatureEnabled_withEnabledVolumeService() throws Exception { 2243 CarOemAudioVolumeProxyService volumeProxyService = 2244 mock(CarOemAudioVolumeProxyService.class); 2245 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(true); 2246 when(mMockCarOemProxyService.getCarOemAudioVolumeService()).thenReturn(volumeProxyService); 2247 CarAudioService service = setUpAudioService(); 2248 2249 boolean isEnabled = 2250 service.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 2251 2252 expectWithMessage("Oem service enabled with enabled volume service") 2253 .that(isEnabled).isTrue(); 2254 } 2255 2256 @Test isAudioFeatureEnabled_withEnabledDuckingService()2257 public void isAudioFeatureEnabled_withEnabledDuckingService() throws Exception { 2258 CarOemAudioDuckingProxyService duckingProxyService = 2259 mock(CarOemAudioDuckingProxyService.class); 2260 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(true); 2261 when(mMockCarOemProxyService.getCarOemAudioDuckingService()) 2262 .thenReturn(duckingProxyService); 2263 CarAudioService service = setUpAudioService(); 2264 2265 boolean isEnabled = service.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 2266 2267 expectWithMessage("Oem service enabled with enabled ducking service") 2268 .that(isEnabled).isTrue(); 2269 } 2270 2271 @Test isAudioFeatureEnabled_withEnabledAudioMirror()2272 public void isAudioFeatureEnabled_withEnabledAudioMirror() throws Exception { 2273 CarAudioService service = setUpAudioService(); 2274 2275 boolean isEnabled = service.isAudioFeatureEnabled(AUDIO_FEATURE_AUDIO_MIRRORING); 2276 2277 expectWithMessage("Audio mirror enabled status") 2278 .that(isEnabled).isTrue(); 2279 } 2280 2281 @Test isAudioFeatureEnabled_withDisabledAudioMirror()2282 public void isAudioFeatureEnabled_withDisabledAudioMirror() throws Exception { 2283 CarAudioService service = setUpCarAudioServiceWithoutMirroring(); 2284 2285 boolean isEnabled = service.isAudioFeatureEnabled(AUDIO_FEATURE_AUDIO_MIRRORING); 2286 2287 expectWithMessage("Audio mirror enabled status") 2288 .that(isEnabled).isFalse(); 2289 } 2290 2291 @Test isAudioFeatureEnabled_forMinMaxActivationVolume()2292 public void isAudioFeatureEnabled_forMinMaxActivationVolume() throws Exception { 2293 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 2294 CarAudioService service = setUpAudioService(); 2295 2296 expectWithMessage("Min/max activation volume feature") 2297 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_MIN_MAX_ACTIVATION_VOLUME)) 2298 .isEqualTo(mUseMinMaxActivationVolume); 2299 } 2300 2301 @Test isAudioFeatureEnabled_forDisabledMinMaxActivationVolume()2302 public void isAudioFeatureEnabled_forDisabledMinMaxActivationVolume() throws Exception { 2303 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 2304 CarAudioService nonMinMaxActivationVolumeAudioService = 2305 setUpAudioServiceWithDisabledResource(audioUseMinMaxActivationVolume); 2306 2307 expectWithMessage("Disabled min/max activation volume feature") 2308 .that(nonMinMaxActivationVolumeAudioService 2309 .isAudioFeatureEnabled(AUDIO_FEATURE_MIN_MAX_ACTIVATION_VOLUME)) 2310 .isFalse(); 2311 } 2312 2313 @Test isAudioFeatureEnabled_forMinMaxActivationVolumeWithDisabledFlag()2314 public void isAudioFeatureEnabled_forMinMaxActivationVolumeWithDisabledFlag() throws Exception { 2315 mSetFlagsRule.disableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 2316 CarAudioService service = setUpAudioService(); 2317 2318 expectWithMessage("Min/max activation volume feature with disabled feature flag") 2319 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_MIN_MAX_ACTIVATION_VOLUME)) 2320 .isFalse(); 2321 } 2322 2323 @Test 2324 @EnableFlags({Flags.FLAG_AUDIO_FADE_BALANCE_GETTER_APIS}) isAudioFeatureEnabled_forEnabledPersistFadeBalance()2325 public void isAudioFeatureEnabled_forEnabledPersistFadeBalance() throws Exception { 2326 CarAudioService service = setUpAudioService(); 2327 2328 expectWithMessage("Persist fade balance values feature") 2329 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_PERSIST_FADE_BALANCE_VALUES)) 2330 .isTrue(); 2331 } 2332 2333 @Test 2334 @EnableFlags({Flags.FLAG_AUDIO_FADE_BALANCE_GETTER_APIS}) isAudioFeatureEnabled_forDisabledPersistFadeBalance()2335 public void isAudioFeatureEnabled_forDisabledPersistFadeBalance() throws Exception { 2336 CarAudioService service = 2337 setUpAudioServiceWithDisabledResource(audioPersistFadeBalanceLevels); 2338 2339 expectWithMessage("Disabled persist fade balance values feature") 2340 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_PERSIST_FADE_BALANCE_VALUES)) 2341 .isFalse(); 2342 } 2343 2344 @Test 2345 @EnableFlags({Flags.FLAG_AUDIO_FADE_BALANCE_GETTER_APIS}) isAudioFeatureEnabled_forPersistFadeBalance_whenDisabledDynamicRouting()2346 public void isAudioFeatureEnabled_forPersistFadeBalance_whenDisabledDynamicRouting() 2347 throws Exception { 2348 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 2349 2350 expectWithMessage("Persist fade balance feature when dynamic routing disabled") 2351 .that(nonDynamicAudioService 2352 .isAudioFeatureEnabled(AUDIO_FEATURE_PERSIST_FADE_BALANCE_VALUES)) 2353 .isFalse(); 2354 } 2355 2356 @Test 2357 @DisableFlags({Flags.FLAG_AUDIO_FADE_BALANCE_GETTER_APIS}) isAudioFeatureEnabled_forDisabledFadeBalanceGetterFlags()2358 public void isAudioFeatureEnabled_forDisabledFadeBalanceGetterFlags() throws Exception { 2359 CarAudioService service = setUpAudioService(); 2360 2361 expectWithMessage("Disabled fade balance getter apis flag") 2362 .that(service.isAudioFeatureEnabled(AUDIO_FEATURE_PERSIST_FADE_BALANCE_VALUES)) 2363 .isFalse(); 2364 } 2365 2366 @Test onOccupantZoneConfigChanged_noUserAssignedToPrimaryZone()2367 public void onOccupantZoneConfigChanged_noUserAssignedToPrimaryZone() throws Exception { 2368 CarAudioService service = setUpAudioService(); 2369 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(UserManagerHelper.USER_NULL); 2370 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 2371 .thenReturn(UserManagerHelper.USER_NULL); 2372 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2373 int prevUserId = service.getUserIdForZone(PRIMARY_AUDIO_ZONE); 2374 2375 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2376 2377 expectWithMessage("User ID before config changed") 2378 .that(service.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2379 .isEqualTo(prevUserId); 2380 } 2381 2382 @Test onOccupantZoneConfigChanged_userAssignedToPrimaryZone()2383 public void onOccupantZoneConfigChanged_userAssignedToPrimaryZone() throws Exception { 2384 CarAudioService service = setUpAudioService(); 2385 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2386 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 2387 .thenReturn(TEST_REAR_LEFT_USER_ID); 2388 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2389 2390 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2391 2392 expectWithMessage("User ID after config changed") 2393 .that(service.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2394 .isEqualTo(TEST_REAR_LEFT_USER_ID); 2395 } 2396 2397 @Test onOccupantZoneConfigChanged_afterResettingUser_returnNoUser()2398 public void onOccupantZoneConfigChanged_afterResettingUser_returnNoUser() throws Exception { 2399 CarAudioService service = setUpAudioService(); 2400 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2401 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 2402 .thenReturn(TEST_REAR_LEFT_USER_ID); 2403 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2404 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2405 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 2406 .thenReturn(UserManagerHelper.USER_NULL); 2407 2408 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2409 2410 expectWithMessage("User ID config changed to null") 2411 .that(service.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2412 .isEqualTo(UserManagerHelper.USER_NULL); 2413 } 2414 2415 @Test onOccupantZoneConfigChanged_noOccupantZoneMapping()2416 public void onOccupantZoneConfigChanged_noOccupantZoneMapping() throws Exception { 2417 setUpCarAudioServiceWithoutZoneMapping(); 2418 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2419 2420 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2421 2422 verify(mMockOccupantZoneService, never()).getUserForOccupant(anyInt()); 2423 } 2424 2425 @Test onOccupantZoneConfigChanged_noOccupantZoneMapping_alreadyAssigned()2426 public void onOccupantZoneConfigChanged_noOccupantZoneMapping_alreadyAssigned() 2427 throws Exception { 2428 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2429 CarAudioService noZoneMappingAudioService = setUpCarAudioServiceWithoutZoneMapping(); 2430 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2431 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2432 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2433 2434 verify(mMockOccupantZoneService, never()).getUserForOccupant(anyInt()); 2435 expectWithMessage("Occupant Zone for primary zone") 2436 .that(noZoneMappingAudioService.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2437 .isEqualTo(TEST_DRIVER_USER_ID); 2438 } 2439 2440 @Test onOccupantZoneConfigChanged_multipleZones()2441 public void onOccupantZoneConfigChanged_multipleZones() throws Exception { 2442 CarAudioService service = setUpAudioService(); 2443 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2444 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 2445 .thenReturn(TEST_REAR_LEFT_USER_ID, TEST_REAR_RIGHT_USER_ID); 2446 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2447 2448 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2449 2450 expectWithMessage("User ID for primary and secondary zone after config changed") 2451 .that(service.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2452 .isNotEqualTo(service.getUserIdForZone(TEST_REAR_LEFT_ZONE_ID)); 2453 expectWithMessage("Secondary user ID config changed") 2454 .that(service.getUserIdForZone(TEST_REAR_LEFT_ZONE_ID)) 2455 .isEqualTo(TEST_REAR_RIGHT_USER_ID); 2456 } 2457 2458 @Test init_forUserAlreadySetup_callsInternalConfigChange()2459 public void init_forUserAlreadySetup_callsInternalConfigChange() throws Exception { 2460 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2461 when(mMockOccupantZoneService.getUserForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 2462 .thenReturn(TEST_DRIVER_USER_ID); 2463 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 2464 .thenReturn(TEST_REAR_RIGHT_USER_ID); 2465 CarAudioService service = setUpAudioServiceWithoutInit(); 2466 2467 initServiceAndWaitForComplete(service); 2468 2469 waitForInternalCallback(); 2470 expectWithMessage("User ID for primary zone for user available at init") 2471 .that(service.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2472 .isEqualTo(TEST_DRIVER_USER_ID); 2473 expectWithMessage("User ID secondary zone for user available at init") 2474 .that(service.getUserIdForZone(TEST_REAR_RIGHT_ZONE_ID)) 2475 .isEqualTo(TEST_REAR_RIGHT_USER_ID); 2476 } 2477 2478 @Test init_withAudioModuleCallbackFeatureDisabled()2479 public void init_withAudioModuleCallbackFeatureDisabled() throws Exception { 2480 when(mAudioControlWrapperAidl.supportsFeature( 2481 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_MODULE_CALLBACK)).thenReturn(false); 2482 2483 setUpAudioService(); 2484 2485 verify(mAudioControlWrapperAidl, never()).setModuleChangeCallback(any()); 2486 } 2487 2488 @Test init_withAudioFocusFeatureDisabled()2489 public void init_withAudioFocusFeatureDisabled() throws Exception { 2490 when(mAudioControlWrapperAidl.supportsFeature( 2491 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_FOCUS)).thenReturn(false); 2492 2493 setUpAudioService(); 2494 2495 verify(mAudioControlWrapperAidl, never()).registerFocusListener(any()); 2496 } 2497 2498 @Test init_withAudioGainCallbackFeatureDisabled()2499 public void init_withAudioGainCallbackFeatureDisabled() throws Exception { 2500 when(mAudioControlWrapperAidl.supportsFeature( 2501 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_GAIN_CALLBACK)).thenReturn(false); 2502 2503 setUpAudioService(); 2504 2505 verify(mAudioControlWrapperAidl, never()).registerAudioGainCallback(any()); 2506 } 2507 2508 @Test serviceDied_registersAudioGainCallback()2509 public void serviceDied_registersAudioGainCallback() throws Exception { 2510 setUpAudioService(); 2511 ArgumentCaptor<AudioControlDeathRecipient> captor = 2512 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2513 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2514 AudioControlDeathRecipient runnable = captor.getValue(); 2515 reset(mAudioControlWrapperAidl); 2516 2517 runnable.serviceDied(); 2518 2519 verify(mAudioControlWrapperAidl).registerAudioGainCallback(any()); 2520 } 2521 2522 @Test serviceDied_withNullAudioGainCallback()2523 public void serviceDied_withNullAudioGainCallback() throws Exception { 2524 when(mAudioControlWrapperAidl.supportsFeature( 2525 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_GAIN_CALLBACK)).thenReturn(false); 2526 setUpAudioService(); 2527 ArgumentCaptor<AudioControlDeathRecipient> captor = 2528 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2529 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2530 AudioControlDeathRecipient runnable = captor.getValue(); 2531 reset(mAudioControlWrapperAidl); 2532 2533 runnable.serviceDied(); 2534 2535 verify(mAudioControlWrapperAidl, never()).registerAudioGainCallback(any()); 2536 } 2537 2538 @Test serviceDied_registersFocusListener()2539 public void serviceDied_registersFocusListener() throws Exception { 2540 setUpAudioService(); 2541 ArgumentCaptor<AudioControlDeathRecipient> captor = 2542 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2543 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2544 AudioControlDeathRecipient runnable = captor.getValue(); 2545 reset(mAudioControlWrapperAidl); 2546 2547 runnable.serviceDied(); 2548 2549 verify(mAudioControlWrapperAidl).registerFocusListener(any()); 2550 } 2551 2552 @Test serviceDied_withAudioServerNotRunning()2553 public void serviceDied_withAudioServerNotRunning() throws Exception { 2554 setUpAudioService(); 2555 ArgumentCaptor<AudioControlDeathRecipient> captor = 2556 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2557 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2558 AudioControlDeathRecipient runnable = captor.getValue(); 2559 reset(mAudioControlWrapperAidl); 2560 when(mAudioManager.isAudioServerRunning()).thenReturn(false); 2561 2562 runnable.serviceDied(); 2563 2564 verify(mAudioControlWrapperAidl, never()).registerAudioGainCallback(any()); 2565 verify(mAudioControlWrapperAidl, never()).registerFocusListener(any()); 2566 } 2567 2568 @Test serviceDied_withAudioServerDown()2569 public void serviceDied_withAudioServerDown() throws Exception { 2570 CarAudioService service = setUpAudioService(); 2571 ArgumentCaptor<AudioControlDeathRecipient> captor = 2572 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2573 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2574 AudioControlDeathRecipient runnable = captor.getValue(); 2575 reset(mAudioControlWrapperAidl); 2576 service.releaseAudioCallbacks(/* isAudioServerDown= */ true); 2577 2578 runnable.serviceDied(); 2579 2580 verify(mAudioControlWrapperAidl, never()).registerAudioGainCallback(any()); 2581 verify(mAudioControlWrapperAidl, never()).registerFocusListener(any()); 2582 verify(mAudioControlWrapperAidl, never()).setModuleChangeCallback(any()); 2583 } 2584 2585 @Test serviceDied_setsModuleChangeCallback()2586 public void serviceDied_setsModuleChangeCallback() throws Exception { 2587 setUpAudioService(); 2588 ArgumentCaptor<AudioControlDeathRecipient> captor = 2589 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2590 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2591 AudioControlDeathRecipient runnable = captor.getValue(); 2592 reset(mAudioControlWrapperAidl); 2593 2594 runnable.serviceDied(); 2595 2596 verify(mAudioControlWrapperAidl).setModuleChangeCallback(any()); 2597 } 2598 2599 @Test serviceDied_withNullModuleChangeCallback()2600 public void serviceDied_withNullModuleChangeCallback() throws Exception { 2601 when(mAudioControlWrapperAidl.supportsFeature( 2602 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_MODULE_CALLBACK)).thenReturn(false); 2603 setUpAudioService(); 2604 ArgumentCaptor<AudioControlDeathRecipient> captor = 2605 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2606 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2607 AudioControlDeathRecipient runnable = captor.getValue(); 2608 reset(mAudioControlWrapperAidl); 2609 2610 runnable.serviceDied(); 2611 2612 verify(mAudioControlWrapperAidl, never()).setModuleChangeCallback(any()); 2613 } 2614 2615 @Test getVolumeGroupIdForAudioContext_forPrimaryGroup()2616 public void getVolumeGroupIdForAudioContext_forPrimaryGroup() throws Exception { 2617 CarAudioService service = setUpAudioService(); 2618 2619 expectWithMessage("Volume group ID for primary audio zone") 2620 .that(service.getVolumeGroupIdForAudioContext(PRIMARY_AUDIO_ZONE, 2621 CarAudioContext.MUSIC)) 2622 .isEqualTo(TEST_PRIMARY_ZONE_GROUP_0); 2623 } 2624 2625 @Test getVolumeGroupIdForAudioAttribute()2626 public void getVolumeGroupIdForAudioAttribute() throws Exception { 2627 CarAudioService service = setUpAudioService(); 2628 2629 expectWithMessage("Volume group ID for primary audio zone") 2630 .that(service.getVolumeGroupIdForAudioAttribute(PRIMARY_AUDIO_ZONE, 2631 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA))) 2632 .isEqualTo(TEST_PRIMARY_ZONE_GROUP_0); 2633 } 2634 2635 @Test getVolumeGroupIdForAudioAttribute_withNullAttribute_fails()2636 public void getVolumeGroupIdForAudioAttribute_withNullAttribute_fails() throws Exception { 2637 CarAudioService service = setUpAudioService(); 2638 2639 NullPointerException thrown = assertThrows(NullPointerException.class, () -> 2640 service.getVolumeGroupIdForAudioAttribute(PRIMARY_AUDIO_ZONE, 2641 /* attributes= */ null)); 2642 2643 expectWithMessage("Null audio attribute exception").that(thrown).hasMessageThat() 2644 .contains("Audio attributes"); 2645 } 2646 2647 @Test getVolumeGroupIdForAudioAttribute_withInvalidZoneId_fails()2648 public void getVolumeGroupIdForAudioAttribute_withInvalidZoneId_fails() throws Exception { 2649 CarAudioService service = setUpAudioService(); 2650 2651 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> 2652 service.getVolumeGroupIdForAudioAttribute(INVALID_AUDIO_ZONE, 2653 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA))); 2654 2655 expectWithMessage("Invalid audio zone exception").that(thrown).hasMessageThat() 2656 .contains("Invalid audio zone Id"); 2657 } 2658 2659 @Test getInputDevicesForZoneId_primaryZone()2660 public void getInputDevicesForZoneId_primaryZone() throws Exception { 2661 CarAudioService service = setUpAudioService(); 2662 2663 expectWithMessage("Get input device for primary zone id") 2664 .that(service.getInputDevicesForZoneId(PRIMARY_AUDIO_ZONE)) 2665 .containsExactly(new AudioDeviceAttributes(mMicrophoneInputDevice)); 2666 } 2667 2668 @Test getExternalSources_forSingleDevice()2669 public void getExternalSources_forSingleDevice() throws Exception { 2670 CarAudioService service = setUpAudioService(); 2671 AudioDeviceInfo[] inputDevices = generateInputDeviceInfos(); 2672 2673 expectWithMessage("External input device addresses") 2674 .that(service.getExternalSources()) 2675 .asList().containsExactly(inputDevices[1].getAddress()); 2676 } 2677 2678 @Test setAudioEnabled_forEnabledVolumeGroupMuting()2679 public void setAudioEnabled_forEnabledVolumeGroupMuting() throws Exception { 2680 CarAudioService service = setUpAudioService(); 2681 2682 service.setAudioEnabled(/* isAudioEnabled= */ true); 2683 2684 verify(mAudioControlWrapperAidl).onDevicesToMuteChange(any()); 2685 } 2686 2687 @Test 2688 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) setAudioEnabled_forEnabledVolumeGroupMutingFromConfigFileWithMatchedRRO()2689 public void setAudioEnabled_forEnabledVolumeGroupMutingFromConfigFileWithMatchedRRO() 2690 throws Exception { 2691 CarAudioService service = setUpCarAudioServiceWithVolumeGroupMutingConfiguredInFile( 2692 R.raw.car_audio_configuration_with_group_muting_config_enabled, 2693 /* useGroupMuting= */ true); 2694 2695 service.setAudioEnabled(/* isAudioEnabled= */ true); 2696 2697 verify(mAudioControlWrapperAidl).onDevicesToMuteChange(any()); 2698 } 2699 2700 @Test 2701 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) setAudioEnabled_forEnabledVolumeGroupMutingFromConfigFileWithUnmatchedRRO()2702 public void setAudioEnabled_forEnabledVolumeGroupMutingFromConfigFileWithUnmatchedRRO() 2703 throws Exception { 2704 CarAudioService service = setUpCarAudioServiceWithVolumeGroupMutingConfiguredInFile( 2705 R.raw.car_audio_configuration_with_group_muting_config_enabled, 2706 /* useGroupMuting= */ false); 2707 2708 service.setAudioEnabled(/* isAudioEnabled= */ true); 2709 2710 verify(mAudioControlWrapperAidl).onDevicesToMuteChange(any()); 2711 } 2712 2713 @Test 2714 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) setAudioEnabled_forDisabledVolumeGroupMutingFromConfigFileWithMatchedRRO()2715 public void setAudioEnabled_forDisabledVolumeGroupMutingFromConfigFileWithMatchedRRO() 2716 throws Exception { 2717 CarAudioService service = setUpCarAudioServiceWithVolumeGroupMutingConfiguredInFile( 2718 R.raw.car_audio_configuration_with_group_muting_config_disabled, 2719 /* useGroupMuting= */ false); 2720 2721 service.setAudioEnabled(/* isAudioEnabled= */ true); 2722 2723 verify(mAudioControlWrapperAidl, never()).onDevicesToMuteChange(any()); 2724 } 2725 2726 @Test 2727 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) setAudioEnabled_forDisabledVolumeGroupMutingFromConfigFileWithUnmatchedRRO()2728 public void setAudioEnabled_forDisabledVolumeGroupMutingFromConfigFileWithUnmatchedRRO() 2729 throws Exception { 2730 CarAudioService service = setUpCarAudioServiceWithVolumeGroupMutingConfiguredInFile( 2731 R.raw.car_audio_configuration_with_group_muting_config_disabled, 2732 /* useGroupMuting= */ true); 2733 2734 service.setAudioEnabled(/* isAudioEnabled= */ true); 2735 2736 verify(mAudioControlWrapperAidl, never()).onDevicesToMuteChange(any()); 2737 } 2738 2739 @Test setAudioEnabled_forDisabledVolumeGroupMuting()2740 public void setAudioEnabled_forDisabledVolumeGroupMuting() throws Exception { 2741 CarAudioService nonVolumeGroupMutingAudioService = 2742 setUpAudioServiceWithDisabledResource(audioUseCarVolumeGroupMuting); 2743 2744 nonVolumeGroupMutingAudioService.setAudioEnabled(/* isAudioEnabled= */ true); 2745 2746 verify(mAudioControlWrapperAidl, never()).onDevicesToMuteChange(any()); 2747 } 2748 2749 @Test onAudioServerDown_forCarAudioServiceCallback()2750 public void onAudioServerDown_forCarAudioServiceCallback() throws Exception { 2751 setUpAudioService(); 2752 AudioServerStateCallback callback = getAudioServerStateCallback(); 2753 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 2754 AudioPlaybackCallback playbackCallback = getCarAudioPlaybackCallback(); 2755 ICarOccupantZoneCallback occupantZoneCallback = getOccupantZoneCallback(); 2756 KeyEventListener keyInputListener = getAudioKeyEventListener(); 2757 2758 callback.onAudioServerDown(); 2759 2760 verify(mAudioControlWrapperAidl, never()).onDevicesToMuteChange(any()); 2761 // Routing policy is not unregistered on audio server going down 2762 verify(mAudioManager, times(AUDIO_SERVICE_POLICY_REGISTRATIONS - 1)) 2763 .unregisterAudioPolicy(any()); 2764 verify(mAudioManager).unregisterAudioPlaybackCallback(playbackCallback); 2765 verify(mAudioControlWrapperAidl).unregisterFocusListener(); 2766 verify(mAudioManager, never()).unregisterVolumeGroupCallback(any()); 2767 verify(mMockPowerService).removePowerPolicyListener(any()); 2768 verify(mMockTelephonyManager).unregisterTelephonyCallback(any()); 2769 verify(mAudioManager).unregisterAudioDeviceCallback(deviceCallback); 2770 verify(mAudioControlWrapperAidl).clearModuleChangeCallback(); 2771 verify(mMockOccupantZoneService).unregisterCallback(occupantZoneCallback); 2772 verify(mMockCarInputService).unregisterKeyEventListener(keyInputListener); 2773 verify(mAudioControlWrapperAidl, never()).unlinkToDeath(); 2774 } 2775 2776 @Test onAudioServerDown_forCarAudioServiceCallback_withFadeManagerEnabled()2777 public void onAudioServerDown_forCarAudioServiceCallback_withFadeManagerEnabled() 2778 throws Exception { 2779 setUpCarAudioServiceWithFadeManagerEnabled(); 2780 AudioServerStateCallback callback = getAudioServerStateCallback(); 2781 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 2782 AudioPlaybackCallback playbackCallback = getCarAudioPlaybackCallback(); 2783 ICarOccupantZoneCallback occupantZoneCallback = getOccupantZoneCallback(); 2784 KeyEventListener keyInputListener = getAudioKeyEventListener(); 2785 2786 callback.onAudioServerDown(); 2787 2788 verify(mAudioControlWrapperAidl, never()).onDevicesToMuteChange(any()); 2789 // Routing policy is not unregistered on audio server going down 2790 verify(mAudioManager, times(AUDIO_SERVICE_POLICY_REGISTRATIONS_WITH_FADE_MANAGER - 1)) 2791 .unregisterAudioPolicy(any()); 2792 verify(mAudioManager).unregisterAudioPlaybackCallback(playbackCallback); 2793 verify(mAudioControlWrapperAidl).unregisterFocusListener(); 2794 verify(mAudioManager, never()).unregisterVolumeGroupCallback(any()); 2795 verify(mMockPowerService).removePowerPolicyListener(any()); 2796 verify(mMockTelephonyManager).unregisterTelephonyCallback(any()); 2797 verify(mAudioManager).unregisterAudioDeviceCallback(deviceCallback); 2798 verify(mAudioControlWrapperAidl).clearModuleChangeCallback(); 2799 verify(mMockOccupantZoneService).unregisterCallback(occupantZoneCallback); 2800 verify(mMockCarInputService).unregisterKeyEventListener(keyInputListener); 2801 verify(mAudioControlWrapperAidl, never()).unlinkToDeath(); 2802 } 2803 2804 @Test onAudioServerDown_forCarAudioServiceCallback_withCoreVolumeAndRouting()2805 public void onAudioServerDown_forCarAudioServiceCallback_withCoreVolumeAndRouting() 2806 throws Exception { 2807 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 2808 AudioServerStateCallback callback = getAudioServerStateCallback(); 2809 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 2810 AudioPlaybackCallback playbackCallback = getCarAudioPlaybackCallback(); 2811 ICarOccupantZoneCallback occupantZoneCallback = getOccupantZoneCallback(); 2812 KeyEventListener keyInputListener = getAudioKeyEventListener(); 2813 2814 callback.onAudioServerDown(); 2815 2816 verify(mAudioControlWrapperAidl, never()).onDevicesToMuteChange(any()); 2817 // Routing policy is not unregistered on audio server going down 2818 verify(mAudioManager, times(AUDIO_SERVICE_POLICY_REGISTRATIONS - 1)) 2819 .unregisterAudioPolicy(any()); 2820 verify(mAudioManager).unregisterAudioPlaybackCallback(playbackCallback); 2821 verify(mAudioControlWrapperAidl).unregisterFocusListener(); 2822 verify(mAudioManager).unregisterVolumeGroupCallback(any()); 2823 verify(mMockPowerService).removePowerPolicyListener(any()); 2824 verify(mMockTelephonyManager).unregisterTelephonyCallback(any()); 2825 verify(mAudioManager).unregisterAudioDeviceCallback(deviceCallback); 2826 verify(mAudioControlWrapperAidl).clearModuleChangeCallback(); 2827 verify(mMockOccupantZoneService).unregisterCallback(occupantZoneCallback); 2828 verify(mMockCarInputService).unregisterKeyEventListener(keyInputListener); 2829 verify(mAudioControlWrapperAidl, never()).unlinkToDeath(); 2830 } 2831 2832 @Test onAudioServerUp_forCarAudioServiceCallback()2833 public void onAudioServerUp_forCarAudioServiceCallback() throws Exception { 2834 CarAudioService service = setUpAudioService(); 2835 AudioServerStateCallback callback = getAudioServerStateCallback(); 2836 callback.onAudioServerDown(); 2837 2838 callback.onAudioServerUp(); 2839 2840 waitForInternalCallback(); 2841 expectWithMessage("Re-initialized Car Audio Service Zones") 2842 .that(service.getAudioZoneIds()).asList() 2843 .containsExactly(PRIMARY_AUDIO_ZONE, TEST_REAR_LEFT_ZONE_ID, 2844 TEST_REAR_RIGHT_ZONE_ID, TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID); 2845 // Each callback should register twice the registration from init for each required callback 2846 verify(mAudioManager, times(2 * AUDIO_SERVICE_POLICY_REGISTRATIONS)) 2847 .registerAudioPolicy(any()); 2848 verify(mAudioManager, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2849 .registerAudioPlaybackCallback(any(), any()); 2850 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2851 .registerFocusListener(any()); 2852 verify(mAudioManager, never()).registerVolumeGroupCallback(any(), any()); 2853 verify(mMockPowerService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2854 .addPowerPolicyListener(any(), any()); 2855 verify(mAudioManager, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2856 .registerAudioDeviceCallback(any(), any()); 2857 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2858 .setModuleChangeCallback(any()); 2859 verify(mMockOccupantZoneService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2860 .registerCallback(any()); 2861 verify(mMockCarInputService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2862 .registerKeyEventListener(any(), any()); 2863 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2864 .linkToDeath(any()); 2865 } 2866 2867 @Test onAudioServerUp_forCarAudioServiceCallback_withFadeManagerEnabled()2868 public void onAudioServerUp_forCarAudioServiceCallback_withFadeManagerEnabled() 2869 throws Exception { 2870 CarAudioService service = setUpCarAudioServiceWithFadeManagerEnabled(); 2871 AudioServerStateCallback callback = getAudioServerStateCallback(); 2872 callback.onAudioServerDown(); 2873 2874 callback.onAudioServerUp(); 2875 2876 service.waitForInitComplete(INIT_TIMEOUT_MS); 2877 expectWithMessage("Re-initialized Car Audio Service Zones") 2878 .that(service.getAudioZoneIds()).asList() 2879 .containsExactly(PRIMARY_AUDIO_ZONE, TEST_REAR_LEFT_ZONE_ID, 2880 TEST_REAR_RIGHT_ZONE_ID, TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID); 2881 // Each callback should register twice the registration from init for each required callback 2882 verify(mAudioManager, times(2 * AUDIO_SERVICE_POLICY_REGISTRATIONS_WITH_FADE_MANAGER)) 2883 .registerAudioPolicy(any()); 2884 verify(mAudioManager, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2885 .registerAudioPlaybackCallback(any(), any()); 2886 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2887 .registerFocusListener(any()); 2888 verify(mAudioManager, never()).registerVolumeGroupCallback(any(), any()); 2889 verify(mMockPowerService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2890 .addPowerPolicyListener(any(), any()); 2891 verify(mAudioManager, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2892 .registerAudioDeviceCallback(any(), any()); 2893 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2894 .setModuleChangeCallback(any()); 2895 verify(mMockOccupantZoneService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2896 .registerCallback(any()); 2897 verify(mMockCarInputService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2898 .registerKeyEventListener(any(), any()); 2899 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2900 .linkToDeath(any()); 2901 } 2902 2903 2904 @Test onAudioServerUp_forCarAudioServiceCallback_withCoreVolumeAndRouting()2905 public void onAudioServerUp_forCarAudioServiceCallback_withCoreVolumeAndRouting() 2906 throws Exception { 2907 CarAudioService service = setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 2908 AudioServerStateCallback callback = getAudioServerStateCallback(); 2909 callback.onAudioServerDown(); 2910 2911 callback.onAudioServerUp(); 2912 2913 service.waitForInitComplete(INIT_TIMEOUT_MS); 2914 expectWithMessage("Re-initialized Car Audio Service Zones") 2915 .that(service.getAudioZoneIds()).asList() 2916 .containsExactly(PRIMARY_AUDIO_ZONE); 2917 // Each callback should register twice the registration from init for each required callback 2918 verify(mAudioManager, times(2 * AUDIO_SERVICE_POLICY_REGISTRATIONS)) 2919 .registerAudioPolicy(any()); 2920 verify(mAudioManager, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2921 .registerAudioPlaybackCallback(any(), any()); 2922 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2923 .registerFocusListener(any()); 2924 verify(mAudioManager, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2925 .registerVolumeGroupCallback(any(), any()); 2926 verify(mMockPowerService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2927 .addPowerPolicyListener(any(), any()); 2928 verify(mAudioManager, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2929 .registerAudioDeviceCallback(any(), any()); 2930 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2931 .setModuleChangeCallback(any()); 2932 verify(mMockOccupantZoneService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2933 .registerCallback(any()); 2934 verify(mMockCarInputService, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2935 .registerKeyEventListener(any(), any()); 2936 verify(mAudioControlWrapperAidl, times(2 * AUDIO_SERVICE_CALLBACKS_REGISTRATION)) 2937 .linkToDeath(any()); 2938 } 2939 2940 @Test onAudioServerUp_forUserIdAssignments()2941 public void onAudioServerUp_forUserIdAssignments() throws Exception { 2942 CarAudioService service = setUpAudioService(); 2943 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2944 when(mMockOccupantZoneService.getUserForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 2945 .thenReturn(TEST_DRIVER_USER_ID); 2946 AudioServerStateCallback callback = getAudioServerStateCallback(); 2947 callback.onAudioServerDown(); 2948 2949 callback.onAudioServerUp(); 2950 2951 service.waitForInitComplete(INIT_TIMEOUT_MS); 2952 waitForInternalCallback(); 2953 expectWithMessage("Re-initialized Car Audio Service Zones") 2954 .that(service.getAudioZoneIds()).asList() 2955 .containsExactly(PRIMARY_AUDIO_ZONE, TEST_REAR_LEFT_ZONE_ID, 2956 TEST_REAR_RIGHT_ZONE_ID, TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID); 2957 expectWithMessage("Primary user id after server recovery") 2958 .that(service.getUserIdForZone(PRIMARY_AUDIO_ZONE)).isEqualTo(TEST_DRIVER_USER_ID); 2959 expectWithMessage("Rear left user id after server recovery") 2960 .that(service.getUserIdForZone(TEST_REAR_LEFT_ZONE_ID)) 2961 .isEqualTo(TEST_REAR_LEFT_USER_ID); 2962 expectWithMessage("Rear right user id after server recovery") 2963 .that(service.getUserIdForZone(TEST_REAR_RIGHT_ZONE_ID)) 2964 .isEqualTo(TEST_REAR_RIGHT_USER_ID); 2965 expectWithMessage("Rear front user id after server recovery") 2966 .that(service.getUserIdForZone(TEST_FRONT_ZONE_ID)) 2967 .isEqualTo(TEST_FRONT_PASSENGER_USER_ID); 2968 expectWithMessage("Rear row 3 user id after server recovery") 2969 .that(service.getUserIdForZone(TEST_REAR_ROW_3_ZONE_ID)) 2970 .isEqualTo(TEST_REAR_ROW_3_PASSENGER_USER_ID); 2971 } 2972 2973 @Test registerVolumeCallback_verifyCallbackHandler()2974 public void registerVolumeCallback_verifyCallbackHandler() throws Exception { 2975 int uid = Binder.getCallingUid(); 2976 CarAudioService service = setUpAudioService(); 2977 2978 service.registerVolumeCallback(mVolumeCallbackBinder); 2979 2980 verify(mCarVolumeCallbackHandler).registerCallback(mVolumeCallbackBinder, uid, true); 2981 } 2982 2983 @Test unregisterVolumeCallback_verifyCallbackHandler()2984 public void unregisterVolumeCallback_verifyCallbackHandler() throws Exception { 2985 int uid = Binder.getCallingUid(); 2986 CarAudioService service = setUpAudioService(); 2987 2988 service.unregisterVolumeCallback(mVolumeCallbackBinder); 2989 2990 verify(mCarVolumeCallbackHandler).unregisterCallback(mVolumeCallbackBinder, uid); 2991 } 2992 2993 @Test getMutedVolumeGroups_forInvalidZone()2994 public void getMutedVolumeGroups_forInvalidZone() throws Exception { 2995 CarAudioService service = setUpAudioService(); 2996 2997 expectWithMessage("Muted volume groups for invalid zone") 2998 .that(service.getMutedVolumeGroups(INVALID_AUDIO_ZONE)) 2999 .isEmpty(); 3000 } 3001 3002 @Test getMutedVolumeGroups_whenVolumeGroupMuteNotSupported()3003 public void getMutedVolumeGroups_whenVolumeGroupMuteNotSupported() throws Exception { 3004 CarAudioService nonVolumeGroupMutingAudioService = 3005 setUpAudioServiceWithDisabledResource(audioUseCarVolumeGroupMuting); 3006 3007 expectWithMessage("Muted volume groups with disable mute feature") 3008 .that(nonVolumeGroupMutingAudioService.getMutedVolumeGroups(PRIMARY_AUDIO_ZONE)) 3009 .isEmpty(); 3010 } 3011 3012 @Test getMutedVolumeGroups_withMutedGroups()3013 public void getMutedVolumeGroups_withMutedGroups() throws Exception { 3014 CarAudioService service = setUpAudioService(); 3015 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 3016 /* mute= */ true, TEST_FLAGS); 3017 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1, 3018 /* mute= */ true, TEST_FLAGS); 3019 3020 expectWithMessage("Muted volume groups") 3021 .that(service.getMutedVolumeGroups(PRIMARY_AUDIO_ZONE)) 3022 .containsExactly(mTestPrimaryZoneVolumeInfo0, 3023 mTestPrimaryZoneVolumeInfo1); 3024 } 3025 3026 @Test getMutedVolumeGroups_afterUnmuting()3027 public void getMutedVolumeGroups_afterUnmuting() throws Exception { 3028 CarAudioService service = setUpAudioService(); 3029 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 3030 /* mute= */ true, TEST_FLAGS); 3031 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1, 3032 /* mute= */ true, TEST_FLAGS); 3033 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 3034 /* mute= */ false, TEST_FLAGS); 3035 3036 expectWithMessage("Muted volume groups after unmuting one group") 3037 .that(service.getMutedVolumeGroups(PRIMARY_AUDIO_ZONE)) 3038 .containsExactly(mTestPrimaryZoneVolumeInfo1); 3039 } 3040 3041 @Test getMutedVolumeGroups_withMutedGroupsForDifferentZone()3042 public void getMutedVolumeGroups_withMutedGroupsForDifferentZone() throws Exception { 3043 CarAudioService service = setUpAudioService(); 3044 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 3045 /* mute= */ true, TEST_FLAGS); 3046 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1, 3047 /* mute= */ true, TEST_FLAGS); 3048 3049 expectWithMessage("Muted volume groups for secondary zone") 3050 .that(service.getMutedVolumeGroups(TEST_REAR_LEFT_ZONE_ID)).isEmpty(); 3051 } 3052 3053 @Test onReceive_forLegacy_noCallToOnVolumeGroupChanged()3054 public void onReceive_forLegacy_noCallToOnVolumeGroupChanged() throws Exception { 3055 setUpAudioServiceWithoutDynamicRouting(); 3056 mVolumeReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); 3057 verify(mMockContext).registerReceiver(mVolumeReceiverCaptor.capture(), any(), anyInt()); 3058 BroadcastReceiver receiver = mVolumeReceiverCaptor.getValue(); 3059 Intent intent = new Intent(VOLUME_CHANGED_ACTION); 3060 3061 receiver.onReceive(mMockContext, intent); 3062 3063 verify(mCarVolumeCallbackHandler, never()) 3064 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 3065 } 3066 3067 @Test onReceive_forLegacy_forStreamMusic()3068 public void onReceive_forLegacy_forStreamMusic() throws Exception { 3069 setUpAudioServiceWithoutDynamicRouting(); 3070 verify(mMockContext).registerReceiver(mVolumeReceiverCaptor.capture(), any(), anyInt()); 3071 BroadcastReceiver receiver = mVolumeReceiverCaptor.getValue(); 3072 Intent intent = new Intent(VOLUME_CHANGED_ACTION) 3073 .putExtra(EXTRA_VOLUME_STREAM_TYPE, STREAM_MUSIC); 3074 3075 receiver.onReceive(mMockContext, intent); 3076 3077 verify(mCarVolumeCallbackHandler).onVolumeGroupChange( 3078 eq(PRIMARY_AUDIO_ZONE), anyInt(), eq(FLAG_FROM_KEY | FLAG_SHOW_UI)); 3079 } 3080 3081 @Test onReceive_forLegacy_onMuteChanged()3082 public void onReceive_forLegacy_onMuteChanged() throws Exception { 3083 setUpAudioServiceWithoutDynamicRouting(); 3084 ArgumentCaptor<BroadcastReceiver> captor = 3085 ArgumentCaptor.forClass(BroadcastReceiver.class); 3086 verify(mMockContext).registerReceiver(captor.capture(), any(), anyInt()); 3087 BroadcastReceiver receiver = captor.getValue(); 3088 Intent intent = new Intent(); 3089 intent.setAction(MASTER_MUTE_CHANGED_ACTION); 3090 3091 receiver.onReceive(mMockContext, intent); 3092 3093 verify(mCarVolumeCallbackHandler) 3094 .onMasterMuteChanged(eq(PRIMARY_AUDIO_ZONE), eq(FLAG_FROM_KEY | FLAG_SHOW_UI)); 3095 } 3096 3097 @Test getVolumeGroupInfosForZone()3098 public void getVolumeGroupInfosForZone() throws Exception { 3099 CarAudioService service = setUpAudioService(); 3100 int groupCount = service.getVolumeGroupCount(PRIMARY_AUDIO_ZONE); 3101 3102 List<CarVolumeGroupInfo> infos = 3103 service.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 3104 3105 for (int index = 0; index < groupCount; index++) { 3106 CarVolumeGroupInfo info = service 3107 .getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, index); 3108 expectWithMessage("Car volume group infos for primary zone and info %s", info) 3109 .that(infos).contains(info); 3110 } 3111 } 3112 3113 @Test getVolumeGroupInfosForZone_forDynamicRoutingDisabled()3114 public void getVolumeGroupInfosForZone_forDynamicRoutingDisabled() throws Exception { 3115 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 3116 List<AudioDeviceInfo> deviceInfos = List.of(mCarAudioDeviceUtils.mMediaOutputDevice); 3117 when(mAudioManager.getAudioDevicesForAttributes(ATTRIBUTES_MEDIA)).thenReturn(deviceInfos); 3118 when(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).thenReturn(true); 3119 CarVolumeGroupInfo expectedVolumeGroupInfo = new CarVolumeGroupInfo.Builder( 3120 TEST_LEGACY_VOLUME_GROUP_NAME, PRIMARY_OCCUPANT_ZONE, MEDIA_VOLUME_GROUP_ID) 3121 .setVolumeGainIndex(TEST_STREAM_VOLUME) 3122 .setMaxVolumeGainIndex(TEST_STREAM_MAX_VOLUME) 3123 .setMinVolumeGainIndex(TEST_STREAM_MIN_VOLUME) 3124 .setAudioAttributes(Arrays.asList(ATTRIBUTES_MEDIA)) 3125 .setAudioDeviceAttributes(List.of( 3126 new AudioDeviceAttributes(mCarAudioDeviceUtils.mMediaOutputDevice))) 3127 .setMuted(true) 3128 .setBlocked(false) 3129 .setAttenuated(false) 3130 .setMaxActivationVolumeGainIndex(TEST_STREAM_MAX_VOLUME) 3131 .setMinActivationVolumeGainIndex(TEST_STREAM_MIN_VOLUME) 3132 .setMutedBySystem(false).build(); 3133 3134 List<CarVolumeGroupInfo> infos = 3135 nonDynamicAudioService.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 3136 3137 expectWithMessage("Car volume group infos size with dynamic routing disabled") 3138 .that(infos).hasSize(CarAudioDynamicRouting.STREAM_TYPES.length); 3139 expectWithMessage("Car volume group info name with dynamic routing disabled") 3140 .that(infos.get(0)).isEqualTo(expectedVolumeGroupInfo); 3141 } 3142 3143 @Test getVolumeGroupInfosForZone_forOEMConfiguration()3144 public void getVolumeGroupInfosForZone_forOEMConfiguration() throws Exception { 3145 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration_using_oem_defined_context); 3146 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, mAudioManager, 3147 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 3148 /* audioFadeConfigurationPath= */ null); 3149 initServiceAndWaitForComplete(nonDynamicAudioService); 3150 3151 List<CarVolumeGroupInfo> infos = 3152 nonDynamicAudioService.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 3153 3154 expectWithMessage("Car volume group infos size with OEM configuration") 3155 .that(infos).hasSize(1); 3156 expectWithMessage("Car volume group info name with OEM configuration") 3157 .that(infos.get(0).getName()).isEqualTo("OEM_VOLUME_GROUP"); 3158 } 3159 3160 @Test getVolumeGroupInfosForZone_size()3161 public void getVolumeGroupInfosForZone_size() throws Exception { 3162 CarAudioService service = setUpAudioService(); 3163 int groupCount = service.getVolumeGroupCount(PRIMARY_AUDIO_ZONE); 3164 3165 List<CarVolumeGroupInfo> infos = 3166 service.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 3167 3168 expectWithMessage("Car volume group infos size for primary zone") 3169 .that(infos).hasSize(groupCount); 3170 } 3171 3172 @Test getVolumeGroupInfosForZone_forInvalidZone()3173 public void getVolumeGroupInfosForZone_forInvalidZone() throws Exception { 3174 CarAudioService service = setUpAudioService(); 3175 3176 IllegalArgumentException thrown = 3177 assertThrows(IllegalArgumentException.class, () -> 3178 service.getVolumeGroupInfosForZone(INVALID_AUDIO_ZONE)); 3179 3180 expectWithMessage("Exception for volume group infos size for invalid zone") 3181 .that(thrown).hasMessageThat().contains("audio zone Id"); 3182 } 3183 3184 @Test getVolumeGroupInfo()3185 public void getVolumeGroupInfo() throws Exception { 3186 CarVolumeGroupInfo testVolumeGroupInfo = new CarVolumeGroupInfo.Builder( 3187 mTestPrimaryZoneVolumeInfo0).setMuted(false).build(); 3188 CarAudioService service = setUpAudioService(); 3189 3190 expectWithMessage("Car volume group info for primary zone") 3191 .that(service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 3192 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(testVolumeGroupInfo); 3193 } 3194 3195 @Test getVolumeGroupInfo_forInvalidZone()3196 public void getVolumeGroupInfo_forInvalidZone() throws Exception { 3197 CarAudioService service = setUpAudioService(); 3198 3199 IllegalArgumentException thrown = 3200 assertThrows(IllegalArgumentException.class, () -> 3201 service.getVolumeGroupInfo(INVALID_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)); 3202 3203 expectWithMessage("Exception for volume group info size for invalid zone") 3204 .that(thrown).hasMessageThat().contains("audio zone Id"); 3205 } 3206 3207 @Test getVolumeGroupInfo_forInvalidGroup()3208 public void getVolumeGroupInfo_forInvalidGroup() throws Exception { 3209 CarAudioService service = setUpAudioService(); 3210 3211 IllegalArgumentException thrown = 3212 assertThrows(IllegalArgumentException.class, () -> 3213 service.getVolumeGroupInfo(INVALID_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)); 3214 3215 expectWithMessage("Exception for volume groups info size for invalid group id") 3216 .that(thrown).hasMessageThat().contains("audio zone Id"); 3217 } 3218 3219 @Test getVolumeGroupInfo_forGroupOverRange()3220 public void getVolumeGroupInfo_forGroupOverRange() throws Exception { 3221 CarAudioService service = setUpAudioService(); 3222 int groupCount = service.getVolumeGroupCount(PRIMARY_AUDIO_ZONE); 3223 3224 IllegalArgumentException thrown = 3225 assertThrows(IllegalArgumentException.class, () -> 3226 service.getVolumeGroupInfo(INVALID_AUDIO_ZONE, 3227 groupCount)); 3228 3229 expectWithMessage("Exception for volume groups info size for out of range group") 3230 .that(thrown).hasMessageThat().contains("audio zone Id"); 3231 } 3232 3233 @Test getVolumeGroupInfo_withLegacyMode()3234 public void getVolumeGroupInfo_withLegacyMode() throws Exception { 3235 CarAudioService service = setUpAudioServiceWithoutDynamicRouting(); 3236 List<AudioDeviceInfo> deviceInfos = List.of(mCarAudioDeviceUtils.mMediaOutputDevice); 3237 when(mAudioManager.getAudioDevicesForAttributes(ATTRIBUTES_MEDIA)).thenReturn(deviceInfos); 3238 when(mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)).thenReturn(true); 3239 CarVolumeGroupInfo expectedVolumeGroupInfo = new CarVolumeGroupInfo.Builder( 3240 TEST_LEGACY_VOLUME_GROUP_NAME, PRIMARY_OCCUPANT_ZONE, MEDIA_VOLUME_GROUP_ID) 3241 .setVolumeGainIndex(TEST_STREAM_VOLUME) 3242 .setMaxVolumeGainIndex(TEST_STREAM_MAX_VOLUME) 3243 .setMinVolumeGainIndex(TEST_STREAM_MIN_VOLUME) 3244 .setAudioAttributes(Arrays.asList(ATTRIBUTES_MEDIA)) 3245 .setAudioDeviceAttributes(List.of( 3246 new AudioDeviceAttributes(mCarAudioDeviceUtils.mMediaOutputDevice))) 3247 .setMuted(true) 3248 .setBlocked(false) 3249 .setAttenuated(false) 3250 .setMaxActivationVolumeGainIndex(TEST_STREAM_MAX_VOLUME) 3251 .setMinActivationVolumeGainIndex(TEST_STREAM_MIN_VOLUME) 3252 .setMutedBySystem(false).build(); 3253 3254 CarVolumeGroupInfo testVolumeGroupInfo = 3255 service.getVolumeGroupInfo(PRIMARY_OCCUPANT_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 3256 3257 expectWithMessage("Volume group info in legacy mode") 3258 .that(testVolumeGroupInfo) 3259 .isEqualTo(expectedVolumeGroupInfo); 3260 } 3261 3262 @Test registerPrimaryZoneMediaAudioRequestCallbackListener_withNullCallback_fails()3263 public void registerPrimaryZoneMediaAudioRequestCallbackListener_withNullCallback_fails() 3264 throws Exception { 3265 CarAudioService service = setUpAudioService(); 3266 3267 NullPointerException thrown = assertThrows(NullPointerException.class, () 3268 -> service.registerPrimaryZoneMediaAudioRequestCallback( 3269 /* callback= */ null)); 3270 3271 expectWithMessage("Register audio media request callback exception") 3272 .that(thrown).hasMessageThat() 3273 .contains("Media request callback"); 3274 } 3275 3276 @Test unregisterPrimaryZoneMediaAudioRequestCallback_withNullCallback_fails()3277 public void unregisterPrimaryZoneMediaAudioRequestCallback_withNullCallback_fails() 3278 throws Exception { 3279 CarAudioService service = setUpAudioService(); 3280 3281 NullPointerException thrown = assertThrows(NullPointerException.class, () 3282 -> service.unregisterPrimaryZoneMediaAudioRequestCallback( 3283 /* callback= */ null)); 3284 3285 expectWithMessage("Unregister audio media request callback exception") 3286 .that(thrown).hasMessageThat() 3287 .contains("Media request callback"); 3288 } 3289 3290 @Test requestMediaAudioOnPrimaryZone_withPassengerOccupant_succeeds()3291 public void requestMediaAudioOnPrimaryZone_withPassengerOccupant_succeeds() 3292 throws Exception { 3293 CarAudioService service = setUpAudioService(); 3294 TestPrimaryZoneMediaAudioRequestCallback 3295 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3296 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3297 assignOccupantToAudioZones(); 3298 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3299 3300 expectWithMessage("Audio media request id") 3301 .that(service.requestMediaAudioOnPrimaryZone(requestCallback, 3302 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 3303 .isNotEqualTo(INVALID_REQUEST_ID); 3304 } 3305 3306 @Test requestMediaAudioOnPrimaryZone_withDriverOccupant_fails()3307 public void requestMediaAudioOnPrimaryZone_withDriverOccupant_fails() 3308 throws Exception { 3309 CarAudioService service = setUpAudioService(); 3310 TestPrimaryZoneMediaAudioRequestCallback 3311 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3312 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3313 assignOccupantToAudioZones(); 3314 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3315 3316 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () 3317 -> service.requestMediaAudioOnPrimaryZone(requestCallback, 3318 TEST_DRIVER_OCCUPANT)); 3319 3320 expectWithMessage("Request media audio exception") 3321 .that(thrown).hasMessageThat().contains("already owns the primary audio zone"); 3322 } 3323 3324 @Test requestMediaAudioOnPrimaryZone_withNonAssignedOccupant_fails()3325 public void requestMediaAudioOnPrimaryZone_withNonAssignedOccupant_fails() 3326 throws Exception { 3327 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_UNASSIGNED_OCCUPANT_ZONE_ID)) 3328 .thenReturn(OUT_OF_RANGE_ZONE); 3329 CarAudioService service = setUpAudioService(); 3330 TestPrimaryZoneMediaAudioRequestCallback 3331 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3332 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3333 CarOccupantZoneManager.OccupantZoneInfo info = 3334 getOccupantInfo(TEST_UNASSIGNED_OCCUPANT_ZONE_ID, 3335 CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER, 3336 VehicleAreaSeat.SEAT_ROW_1_LEFT); 3337 assignOccupantToAudioZones(); 3338 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3339 3340 expectWithMessage("Invalid audio media request id") 3341 .that(service.requestMediaAudioOnPrimaryZone(requestCallback, info)) 3342 .isEqualTo(INVALID_REQUEST_ID); 3343 } 3344 3345 @Test requestMediaAudioOnPrimaryZone_withPassengerOccupant_callsApprover()3346 public void requestMediaAudioOnPrimaryZone_withPassengerOccupant_callsApprover() 3347 throws Exception { 3348 CarAudioService service = setUpAudioService(); 3349 TestPrimaryZoneMediaAudioRequestCallback 3350 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3351 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3352 assignOccupantToAudioZones(); 3353 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3354 3355 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3356 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3357 3358 requestToken.waitForCallback(); 3359 expectWithMessage("Called audio media request id") 3360 .that(requestToken.mRequestId).isEqualTo(requestId); 3361 expectWithMessage("Called audio media request info") 3362 .that(requestToken.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3363 } 3364 3365 @Test requestMediaAudioOnPrimaryZone_withZoneMirroring_fails()3366 public void requestMediaAudioOnPrimaryZone_withZoneMirroring_fails() 3367 throws Exception { 3368 CarAudioService service = setUpAudioService(); 3369 TestPrimaryZoneMediaAudioRequestCallback 3370 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3371 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3372 assignOccupantToAudioZones(); 3373 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3374 TestAudioZonesMirrorStatusCallbackCallback mirrorCallback = 3375 getAudioZonesMirrorStatusCallback(service); 3376 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3377 mirrorCallback.waitForCallback(); 3378 3379 IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> 3380 service.requestMediaAudioOnPrimaryZone(requestCallback, 3381 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)); 3382 3383 expectWithMessage("Request audio share while mirroring exception").that(thrown) 3384 .hasMessageThat().contains("Can not request audio share to primary zone"); 3385 } 3386 3387 @Test binderDied_onMediaRequestApprover_resetsApprovedRequest()3388 public void binderDied_onMediaRequestApprover_resetsApprovedRequest() 3389 throws Exception { 3390 CarAudioService service = setUpAudioService(); 3391 TestPrimaryZoneMediaAudioRequestCallback requestToken = 3392 new TestPrimaryZoneMediaAudioRequestCallback(); 3393 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3394 assignOccupantToAudioZones(); 3395 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3396 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3397 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3398 requestToken.waitForCallback(); 3399 requestToken.reset(); 3400 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3401 requestToken.waitForCallback(); 3402 requestCallback.waitForCallback(); 3403 requestCallback.reset(); 3404 3405 requestToken.mDeathRecipient.binderDied(); 3406 3407 requestCallback.waitForCallback(); 3408 expectWithMessage("Stopped status due to approver's death").that(requestCallback.mStatus) 3409 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 3410 expectWithMessage("Stopped id due to approver's death") 3411 .that(requestCallback.mRequestId).isEqualTo(requestId); 3412 } 3413 3414 @Test allowMediaAudioOnPrimaryZone_withAllowedRequest()3415 public void allowMediaAudioOnPrimaryZone_withAllowedRequest() throws Exception { 3416 CarAudioService service = setUpAudioService(); 3417 TestPrimaryZoneMediaAudioRequestCallback 3418 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3419 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3420 assignOccupantToAudioZones(); 3421 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3422 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3423 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3424 requestToken.waitForCallback(); 3425 3426 boolean results = service.allowMediaAudioOnPrimaryZone(requestToken, requestId, 3427 /* allow= */ true); 3428 3429 expectWithMessage("Allowed audio playback").that(results).isTrue(); 3430 } 3431 3432 @Test allowMediaAudioOnPrimaryZone_whileMirroring_fails()3433 public void allowMediaAudioOnPrimaryZone_whileMirroring_fails() throws Exception { 3434 CarAudioService service = setUpAudioService(); 3435 TestPrimaryZoneMediaAudioRequestCallback 3436 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3437 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3438 assignOccupantToAudioZones(); 3439 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3440 long shareId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3441 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3442 requestToken.waitForCallback(); 3443 TestAudioZonesMirrorStatusCallbackCallback mirrorCallback = 3444 getAudioZonesMirrorStatusCallback(service); 3445 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3446 mirrorCallback.waitForCallback(); 3447 requestCallback.waitForCallback(); 3448 3449 IllegalStateException thrown = 3450 assertThrows(IllegalStateException.class, () -> service 3451 .allowMediaAudioOnPrimaryZone(requestToken, shareId, /* allow= */ true)); 3452 3453 expectWithMessage("Allow audio share while mirroring exception").that(thrown) 3454 .hasMessageThat().contains("Can not allow audio share to primary zone"); 3455 requestCallback.waitForCallback(); 3456 expectWithMessage("Rejected status due to mirroring").that(requestCallback.mStatus) 3457 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_REJECTED); 3458 expectWithMessage("Rejected id with rejected due to mirroring") 3459 .that(requestCallback.mRequestId).isEqualTo(shareId); 3460 } 3461 3462 @Test allowMediaAudioOnPrimaryZone_withUnallowedRequest()3463 public void allowMediaAudioOnPrimaryZone_withUnallowedRequest() throws Exception { 3464 CarAudioService service = setUpAudioService(); 3465 TestPrimaryZoneMediaAudioRequestCallback 3466 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3467 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3468 assignOccupantToAudioZones(); 3469 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3470 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3471 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3472 requestToken.waitForCallback(); 3473 3474 boolean results = service.allowMediaAudioOnPrimaryZone(requestToken, requestId, 3475 /* allow= */ false); 3476 3477 expectWithMessage("Unallowed audio playback").that(results).isTrue(); 3478 } 3479 3480 @Test allowMediaAudioOnPrimaryZone_withAllowedRequest_callsRequester()3481 public void allowMediaAudioOnPrimaryZone_withAllowedRequest_callsRequester() throws Exception { 3482 CarAudioService service = setUpAudioService(); 3483 TestPrimaryZoneMediaAudioRequestCallback 3484 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3485 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3486 assignOccupantToAudioZones(); 3487 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3488 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3489 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3490 requestToken.waitForCallback(); 3491 3492 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3493 3494 requestCallback.waitForCallback(); 3495 expectWithMessage("Media request called audio media request id") 3496 .that(requestCallback.mRequestId).isEqualTo(requestId); 3497 expectWithMessage("Media request called audio media request info") 3498 .that(requestCallback.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3499 expectWithMessage("Media request called audio media request status") 3500 .that(requestCallback.mStatus) 3501 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 3502 } 3503 3504 @Test allowMediaAudioOnPrimaryZone_withAllowedRequest_callsApprover()3505 public void allowMediaAudioOnPrimaryZone_withAllowedRequest_callsApprover() throws Exception { 3506 CarAudioService service = setUpAudioService(); 3507 TestPrimaryZoneMediaAudioRequestCallback 3508 requestApprover = new TestPrimaryZoneMediaAudioRequestCallback(); 3509 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3510 assignOccupantToAudioZones(); 3511 service.registerPrimaryZoneMediaAudioRequestCallback(requestApprover); 3512 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3513 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3514 requestApprover.waitForCallback(); 3515 requestApprover.reset(); 3516 3517 service.allowMediaAudioOnPrimaryZone(requestApprover, requestId, /* allow= */ true); 3518 3519 requestApprover.waitForCallback(); 3520 expectWithMessage("Media approver called audio media request id") 3521 .that(requestApprover.mRequestId).isEqualTo(requestId); 3522 expectWithMessage("Media approver called audio media request info") 3523 .that(requestApprover.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3524 expectWithMessage("Media approver called audio media request status") 3525 .that(requestApprover.mStatus) 3526 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 3527 } 3528 3529 @Test allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsRequester()3530 public void allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsRequester() 3531 throws Exception { 3532 CarAudioService service = setUpAudioService(); 3533 TestPrimaryZoneMediaAudioRequestCallback 3534 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3535 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3536 assignOccupantToAudioZones(); 3537 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3538 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3539 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3540 requestToken.waitForCallback(); 3541 3542 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ false); 3543 3544 requestCallback.waitForCallback(); 3545 expectWithMessage("Unallowed media request called audio media request id") 3546 .that(requestCallback.mRequestId).isEqualTo(requestId); 3547 expectWithMessage("Unallowed media request called audio media request info") 3548 .that(requestCallback.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3549 expectWithMessage("Unallowed media request called audio media request status") 3550 .that(requestCallback.mStatus) 3551 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_REJECTED); 3552 } 3553 3554 @Test allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsApprover()3555 public void allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsApprover() throws Exception { 3556 CarAudioService service = setUpAudioService(); 3557 TestPrimaryZoneMediaAudioRequestCallback 3558 requestApprover = new TestPrimaryZoneMediaAudioRequestCallback(); 3559 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3560 assignOccupantToAudioZones(); 3561 service.registerPrimaryZoneMediaAudioRequestCallback(requestApprover); 3562 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3563 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3564 requestApprover.waitForCallback(); 3565 requestApprover.reset(); 3566 3567 service.allowMediaAudioOnPrimaryZone(requestApprover, requestId, /* allow= */ false); 3568 3569 requestApprover.waitForCallback(); 3570 expectWithMessage("Unallowed media approver called audio media request id") 3571 .that(requestApprover.mRequestId).isEqualTo(requestId); 3572 expectWithMessage("Unallowed approver token called audio media request info") 3573 .that(requestApprover.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3574 expectWithMessage("Unallowed approver token called audio media request status") 3575 .that(requestApprover.mStatus) 3576 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_REJECTED); 3577 } 3578 3579 @Test isMediaAudioAllowedInPrimaryZone_witNullOccupant_fails()3580 public void isMediaAudioAllowedInPrimaryZone_witNullOccupant_fails() throws Exception { 3581 CarAudioService service = setUpAudioService(); 3582 NullPointerException thrown = assertThrows(NullPointerException.class, () 3583 -> service.isMediaAudioAllowedInPrimaryZone(/* info= */ null)); 3584 3585 expectWithMessage("Media status exception").that(thrown) 3586 .hasMessageThat().contains("Occupant zone info"); 3587 } 3588 3589 @Test isMediaAudioAllowedInPrimaryZone_byDefault()3590 public void isMediaAudioAllowedInPrimaryZone_byDefault() throws Exception { 3591 CarAudioService service = setUpAudioService(); 3592 3593 expectWithMessage("Media default status") 3594 .that(service.isMediaAudioAllowedInPrimaryZone( 3595 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 3596 .isFalse(); 3597 } 3598 3599 @Test isMediaAudioAllowedInPrimaryZone_afterAllowed()3600 public void isMediaAudioAllowedInPrimaryZone_afterAllowed() throws Exception { 3601 CarAudioService service = setUpAudioService(); 3602 TestPrimaryZoneMediaAudioRequestCallback 3603 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3604 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3605 assignOccupantToAudioZones(); 3606 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3607 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3608 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3609 requestToken.waitForCallback(); 3610 requestToken.reset(); 3611 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3612 requestToken.waitForCallback(); 3613 3614 expectWithMessage("Media allowed status") 3615 .that(service.isMediaAudioAllowedInPrimaryZone( 3616 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 3617 .isTrue(); 3618 } 3619 3620 @Test isMediaAudioAllowedInPrimaryZone_afterDisallowed()3621 public void isMediaAudioAllowedInPrimaryZone_afterDisallowed() throws Exception { 3622 CarAudioService service = setUpAudioService(); 3623 TestPrimaryZoneMediaAudioRequestCallback 3624 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3625 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3626 assignOccupantToAudioZones(); 3627 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3628 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3629 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3630 requestToken.waitForCallback(); 3631 requestToken.reset(); 3632 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ false); 3633 requestToken.waitForCallback(); 3634 3635 expectWithMessage("Media after disallowed status") 3636 .that(service.isMediaAudioAllowedInPrimaryZone( 3637 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 3638 .isFalse(); 3639 } 3640 3641 @Test isMediaAudioAllowedInPrimaryZone_afterUserLogout()3642 public void isMediaAudioAllowedInPrimaryZone_afterUserLogout() throws Exception { 3643 CarAudioService service = setUpAudioService(); 3644 TestPrimaryZoneMediaAudioRequestCallback 3645 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3646 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3647 assignOccupantToAudioZones(); 3648 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3649 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3650 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3651 requestToken.waitForCallback(); 3652 requestToken.reset(); 3653 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3654 requestToken.waitForCallback(); 3655 requestToken.reset(); 3656 simulateLogoutPassengers(); 3657 requestToken.waitForCallback(); 3658 3659 expectWithMessage("Media allowed status after passenger logout") 3660 .that(service.isMediaAudioAllowedInPrimaryZone( 3661 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)).isFalse(); 3662 } 3663 3664 @Test isMediaAudioAllowedInPrimaryZone_afterUserSwitch()3665 public void isMediaAudioAllowedInPrimaryZone_afterUserSwitch() throws Exception { 3666 CarAudioService service = setUpAudioService(); 3667 TestPrimaryZoneMediaAudioRequestCallback 3668 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3669 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3670 assignOccupantToAudioZones(); 3671 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3672 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3673 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3674 requestToken.waitForCallback(); 3675 requestToken.reset(); 3676 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3677 requestToken.waitForCallback(); 3678 requestToken.reset(); 3679 simulatePassengersSwitch(); 3680 requestToken.waitForCallback(); 3681 3682 expectWithMessage("Media allowed status after passenger switch") 3683 .that(service.isMediaAudioAllowedInPrimaryZone( 3684 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)).isFalse(); 3685 } 3686 3687 @Test resetMediaAudioOnPrimaryZone_afterAllowed()3688 public void resetMediaAudioOnPrimaryZone_afterAllowed() throws Exception { 3689 CarAudioService service = setUpAudioService(); 3690 TestPrimaryZoneMediaAudioRequestCallback 3691 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3692 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3693 assignOccupantToAudioZones(); 3694 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3695 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3696 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3697 requestToken.waitForCallback(); 3698 requestToken.reset(); 3699 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3700 requestToken.waitForCallback(); 3701 requestToken.reset(); 3702 3703 boolean reset = service.resetMediaAudioOnPrimaryZone( 3704 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3705 3706 requestToken.waitForCallback(); 3707 expectWithMessage("Reset status").that(reset).isTrue(); 3708 expectWithMessage("Media reset status") 3709 .that(service.isMediaAudioAllowedInPrimaryZone( 3710 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 3711 .isFalse(); 3712 } 3713 3714 @Test cancelMediaAudioOnPrimaryZone_beforeAllowed()3715 public void cancelMediaAudioOnPrimaryZone_beforeAllowed() throws Exception { 3716 CarAudioService service = setUpAudioService(); 3717 TestPrimaryZoneMediaAudioRequestCallback 3718 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3719 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3720 assignOccupantToAudioZones(); 3721 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3722 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3723 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3724 requestToken.waitForCallback(); 3725 requestToken.reset(); 3726 3727 boolean cancel = service.cancelMediaAudioOnPrimaryZone(requestId); 3728 3729 requestToken.waitForCallback(); 3730 expectWithMessage("Cancel status").that(cancel).isTrue(); 3731 expectWithMessage("Canceled media token called audio media request id") 3732 .that(requestToken.mRequestId).isEqualTo(requestId); 3733 expectWithMessage("Canceled media token called audio media request info") 3734 .that(requestToken.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3735 expectWithMessage("Canceled media token called audio media request status") 3736 .that(requestToken.mStatus) 3737 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_CANCELLED); 3738 } 3739 3740 @Test cancelMediaAudioOnPrimaryZone_afterAllowed()3741 public void cancelMediaAudioOnPrimaryZone_afterAllowed() throws Exception { 3742 CarAudioService service = setUpAudioService(); 3743 TestPrimaryZoneMediaAudioRequestCallback 3744 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3745 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3746 assignOccupantToAudioZones(); 3747 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3748 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3749 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3750 requestToken.waitForCallback(); 3751 requestToken.reset(); 3752 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3753 requestToken.waitForCallback(); 3754 requestToken.reset(); 3755 3756 boolean cancel = service.cancelMediaAudioOnPrimaryZone(requestId); 3757 3758 requestToken.waitForCallback(); 3759 expectWithMessage("Cancel status after allowed").that(cancel).isTrue(); 3760 expectWithMessage("Media allowed status after canceled") 3761 .that(service.isMediaAudioAllowedInPrimaryZone( 3762 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 3763 .isFalse(); 3764 } 3765 3766 @Test getZoneIdForAudioFocusInfo_beforeAllowedSharedAudio()3767 public void getZoneIdForAudioFocusInfo_beforeAllowedSharedAudio() throws Exception { 3768 CarAudioService service = setUpAudioService(); 3769 TestPrimaryZoneMediaAudioRequestCallback 3770 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3771 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3772 assignOccupantToAudioZones(); 3773 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3774 service.requestMediaAudioOnPrimaryZone(requestCallback, 3775 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3776 requestToken.waitForCallback(); 3777 3778 expectWithMessage("Not yet shared media user zone") 3779 .that(service.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 3780 .isEqualTo(TEST_REAR_RIGHT_ZONE_ID); 3781 } 3782 3783 @Test getZoneIdForAudioFocusInfo_afterAllowedShareAudio()3784 public void getZoneIdForAudioFocusInfo_afterAllowedShareAudio() throws Exception { 3785 CarAudioService service = setUpAudioService(); 3786 TestPrimaryZoneMediaAudioRequestCallback 3787 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3788 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3789 assignOccupantToAudioZones(); 3790 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3791 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3792 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3793 requestToken.waitForCallback(); 3794 requestToken.reset(); 3795 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3796 requestToken.waitForCallback(); 3797 3798 expectWithMessage("Shared media user zone") 3799 .that(service.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 3800 .isEqualTo(PRIMARY_AUDIO_ZONE); 3801 } 3802 3803 @Test getZoneIdForAudioFocusInfo_afterCanceled()3804 public void getZoneIdForAudioFocusInfo_afterCanceled() throws Exception { 3805 CarAudioService service = setUpAudioService(); 3806 TestPrimaryZoneMediaAudioRequestCallback 3807 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3808 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3809 assignOccupantToAudioZones(); 3810 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3811 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3812 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3813 requestToken.waitForCallback(); 3814 requestToken.reset(); 3815 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3816 requestToken.waitForCallback(); 3817 requestToken.reset(); 3818 service.cancelMediaAudioOnPrimaryZone(requestId); 3819 requestToken.waitForCallback(); 3820 3821 expectWithMessage("Canceled shared media user zone") 3822 .that(service.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 3823 .isEqualTo(TEST_REAR_RIGHT_ZONE_ID); 3824 } 3825 3826 @Test getZoneIdForAudioFocusInfo_afterReset()3827 public void getZoneIdForAudioFocusInfo_afterReset() throws Exception { 3828 CarAudioService service = setUpAudioService(); 3829 TestPrimaryZoneMediaAudioRequestCallback 3830 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3831 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3832 assignOccupantToAudioZones(); 3833 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3834 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 3835 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3836 requestToken.waitForCallback(); 3837 requestToken.reset(); 3838 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 3839 requestToken.waitForCallback(); 3840 requestToken.reset(); 3841 service.resetMediaAudioOnPrimaryZone(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3842 requestToken.waitForCallback(); 3843 3844 expectWithMessage("Reset shared media user zone") 3845 .that(service.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 3846 .isEqualTo(TEST_REAR_RIGHT_ZONE_ID); 3847 } 3848 getOccupantInfo(int occupantZoneId, int occupantType, int seat)3849 private static CarOccupantZoneManager.OccupantZoneInfo getOccupantInfo(int occupantZoneId, 3850 int occupantType, int seat) { 3851 return new CarOccupantZoneManager.OccupantZoneInfo(occupantZoneId, occupantType, seat); 3852 } 3853 3854 @Test getAudioAttributesForVolumeGroup()3855 public void getAudioAttributesForVolumeGroup() throws Exception { 3856 CarAudioService service = setUpAudioService(); 3857 CarVolumeGroupInfo info = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 3858 TEST_PRIMARY_ZONE_GROUP_0); 3859 3860 List<AudioAttributes> audioAttributes = 3861 service.getAudioAttributesForVolumeGroup(info); 3862 3863 expectWithMessage("Volume group audio attributes").that(audioAttributes) 3864 .containsExactly( 3865 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA), 3866 CarAudioContext.getAudioAttributeFromUsage(USAGE_GAME), 3867 CarAudioContext.getAudioAttributeFromUsage(USAGE_UNKNOWN), 3868 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION), 3869 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION_EVENT), 3870 CarAudioContext.getAudioAttributeFromUsage(USAGE_ANNOUNCEMENT)); 3871 } 3872 3873 @Test getAudioAttributesForVolumeGroup_withNullInfo_fails()3874 public void getAudioAttributesForVolumeGroup_withNullInfo_fails() throws Exception { 3875 CarAudioService service = setUpAudioService(); 3876 3877 NullPointerException thrown = 3878 assertThrows(NullPointerException.class, () -> 3879 service.getAudioAttributesForVolumeGroup(/* groupInfo= */ null)); 3880 3881 expectWithMessage("Volume group audio attributes with null info exception") 3882 .that(thrown).hasMessageThat().contains("Car volume group info"); 3883 } 3884 3885 @Test getAudioAttributesForVolumeGroup_withDynamicRoutingDisabled()3886 public void getAudioAttributesForVolumeGroup_withDynamicRoutingDisabled() throws Exception { 3887 CarAudioService nonDynamicAudioService = setUpAudioServiceWithoutDynamicRouting(); 3888 3889 List<AudioAttributes> audioAttributes = nonDynamicAudioService 3890 .getAudioAttributesForVolumeGroup(mTestPrimaryZoneVolumeInfo0); 3891 3892 expectWithMessage("Volume group audio attributes with dynamic routing disabled") 3893 .that(audioAttributes) 3894 .containsExactly(CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA)); 3895 } 3896 3897 @Test onKeyEvent_forInvalidAudioZone()3898 public void onKeyEvent_forInvalidAudioZone() throws Exception { 3899 CarAudioService service = setUpAudioService(); 3900 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 3901 TEST_PRIMARY_ZONE_GROUP_0); 3902 KeyEventListener listener = getAudioKeyEventListener(); 3903 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3904 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3905 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3906 .thenReturn(INVALID_AUDIO_ZONE); 3907 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_UNKNOWN); 3908 3909 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3910 3911 expectWithMessage("Volume group volume after invalid audio zone") 3912 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 3913 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 3914 } 3915 3916 @Test onKeyEvent_forInvalidEvent()3917 public void onKeyEvent_forInvalidEvent() throws Exception { 3918 CarAudioService service = setUpAudioService(); 3919 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 3920 TEST_PRIMARY_ZONE_GROUP_0); 3921 KeyEventListener listener = getAudioKeyEventListener(); 3922 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3923 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3924 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3925 .thenReturn(PRIMARY_AUDIO_ZONE); 3926 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_UNKNOWN); 3927 3928 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3929 3930 expectWithMessage("Volume group volume after unknown key event") 3931 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 3932 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 3933 } 3934 3935 @Test onKeyEvent_forActionUp()3936 public void onKeyEvent_forActionUp() throws Exception { 3937 CarAudioService service = setUpAudioService(); 3938 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 3939 TEST_PRIMARY_ZONE_GROUP_0); 3940 KeyEventListener listener = getAudioKeyEventListener(); 3941 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3942 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3943 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3944 .thenReturn(PRIMARY_AUDIO_ZONE); 3945 KeyEvent keyEvent = new KeyEvent(ACTION_UP, KEYCODE_VOLUME_UP); 3946 3947 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3948 3949 expectWithMessage("Volume group volume after volume up in primary zone in primary group " 3950 + "for action up") 3951 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 3952 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 3953 } 3954 3955 @Test onKeyEvent_forDynamicDevKeyEventEnabledForDefaultConfigForZoneWithDynamicDevices()3956 public void onKeyEvent_forDynamicDevKeyEventEnabledForDefaultConfigForZoneWithDynamicDevices() 3957 throws Exception { 3958 enableVolumeKeyEventsToDynamicDevices(/* enableVolumeKeyEvents= */ true); 3959 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 3960 initServiceAndWaitForComplete(service); 3961 assignOccupantToAudioZones(); 3962 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 3963 KeyEventListener listener = getAudioKeyEventListener(); 3964 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3965 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3966 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3967 .thenReturn(PRIMARY_AUDIO_ZONE); 3968 KeyEvent actionDownKeyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 3969 KeyEvent actionUpKeyEvent = new KeyEvent(ACTION_UP, KEYCODE_VOLUME_UP); 3970 listener.onKeyEvent(actionDownKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3971 3972 listener.onKeyEvent(actionUpKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3973 3974 expectWithMessage("Volume group volume after volume up in primary zone in primary group " 3975 + "for volume group without dynamic devices") 3976 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 3977 .isEqualTo(volumeBefore + 1); 3978 } 3979 3980 @Test 3981 public void onKeyEvent_forDynamicDevKeyEventEnabledForDynamicDeviceConfigForZoneWithDynamicDevices()3982 onKeyEvent_forDynamicDevKeyEventEnabledForDynamicDeviceConfigForZoneWithDynamicDevices() 3983 throws Exception { 3984 enableVolumeKeyEventsToDynamicDevices(/* enableVolumeKeyEvents= */ true); 3985 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 3986 initServiceAndWaitForComplete(service); 3987 assignOccupantToAudioZones(); 3988 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 3989 TestAudioZoneConfigurationsChangeCallback configCallback = 3990 getRegisteredZoneConfigCallback(service); 3991 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 3992 deviceCallback.onAudioDevicesAdded( 3993 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 3994 configCallback.waitForCallback(); 3995 configCallback.reset(); 3996 List<CarAudioZoneConfigInfo> zoneConfigInfos = 3997 service.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 3998 CarAudioZoneConfigInfo zoneConfigSwitchTo = zoneConfigInfos.stream() 3999 .filter(c -> c.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 4000 .findFirst().orElseThrow(); 4001 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 4002 configCallback.waitForCallback(); 4003 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 4004 KeyEventListener listener = getAudioKeyEventListener(); 4005 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4006 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4007 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4008 .thenReturn(PRIMARY_AUDIO_ZONE); 4009 KeyEvent actionDownKeyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 4010 KeyEvent actionUpKeyEvent = new KeyEvent(ACTION_UP, KEYCODE_VOLUME_UP); 4011 listener.onKeyEvent(actionDownKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4012 4013 listener.onKeyEvent(actionUpKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4014 4015 expectWithMessage("Volume after volume up in primary zone in primary group " 4016 + "for volume group with dynamic devices while dynamic device key events enabled") 4017 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 4018 .isEqualTo(volumeBefore + 1); 4019 } 4020 4021 @Test 4022 public void onKeyEvent_forDynDevKeyEventDisabledForDynamicDeviceConfigForZoneWithDynamicDevices()4023 onKeyEvent_forDynDevKeyEventDisabledForDynamicDeviceConfigForZoneWithDynamicDevices() 4024 throws Exception { 4025 enableVolumeKeyEventsToDynamicDevices(/* enableVolumeKeyEvents= */ false); 4026 CarAudioService service = setUpAudioServiceWithDynamicDevices(); 4027 initServiceAndWaitForComplete(service); 4028 assignOccupantToAudioZones(); 4029 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 4030 TestAudioZoneConfigurationsChangeCallback configCallback = 4031 getRegisteredZoneConfigCallback(service); 4032 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 4033 deviceCallback.onAudioDevicesAdded( 4034 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 4035 configCallback.waitForCallback(); 4036 configCallback.reset(); 4037 List<CarAudioZoneConfigInfo> zoneConfigInfos = 4038 service.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 4039 CarAudioZoneConfigInfo zoneConfigSwitchTo = zoneConfigInfos.stream() 4040 .filter(c -> c.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 4041 .findFirst().orElseThrow(); 4042 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 4043 configCallback.waitForCallback(); 4044 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 4045 KeyEventListener listener = getAudioKeyEventListener(); 4046 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4047 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4048 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4049 .thenReturn(PRIMARY_AUDIO_ZONE); 4050 KeyEvent actionDownKeyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 4051 KeyEvent actionUpKeyEvent = new KeyEvent(ACTION_UP, KEYCODE_VOLUME_UP); 4052 listener.onKeyEvent(actionDownKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4053 4054 listener.onKeyEvent(actionUpKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4055 4056 expectWithMessage("Volume after volume up in primary zone in primary group " 4057 + "for volume group with dynamic devices while dynamic device key events disabled") 4058 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 4059 .isEqualTo(volumeBefore); 4060 } 4061 4062 @Test onKeyEvent_forActionDownFollowedByActionUp()4063 public void onKeyEvent_forActionDownFollowedByActionUp() throws Exception { 4064 CarAudioService service = setUpAudioService(); 4065 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4066 TEST_PRIMARY_ZONE_GROUP_0); 4067 KeyEventListener listener = getAudioKeyEventListener(); 4068 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4069 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4070 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4071 .thenReturn(PRIMARY_AUDIO_ZONE); 4072 KeyEvent actionDownKeyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 4073 KeyEvent actionUpKeyEvent = new KeyEvent(ACTION_UP, KEYCODE_VOLUME_UP); 4074 listener.onKeyEvent(actionDownKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4075 4076 listener.onKeyEvent(actionUpKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4077 4078 expectWithMessage("Volume group volume after volume up in primary zone in primary group " 4079 + "for action down then action up") 4080 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4081 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore + 1); 4082 } 4083 4084 @Test onKeyEvent_forVolumeUpEvent_inPrimaryZone()4085 public void onKeyEvent_forVolumeUpEvent_inPrimaryZone() throws Exception { 4086 CarAudioService service = setUpAudioService(); 4087 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4088 TEST_PRIMARY_ZONE_GROUP_0); 4089 KeyEventListener listener = getAudioKeyEventListener(); 4090 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4091 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4092 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4093 .thenReturn(PRIMARY_AUDIO_ZONE); 4094 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 4095 4096 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4097 4098 expectWithMessage("Volume group volume after volume up in primary zone in primary group") 4099 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4100 TEST_PRIMARY_ZONE_GROUP_0)).isGreaterThan(volumeBefore); 4101 } 4102 4103 @Test onKeyEvent_forVolumeDownEvent_inPrimaryZone()4104 public void onKeyEvent_forVolumeDownEvent_inPrimaryZone() throws Exception { 4105 CarAudioService service = setUpAudioService(); 4106 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4107 TEST_PRIMARY_ZONE_GROUP_0); 4108 KeyEventListener listener = getAudioKeyEventListener(); 4109 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4110 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4111 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4112 .thenReturn(PRIMARY_AUDIO_ZONE); 4113 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 4114 4115 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4116 4117 expectWithMessage("Volume group volume after volume down in primary zone in primary group") 4118 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4119 TEST_PRIMARY_ZONE_GROUP_0)).isLessThan(volumeBefore); 4120 } 4121 4122 @Test onKeyEvent_forVolumeDownEvent_inPrimaryZone_forSecondaryGroup()4123 public void onKeyEvent_forVolumeDownEvent_inPrimaryZone_forSecondaryGroup() throws Exception { 4124 CarAudioService service = setUpAudioService(); 4125 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4126 TEST_PRIMARY_ZONE_GROUP_1); 4127 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 4128 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 4129 .setUsage(USAGE_ASSISTANT) 4130 .setDeviceAddress(VOICE_TEST_DEVICE) 4131 .build()) 4132 ); 4133 KeyEventListener listener = getAudioKeyEventListener(); 4134 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4135 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4136 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4137 .thenReturn(PRIMARY_AUDIO_ZONE); 4138 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 4139 4140 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4141 4142 expectWithMessage("Assistant volume group volume after volume down") 4143 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4144 TEST_PRIMARY_ZONE_GROUP_1)).isLessThan(volumeBefore); 4145 } 4146 4147 @Test onKeyEvent_forVolumeDownEvent_inPrimaryZone_withHigherPriority()4148 public void onKeyEvent_forVolumeDownEvent_inPrimaryZone_withHigherPriority() throws Exception { 4149 CarAudioService service = setUpAudioService(); 4150 int primaryGroupVolumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4151 TEST_PRIMARY_ZONE_GROUP_0); 4152 int voiceVolumeGroupBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4153 TEST_PRIMARY_ZONE_GROUP_2); 4154 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 4155 callback.onPlaybackConfigChanged(List.of( 4156 new AudioPlaybackConfigurationBuilder() 4157 .setUsage(USAGE_VOICE_COMMUNICATION) 4158 .setDeviceAddress(CALL_TEST_DEVICE) 4159 .build(), 4160 new AudioPlaybackConfigurationBuilder() 4161 .setUsage(USAGE_MEDIA) 4162 .setDeviceAddress(MEDIA_TEST_DEVICE) 4163 .build()) 4164 ); 4165 KeyEventListener listener = getAudioKeyEventListener(); 4166 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4167 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4168 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4169 .thenReturn(PRIMARY_AUDIO_ZONE); 4170 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 4171 4172 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4173 4174 expectWithMessage("Media volume group volume after volume down") 4175 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4176 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(primaryGroupVolumeBefore); 4177 expectWithMessage("Call volume group volume after volume down") 4178 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4179 TEST_PRIMARY_ZONE_GROUP_2)).isLessThan(voiceVolumeGroupBefore); 4180 } 4181 4182 @Test onKeyEvent_forVolumeDownEvent_inPrimaryZone_withVersionTwoVolumeList()4183 public void onKeyEvent_forVolumeDownEvent_inPrimaryZone_withVersionTwoVolumeList() 4184 throws Exception { 4185 CarAudioService service = setUpCarAudioServiceWithVersionTwoVolumeList(); 4186 int primaryGroupVolumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4187 TEST_PRIMARY_ZONE_GROUP_0); 4188 int voiceVolumeGroupBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4189 TEST_PRIMARY_ZONE_GROUP_2); 4190 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 4191 callback.onPlaybackConfigChanged(List.of( 4192 new AudioPlaybackConfigurationBuilder() 4193 .setUsage(USAGE_VOICE_COMMUNICATION) 4194 .setDeviceAddress(CALL_TEST_DEVICE) 4195 .build(), 4196 new AudioPlaybackConfigurationBuilder() 4197 .setUsage(USAGE_MEDIA) 4198 .setDeviceAddress(MEDIA_TEST_DEVICE) 4199 .build()) 4200 ); 4201 KeyEventListener listener = getAudioKeyEventListener(); 4202 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4203 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4204 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4205 .thenReturn(PRIMARY_AUDIO_ZONE); 4206 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 4207 4208 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4209 4210 expectWithMessage("Media volume group volume after volume down for volume list two") 4211 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4212 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(primaryGroupVolumeBefore); 4213 expectWithMessage("Call volume group volume after volume down for volume list two") 4214 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4215 TEST_PRIMARY_ZONE_GROUP_2)).isLessThan(voiceVolumeGroupBefore); 4216 } 4217 4218 @Test onKeyEvent_forVolumeMuteEvent_inPrimaryZone()4219 public void onKeyEvent_forVolumeMuteEvent_inPrimaryZone() throws Exception { 4220 CarAudioService service = setUpAudioService(); 4221 boolean muteBefore = service.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 4222 TEST_PRIMARY_ZONE_GROUP_0); 4223 KeyEventListener listener = getAudioKeyEventListener(); 4224 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4225 .thenReturn(PRIMARY_OCCUPANT_ZONE); 4226 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 4227 .thenReturn(PRIMARY_AUDIO_ZONE); 4228 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_MUTE); 4229 4230 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4231 4232 expectWithMessage("Volume group volume after volume mute") 4233 .that(service.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 4234 TEST_PRIMARY_ZONE_GROUP_0)).isNotEqualTo(muteBefore); 4235 } 4236 4237 @Test onKeyEvent_forVolumeUpEvent_inSecondaryZone()4238 public void onKeyEvent_forVolumeUpEvent_inSecondaryZone() throws Exception { 4239 CarAudioService service = setUpAudioService(); 4240 int volumeBefore = service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 4241 SECONDARY_ZONE_VOLUME_GROUP_ID); 4242 KeyEventListener listener = getAudioKeyEventListener(); 4243 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4244 .thenReturn(TEST_DRIVER_OCCUPANT_ZONE_ID); 4245 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 4246 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 4247 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 4248 4249 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4250 4251 expectWithMessage("Secondary zone volume group after volume up") 4252 .that(service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 4253 SECONDARY_ZONE_VOLUME_GROUP_ID)) 4254 .isGreaterThan(volumeBefore); 4255 } 4256 4257 @Test onKeyEvent_forVolumeDownEvent_inSecondaryZone()4258 public void onKeyEvent_forVolumeDownEvent_inSecondaryZone() throws Exception { 4259 CarAudioService service = setUpAudioService(); 4260 int volumeBefore = service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 4261 SECONDARY_ZONE_VOLUME_GROUP_ID); 4262 KeyEventListener listener = getAudioKeyEventListener(); 4263 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4264 .thenReturn(TEST_DRIVER_OCCUPANT_ZONE_ID); 4265 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 4266 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 4267 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 4268 4269 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4270 4271 expectWithMessage("Secondary zone volume group after volume down") 4272 .that(service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 4273 SECONDARY_ZONE_VOLUME_GROUP_ID)) 4274 .isLessThan(volumeBefore); 4275 } 4276 4277 @Test onKeyEvent_forVolumeMuteEvent_inSecondaryZone()4278 public void onKeyEvent_forVolumeMuteEvent_inSecondaryZone() throws Exception { 4279 CarAudioService service = setUpAudioService(); 4280 boolean muteBefore = service.isVolumeGroupMuted(TEST_REAR_LEFT_ZONE_ID, 4281 SECONDARY_ZONE_VOLUME_GROUP_ID); 4282 KeyEventListener listener = getAudioKeyEventListener(); 4283 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 4284 .thenReturn(TEST_DRIVER_OCCUPANT_ZONE_ID); 4285 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 4286 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 4287 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_MUTE); 4288 4289 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 4290 4291 expectWithMessage("Secondary zone volume group after volume mute") 4292 .that(service.isVolumeGroupMuted(TEST_REAR_LEFT_ZONE_ID, 4293 SECONDARY_ZONE_VOLUME_GROUP_ID)) 4294 .isNotEqualTo(muteBefore); 4295 } 4296 4297 @Test onAudioDeviceGainsChanged_forPrimaryZone_changesVolume()4298 public void onAudioDeviceGainsChanged_forPrimaryZone_changesVolume() throws Exception { 4299 CarAudioService service = setUpAudioService(); 4300 HalAudioGainCallback callback = getHalAudioGainCallback(); 4301 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(PRIMARY_AUDIO_ZONE, 4302 MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 4303 4304 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), List.of(carGain)); 4305 4306 expectWithMessage("New audio gains for primary zone") 4307 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4308 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 4309 } 4310 4311 @Test onAudioDeviceGainsChanged_forSecondaryZone_changesVolume()4312 public void onAudioDeviceGainsChanged_forSecondaryZone_changesVolume() throws Exception { 4313 CarAudioService service = setUpAudioService(); 4314 HalAudioGainCallback callback = getHalAudioGainCallback(); 4315 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(TEST_REAR_LEFT_ZONE_ID, 4316 SECONDARY_TEST_DEVICE_CONFIG_0, TEST_GAIN_INDEX); 4317 4318 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), List.of(carGain)); 4319 4320 expectWithMessage("New audio gains for secondary zone") 4321 .that(service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 4322 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 4323 } 4324 4325 @Test onAudioDeviceGainsChanged_forIncorrectDeviceAddress_sameVolume()4326 public void onAudioDeviceGainsChanged_forIncorrectDeviceAddress_sameVolume() throws Exception { 4327 CarAudioService service = setUpAudioService(); 4328 HalAudioGainCallback callback = getHalAudioGainCallback(); 4329 int volumeBefore = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4330 TEST_PRIMARY_ZONE_GROUP_0); 4331 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(PRIMARY_AUDIO_ZONE, 4332 SECONDARY_TEST_DEVICE_CONFIG_0, TEST_GAIN_INDEX); 4333 4334 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), List.of(carGain)); 4335 4336 expectWithMessage("Same audio gains for primary zone") 4337 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4338 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 4339 } 4340 4341 @Test onAudioDeviceGainsChanged_forMultipleZones_changesVolume()4342 public void onAudioDeviceGainsChanged_forMultipleZones_changesVolume() throws Exception { 4343 CarAudioService service = setUpAudioService(); 4344 HalAudioGainCallback callback = getHalAudioGainCallback(); 4345 CarAudioGainConfigInfo primaryAudioZoneCarGain = createCarAudioGainConfigInfo( 4346 PRIMARY_AUDIO_ZONE, MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 4347 CarAudioGainConfigInfo secondaryAudioZoneCarGain = createCarAudioGainConfigInfo( 4348 TEST_REAR_LEFT_ZONE_ID, SECONDARY_TEST_DEVICE_CONFIG_0, TEST_GAIN_INDEX); 4349 4350 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), 4351 List.of(primaryAudioZoneCarGain, secondaryAudioZoneCarGain)); 4352 4353 expectWithMessage("New audio gains for primary zone") 4354 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, 4355 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 4356 expectWithMessage("New audio gains for secondary zone") 4357 .that(service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 4358 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 4359 } 4360 4361 @Test onAudioDeviceGainsChanged_withMute_setsSystemMute()4362 public void onAudioDeviceGainsChanged_withMute_setsSystemMute() throws Exception { 4363 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MUTE_AMBIGUITY); 4364 CarAudioService service = setUpAudioService(); 4365 HalAudioGainCallback halAudioGainCallback = getHalAudioGainCallback(); 4366 CarAudioGainConfigInfo primaryAudioZoneCarGain = createCarAudioGainConfigInfo( 4367 PRIMARY_AUDIO_ZONE, MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 4368 4369 halAudioGainCallback.onAudioDeviceGainsChanged(List.of(Reasons.TCU_MUTE), 4370 List.of(primaryAudioZoneCarGain)); 4371 4372 expectWithMessage("Hal mute status for primary zone %s", service 4373 .getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)).that(service 4374 .getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0) 4375 .isMutedBySystem()).isTrue(); 4376 } 4377 4378 @Test onAudioPortsChanged_forMediaBus_changesVolumeRanges()4379 public void onAudioPortsChanged_forMediaBus_changesVolumeRanges() throws Exception { 4380 CarAudioService service = setUpAudioService(); 4381 HalAudioModuleChangeCallback callback = getHalModuleChangeCallback(); 4382 TestCarVolumeEventCallback volumeEventCallback = 4383 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 4384 service.registerCarVolumeEventCallback(volumeEventCallback); 4385 HalAudioDeviceInfo mediaBusDeviceInfo = createHalAudioDeviceInfo( 4386 TEST_MEDIA_PORT_ID, TEST_MEDIA_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 4387 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, MEDIA_TEST_DEVICE); 4388 CarVolumeGroupInfo volumeGroupInfoBefore = 4389 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 4390 4391 callback.onAudioPortsChanged(List.of(mediaBusDeviceInfo)); 4392 4393 CarVolumeGroupInfo volumeGroupInfoAfter = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 4394 TEST_PRIMARY_ZONE_GROUP_0); 4395 expectWithMessage("update audio port for media device") 4396 .that(volumeGroupInfoAfter).isNotEqualTo(volumeGroupInfoBefore); 4397 volumeEventCallback.waitForCallback(); 4398 expectWithMessage("Volume events count after switching zone configuration") 4399 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 4400 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 4401 expectWithMessage("Volume group infos after switching zone configuration") 4402 .that(groupEvent.getCarVolumeGroupInfos()) 4403 .containsExactly(volumeGroupInfoAfter); 4404 } 4405 4406 @Test onAudioPortsChanged_forNavBus_changesVolumeRanges()4407 public void onAudioPortsChanged_forNavBus_changesVolumeRanges() throws Exception { 4408 CarAudioService service = setUpAudioService(); 4409 HalAudioModuleChangeCallback callback = getHalModuleChangeCallback(); 4410 HalAudioDeviceInfo navBusDeviceInfo = createHalAudioDeviceInfo( 4411 TEST_NAV_PORT_ID, TEST_NAV_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 4412 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, NAVIGATION_TEST_DEVICE); 4413 CarVolumeGroupInfo volumeGroupInfoBefore = 4414 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1); 4415 4416 callback.onAudioPortsChanged(List.of(navBusDeviceInfo)); 4417 4418 expectWithMessage("update audio port for nav device") 4419 .that(service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 4420 TEST_PRIMARY_ZONE_GROUP_1)).isNotEqualTo(volumeGroupInfoBefore); 4421 } 4422 4423 @Test onAudioPortsChanged_forMultipleBuses_changesVolumeRanges()4424 public void onAudioPortsChanged_forMultipleBuses_changesVolumeRanges() throws Exception { 4425 CarAudioService service = setUpAudioService(); 4426 HalAudioModuleChangeCallback callback = getHalModuleChangeCallback(); 4427 HalAudioDeviceInfo mediaBusDeviceInfo = createHalAudioDeviceInfo( 4428 TEST_MEDIA_PORT_ID, TEST_MEDIA_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 4429 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, MEDIA_TEST_DEVICE); 4430 HalAudioDeviceInfo navBusDeviceInfo = createHalAudioDeviceInfo( 4431 TEST_NAV_PORT_ID, TEST_NAV_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 4432 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, NAVIGATION_TEST_DEVICE); 4433 CarVolumeGroupInfo mediaVolumeGroupInfoBefore = 4434 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 4435 CarVolumeGroupInfo navVolumeGroupInfoBefore = 4436 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1); 4437 4438 callback.onAudioPortsChanged(List.of(mediaBusDeviceInfo, navBusDeviceInfo)); 4439 4440 expectWithMessage("update audio port for media device") 4441 .that(service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 4442 TEST_PRIMARY_ZONE_GROUP_0)).isNotEqualTo(mediaVolumeGroupInfoBefore); 4443 expectWithMessage("update audio port for nav device") 4444 .that(service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 4445 TEST_PRIMARY_ZONE_GROUP_1)).isNotEqualTo(navVolumeGroupInfoBefore); 4446 } 4447 4448 @Test onAudioPortsChanged_withEmptyDeviceInfoList()4449 public void onAudioPortsChanged_withEmptyDeviceInfoList() throws Exception { 4450 CarAudioService service = setUpAudioService(); 4451 HalAudioModuleChangeCallback callback = getHalModuleChangeCallback(); 4452 TestCarVolumeEventCallback volumeEventCallback = 4453 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 4454 service.registerCarVolumeEventCallback(volumeEventCallback); 4455 4456 callback.onAudioPortsChanged(Collections.EMPTY_LIST); 4457 4458 expectWithMessage("No volume event callback invocation with empty device info list") 4459 .that(volumeEventCallback.waitForCallback()).isFalse(); 4460 } 4461 4462 @Test getActiveAudioAttributesForZone()4463 public void getActiveAudioAttributesForZone() throws Exception { 4464 CarAudioService service = setUpAudioService(); 4465 4466 expectWithMessage("Default active audio attributes").that( 4467 service.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)).isEmpty(); 4468 } 4469 4470 @Test getActiveAudioAttributesForZone_withActiveHalFocus()4471 public void getActiveAudioAttributesForZone_withActiveHalFocus() throws Exception { 4472 when(mAudioManager.requestAudioFocus(any())).thenReturn( 4473 AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 4474 CarAudioService service = setUpAudioService(); 4475 requestHalAudioFocus(USAGE_ALARM); 4476 4477 expectWithMessage("HAL active audio attributes") 4478 .that(service.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)) 4479 .containsExactly(new AudioAttributes.Builder().setUsage(USAGE_ALARM).build()); 4480 } 4481 4482 @Test getActiveAudioAttributesForZone_withActivePlayback()4483 public void getActiveAudioAttributesForZone_withActivePlayback() throws Exception { 4484 CarAudioService service = setUpAudioService(); 4485 mockActivePlayback(); 4486 4487 expectWithMessage("Playback active audio attributes") 4488 .that(service.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)) 4489 .containsExactly(new AudioAttributes.Builder().setUsage(USAGE_MEDIA).build()); 4490 } 4491 4492 @Test getActiveAudioAttributesForZone_withActiveHalAndPlayback()4493 public void getActiveAudioAttributesForZone_withActiveHalAndPlayback() throws Exception { 4494 CarAudioService service = setUpAudioService(); 4495 mockActivePlayback(); 4496 when(mAudioManager.requestAudioFocus(any())).thenReturn( 4497 AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 4498 requestHalAudioFocus(USAGE_VOICE_COMMUNICATION); 4499 4500 expectWithMessage("Playback active audio attributes") 4501 .that(service.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)) 4502 .containsExactly(new AudioAttributes.Builder().setUsage(USAGE_MEDIA).build(), 4503 new AudioAttributes.Builder().setUsage(USAGE_VOICE_COMMUNICATION).build()); 4504 } 4505 4506 @Test getCallStateForZone_forPrimaryZone()4507 public void getCallStateForZone_forPrimaryZone() throws Exception { 4508 when(mMockTelephonyManagerWithoutSubscriptionId.getCallState()) 4509 .thenReturn(TelephonyManager.CALL_STATE_OFFHOOK); 4510 CarAudioService service = setUpAudioService(); 4511 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 4512 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 4513 .thenReturn(TEST_DRIVER_USER_ID, TEST_REAR_RIGHT_USER_ID); 4514 assignOccupantToAudioZones(); 4515 4516 expectWithMessage("Primary zone call state").that( 4517 service.getCallStateForZone(PRIMARY_AUDIO_ZONE)) 4518 .isEqualTo(TelephonyManager.CALL_STATE_OFFHOOK); 4519 } 4520 4521 @Test getCallStateForZone_forNonPrimaryZone()4522 public void getCallStateForZone_forNonPrimaryZone() throws Exception { 4523 CarAudioService service = setUpAudioService(); 4524 when(mMockTelephonyManagerWithoutSubscriptionId.getCallState()) 4525 .thenReturn(TelephonyManager.CALL_STATE_OFFHOOK); 4526 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 4527 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 4528 .thenReturn(TEST_REAR_LEFT_USER_ID, TEST_REAR_RIGHT_USER_ID); 4529 assignOccupantToAudioZones(); 4530 4531 expectWithMessage("Secondary zone call state").that( 4532 service.getCallStateForZone(TEST_REAR_LEFT_ZONE_ID)) 4533 .isEqualTo(TelephonyManager.CALL_STATE_IDLE); 4534 } 4535 4536 @Test getVolumeGroupAndContextCount()4537 public void getVolumeGroupAndContextCount() throws Exception { 4538 CarAudioService useCoreAudioCarAudioService = 4539 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 4540 4541 verify(mAudioManager).registerVolumeGroupCallback(any(), any()); 4542 expectWithMessage("Primary zone car volume group count") 4543 .that(useCoreAudioCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 4544 .isEqualTo(CoreAudioRoutingUtils.getVolumeGroups().size()); 4545 expectWithMessage("Number of contexts") 4546 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds().size()) 4547 .isEqualTo(CoreAudioRoutingUtils.getProductStrategies().size()); 4548 expectWithMessage("Car Audio Contexts") 4549 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds()) 4550 .containsExactly(CoreAudioRoutingUtils.NAV_STRATEGY_ID, 4551 CoreAudioRoutingUtils.MUSIC_STRATEGY_ID, 4552 CoreAudioRoutingUtils.OEM_STRATEGY_ID); 4553 } 4554 4555 @Test 4556 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) getVolumeGroupAndContextCount_withCoreVolumeAndRoutingFromConfigConflictRRO()4557 public void getVolumeGroupAndContextCount_withCoreVolumeAndRoutingFromConfigConflictRRO() 4558 throws Exception { 4559 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(false); 4560 when(mMockResources.getBoolean(audioUseCoreRouting)).thenReturn(false); 4561 CarAudioService useCoreAudioCarAudioService = 4562 setUpCarAudioServiceUsingCoreAudioRoutingAndVolumeInConfigFile(); 4563 4564 verify(mAudioManager).registerVolumeGroupCallback(any(), any()); 4565 expectWithMessage("Primary zone car volume group count with core configs in file and " 4566 + "conflict RRO") 4567 .that(useCoreAudioCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 4568 .isEqualTo(CoreAudioRoutingUtils.getVolumeGroups().size()); 4569 expectWithMessage("Number of contexts with core configs in and " 4570 + "conflict RRO") 4571 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds().size()) 4572 .isEqualTo(CoreAudioRoutingUtils.getProductStrategies().size()); 4573 expectWithMessage("Car Audio Contexts with core configs in and " 4574 + "conflict RRO") 4575 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds()) 4576 .containsExactly(CoreAudioRoutingUtils.NAV_STRATEGY_ID, 4577 CoreAudioRoutingUtils.MUSIC_STRATEGY_ID, 4578 CoreAudioRoutingUtils.OEM_STRATEGY_ID); 4579 } 4580 4581 @Test 4582 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) getVolumeGroupAndContextCount_withCoreVolumeAndRoutingFromConfigNonConflictRRO()4583 public void getVolumeGroupAndContextCount_withCoreVolumeAndRoutingFromConfigNonConflictRRO() 4584 throws Exception { 4585 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(true); 4586 when(mMockResources.getBoolean(audioUseCoreRouting)).thenReturn(true); 4587 CarAudioService useCoreAudioCarAudioService = 4588 setUpCarAudioServiceUsingCoreAudioRoutingAndVolumeInConfigFile(); 4589 4590 verify(mAudioManager).registerVolumeGroupCallback(any(), any()); 4591 expectWithMessage("Primary zone car volume group count with core configs in file and " 4592 + "non conflict RRO") 4593 .that(useCoreAudioCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 4594 .isEqualTo(CoreAudioRoutingUtils.getVolumeGroups().size()); 4595 expectWithMessage("Number of contexts with core configs in file and " 4596 + "non conflict RRO") 4597 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds().size()) 4598 .isEqualTo(CoreAudioRoutingUtils.getProductStrategies().size()); 4599 expectWithMessage("Car Audio Contexts with core configs in file and " 4600 + "non conflict RRO") 4601 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds()) 4602 .containsExactly(CoreAudioRoutingUtils.NAV_STRATEGY_ID, 4603 CoreAudioRoutingUtils.MUSIC_STRATEGY_ID, 4604 CoreAudioRoutingUtils.OEM_STRATEGY_ID); 4605 } 4606 4607 @Test 4608 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) 4609 public void getVolumeGroupAndContextCount_withDisabledCoreVolumeAndRoutingFromConfigAndConflictRRO()4610 getVolumeGroupAndContextCount_withDisabledCoreVolumeAndRoutingFromConfigAndConflictRRO() 4611 throws Exception { 4612 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(true); 4613 when(mMockResources.getBoolean(audioUseCoreRouting)).thenReturn(true); 4614 CarAudioService useCoreAudioCarAudioService = 4615 setUpCarAudioServiceWithCoreAudioRoutingAndVolumeDisabledInConfigFile(); 4616 4617 expectWithMessage("Primary zone car volume group count with core config disabled in and " 4618 + "conflict RRO") 4619 .that(useCoreAudioCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 4620 .isEqualTo(2); 4621 expectWithMessage("Number of contexts with core config disabled in and " 4622 + "conflict RRO") 4623 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds().size()) 4624 .isEqualTo(2); 4625 } 4626 4627 @Test 4628 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) 4629 public void getVolumeGroupAndContextCount_withDisCoreVolumeAndRoutingFromConfigAndNonConflictRRO()4630 getVolumeGroupAndContextCount_withDisCoreVolumeAndRoutingFromConfigAndNonConflictRRO() 4631 throws Exception { 4632 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(false); 4633 when(mMockResources.getBoolean(audioUseCoreRouting)).thenReturn(false); 4634 CarAudioService useCoreAudioCarAudioService = 4635 setUpCarAudioServiceWithCoreAudioRoutingAndVolumeDisabledInConfigFile(); 4636 4637 expectWithMessage("Primary zone car volume group count with core config disabled in and " 4638 + "non conflict RRO") 4639 .that(useCoreAudioCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 4640 .isEqualTo(2); 4641 expectWithMessage("Number of contexts with core config disabled in and " 4642 + "non conflict RRO") 4643 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds().size()) 4644 .isEqualTo(2); 4645 } 4646 4647 @Test registerAudioZonesMirrorStatusCallback()4648 public void registerAudioZonesMirrorStatusCallback() throws Exception { 4649 CarAudioService service = setUpAudioService(); 4650 TestAudioZonesMirrorStatusCallbackCallback callback = 4651 new TestAudioZonesMirrorStatusCallbackCallback(/* count= */ 1); 4652 4653 boolean registered = service.registerAudioZonesMirrorStatusCallback(callback); 4654 4655 expectWithMessage("Audio zones mirror status callback registered status") 4656 .that(registered).isTrue(); 4657 } 4658 4659 @Test registerAudioZonesMirrorStatusCallback_withoutMirroringEnabled()4660 public void registerAudioZonesMirrorStatusCallback_withoutMirroringEnabled() throws Exception { 4661 CarAudioService service = setUpCarAudioServiceWithoutMirroring(); 4662 TestAudioZonesMirrorStatusCallbackCallback callback = 4663 new TestAudioZonesMirrorStatusCallbackCallback(/* count= */ 1); 4664 4665 IllegalStateException thrown = 4666 assertThrows(IllegalStateException.class, () -> 4667 service.registerAudioZonesMirrorStatusCallback(callback)); 4668 4669 expectWithMessage("Disabled audio zones mirror register exception").that(thrown) 4670 .hasMessageThat().contains("Audio zones mirroring is required"); 4671 } 4672 4673 @Test registerAudioZonesMirrorStatusCallback_withNullCallback()4674 public void registerAudioZonesMirrorStatusCallback_withNullCallback() throws Exception { 4675 CarAudioService service = setUpAudioService(); 4676 4677 NullPointerException thrown = 4678 assertThrows(NullPointerException.class, () -> 4679 service.registerAudioZonesMirrorStatusCallback(/* callback= */ null)); 4680 4681 expectWithMessage("Null audio zones mirror register exception").that(thrown) 4682 .hasMessageThat().contains("Audio zones mirror status callback"); 4683 } 4684 4685 @Test unregisterAudioZonesMirrorStatusCallback_withNullCallback()4686 public void unregisterAudioZonesMirrorStatusCallback_withNullCallback() throws Exception { 4687 CarAudioService service = setUpAudioService(); 4688 4689 NullPointerException thrown = 4690 assertThrows(NullPointerException.class, () -> service 4691 .unregisterAudioZonesMirrorStatusCallback(/* callback= */ null)); 4692 4693 expectWithMessage("Null audio zones mirror unregister exception").that(thrown) 4694 .hasMessageThat().contains("Audio zones mirror status callback"); 4695 } 4696 4697 @Test enableMirrorForAudioZones_withNullAudioZones()4698 public void enableMirrorForAudioZones_withNullAudioZones() throws Exception { 4699 CarAudioService service = setUpAudioService(); 4700 4701 NullPointerException thrown = 4702 assertThrows(NullPointerException.class, () -> 4703 service.enableMirrorForAudioZones(/* audioZones= */ null)); 4704 4705 expectWithMessage("Null mirror audio zones exception").that(thrown) 4706 .hasMessageThat().contains("Mirror audio zones"); 4707 } 4708 4709 @Test enableMirrorForAudioZones()4710 public void enableMirrorForAudioZones() throws Exception { 4711 CarAudioService service = setUpAudioService(); 4712 TestAudioZonesMirrorStatusCallbackCallback callback = 4713 getAudioZonesMirrorStatusCallback(service); 4714 assignOccupantToAudioZones(); 4715 4716 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4717 4718 callback.waitForCallback(); 4719 expectWithMessage("Audio mirror approved status").that(callback.getLastStatus()) 4720 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 4721 expectWithMessage("Audio mirror approved zones").that(callback.getLastZoneIds()) 4722 .asList().containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID); 4723 } 4724 4725 @Test enableMirrorForAudioZones_sendsMirrorInfoToAudioHAL()4726 public void enableMirrorForAudioZones_sendsMirrorInfoToAudioHAL() throws Exception { 4727 CarAudioService service = setUpAudioService(); 4728 TestAudioZonesMirrorStatusCallbackCallback callback = 4729 getAudioZonesMirrorStatusCallback(service); 4730 assignOccupantToAudioZones(); 4731 4732 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4733 4734 callback.waitForCallback(); 4735 String audioMirrorInfoCommand = captureAudioMirrorInfoCommand(1); 4736 List<String> commands = Arrays.asList(audioMirrorInfoCommand.split(";")); 4737 String sourceDeviceAddress = removeUpToEquals(commands.get(0)); 4738 expectWithMessage("Audio mirror source info").that(sourceDeviceAddress) 4739 .isEqualTo(MIRROR_TEST_DEVICE); 4740 String destinationsDevices = commands.get(1); 4741 List<String> deviceAddresses = Arrays.asList(removeUpToEquals(destinationsDevices) 4742 .split(",")); 4743 expectWithMessage("Audio mirror zone one info").that(deviceAddresses.get(0)) 4744 .isEqualTo(SECONDARY_TEST_DEVICE_CONFIG_0); 4745 expectWithMessage("Audio mirror zone two info").that(deviceAddresses.get(1)) 4746 .isEqualTo(TERTIARY_TEST_DEVICE_1); 4747 } 4748 4749 @Test enableMirrorForAudioZones_forPrimaryZone_fails()4750 public void enableMirrorForAudioZones_forPrimaryZone_fails() throws Exception { 4751 CarAudioService service = setUpAudioService(); 4752 assignOccupantToAudioZones(); 4753 int[] audioZones = new int[]{TEST_REAR_LEFT_ZONE_ID, PRIMARY_AUDIO_ZONE}; 4754 4755 IllegalArgumentException thrown = 4756 assertThrows(IllegalArgumentException.class, () -> 4757 service.enableMirrorForAudioZones(audioZones)); 4758 4759 expectWithMessage("Mirror audio zones with primary zone exception").that(thrown) 4760 .hasMessageThat().contains("not allowed for primary audio zone"); 4761 } 4762 4763 @Test enableMirrorForAudioZones_forNonAssignedZone_fails()4764 public void enableMirrorForAudioZones_forNonAssignedZone_fails() throws Exception { 4765 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 4766 .thenReturn(UserManagerHelper.USER_NULL); 4767 CarAudioService service = setUpAudioService(); 4768 getAudioZonesMirrorStatusCallback(service); 4769 assignOccupantToAudioZones(); 4770 4771 IllegalStateException thrown = 4772 assertThrows(IllegalStateException.class, () -> 4773 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 4774 4775 expectWithMessage("Mirror audio zones for unoccupied audio zone exception") 4776 .that(thrown).hasMessageThat().contains("must have an active user"); 4777 } 4778 4779 @Test enableMirrorForAudioZones_forRepeatingZones_fails()4780 public void enableMirrorForAudioZones_forRepeatingZones_fails() throws Exception { 4781 CarAudioService service = setUpAudioService(); 4782 assignOccupantToAudioZones(); 4783 int[] audioZones = new int[]{TEST_REAR_LEFT_ZONE_ID, 4784 TEST_REAR_LEFT_ZONE_ID}; 4785 4786 IllegalArgumentException thrown = 4787 assertThrows(IllegalArgumentException.class, () -> 4788 service.enableMirrorForAudioZones(audioZones)); 4789 4790 expectWithMessage("Repeated mirror audio zones exception").that(thrown) 4791 .hasMessageThat().contains("must be unique"); 4792 } 4793 4794 @Test enableMirrorForAudioZones_forAlreadyMirroredZones()4795 public void enableMirrorForAudioZones_forAlreadyMirroredZones() throws Exception { 4796 CarAudioService service = setUpAudioService(); 4797 TestAudioZonesMirrorStatusCallbackCallback callback = 4798 getAudioZonesMirrorStatusCallback(service); 4799 assignOccupantToAudioZones(); 4800 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4801 callback.waitForCallback(); 4802 callback.reset(/* count= */ 1); 4803 4804 IllegalStateException thrown = 4805 assertThrows(IllegalStateException.class, () -> 4806 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 4807 4808 expectWithMessage("Audio mirror exception for repeating request") 4809 .that(thrown).hasMessageThat().contains("is already mirroring"); 4810 4811 } 4812 4813 @Test enableMirrorForAudioZones_afterSharedInPrimaryZone()4814 public void enableMirrorForAudioZones_afterSharedInPrimaryZone() throws Exception { 4815 CarAudioService service = setUpAudioService(); 4816 TestPrimaryZoneMediaAudioRequestCallback 4817 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 4818 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 4819 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 4820 assignOccupantToAudioZones(); 4821 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 4822 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 4823 requestToken.waitForCallback(); 4824 requestToken.reset(); 4825 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 4826 requestToken.waitForCallback(); 4827 requestToken.reset(); 4828 4829 IllegalStateException thrown = 4830 assertThrows(IllegalStateException.class, () -> 4831 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 4832 4833 expectWithMessage("Mirror audio zones while sharing in primary zone exception") 4834 .that(thrown).hasMessageThat().contains("currently sharing to primary zone"); 4835 } 4836 4837 @Test enableMirrorForAudioZones_forInvertedMirrorConfiguration()4838 public void enableMirrorForAudioZones_forInvertedMirrorConfiguration() throws Exception { 4839 CarAudioService service = setUpAudioService(); 4840 TestAudioZonesMirrorStatusCallbackCallback callback = 4841 getAudioZonesMirrorStatusCallback(service); 4842 assignOccupantToAudioZones(); 4843 service.enableMirrorForAudioZones(new int[] {TEST_REAR_RIGHT_ZONE_ID, 4844 TEST_REAR_LEFT_ZONE_ID}); 4845 callback.waitForCallback(); 4846 callback.reset(/* count= */ 1); 4847 4848 IllegalStateException thrown = 4849 assertThrows(IllegalStateException.class, () -> 4850 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 4851 4852 expectWithMessage("Audio mirror exception for inverted zone request") 4853 .that(thrown).hasMessageThat().contains("is already mirroring"); 4854 } 4855 4856 @Test enableMirrorForAudioZones_withNoMoreMirrorDevices_fails()4857 public void enableMirrorForAudioZones_withNoMoreMirrorDevices_fails() throws Exception { 4858 CarAudioService service = setUpAudioService(); 4859 TestAudioZonesMirrorStatusCallbackCallback callback = 4860 getAudioZonesMirrorStatusCallback(service); 4861 assignOccupantToAudioZones(); 4862 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4863 callback.waitForCallback(); 4864 callback.reset(/* count= */ 1); 4865 4866 IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> 4867 service.enableMirrorForAudioZones( 4868 new int[] {TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID})); 4869 4870 expectWithMessage("Audio mirror for out of mirror devices exception") 4871 .that(thrown).hasMessageThat().contains("available mirror output devices"); 4872 } 4873 4874 @Test canEnableAudioMirror_withOutOfMirroringDevices()4875 public void canEnableAudioMirror_withOutOfMirroringDevices() throws Exception { 4876 CarAudioService service = setUpAudioService(); 4877 TestAudioZonesMirrorStatusCallbackCallback callback = 4878 getAudioZonesMirrorStatusCallback(service); 4879 assignOccupantToAudioZones(); 4880 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4881 callback.waitForCallback(); 4882 4883 expectWithMessage("Can audio mirror status").that(service 4884 .canEnableAudioMirror()) 4885 .isEqualTo(AUDIO_MIRROR_OUT_OF_OUTPUT_DEVICES); 4886 } 4887 4888 @Test canEnableAudioMirror_withAudioMirrorEnabledAndNoPendingRequests()4889 public void canEnableAudioMirror_withAudioMirrorEnabledAndNoPendingRequests() throws Exception { 4890 CarAudioService service = setUpAudioService(); 4891 4892 expectWithMessage("Can audio mirror status before audio mirror request") 4893 .that(service.canEnableAudioMirror()) 4894 .isEqualTo(AUDIO_MIRROR_CAN_ENABLE); 4895 } 4896 4897 @Test canEnableAudioMirror_withMirroringDisabled()4898 public void canEnableAudioMirror_withMirroringDisabled() throws Exception { 4899 CarAudioService service = setUpCarAudioServiceWithoutMirroring(); 4900 4901 IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> 4902 service.canEnableAudioMirror()); 4903 4904 expectWithMessage("Can enable audio mirror exception") 4905 .that(thrown).hasMessageThat().contains("Audio zones mirroring is required"); 4906 } 4907 4908 @Test extendAudioMirrorRequest()4909 public void extendAudioMirrorRequest() throws Exception { 4910 CarAudioService service = setUpAudioService(); 4911 TestAudioZonesMirrorStatusCallbackCallback callback = 4912 getAudioZonesMirrorStatusCallback(service); 4913 assignOccupantToAudioZones(); 4914 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4915 callback.waitForCallback(); 4916 callback.reset(1); 4917 4918 service.extendAudioMirrorRequest(requestId, new int[] {TEST_FRONT_ZONE_ID}); 4919 4920 callback.waitForCallback(); 4921 expectWithMessage("Audio mirror approved status").that(callback.getLastStatus()) 4922 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 4923 expectWithMessage("Audio mirror approved zones").that(callback.getLastZoneIds()) 4924 .asList().containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID, 4925 TEST_FRONT_ZONE_ID); 4926 } 4927 4928 @Test extendAudioMirrorRequest_withNullAudioZones()4929 public void extendAudioMirrorRequest_withNullAudioZones() throws Exception { 4930 CarAudioService service = setUpAudioService(); 4931 TestAudioZonesMirrorStatusCallbackCallback callback = 4932 getAudioZonesMirrorStatusCallback(service); 4933 assignOccupantToAudioZones(); 4934 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4935 callback.waitForCallback(); 4936 callback.reset(1); 4937 4938 NullPointerException thrown = 4939 assertThrows(NullPointerException.class, () -> 4940 service.extendAudioMirrorRequest(requestId, 4941 /* audioZones = */ null)); 4942 4943 expectWithMessage("Null audio zones to extend for mirror request exception") 4944 .that(thrown).hasMessageThat().contains("Mirror audio zones"); 4945 } 4946 4947 @Test extendAudioMirrorRequest_withPrimaryAudioZone()4948 public void extendAudioMirrorRequest_withPrimaryAudioZone() throws Exception { 4949 CarAudioService service = setUpAudioService(); 4950 TestAudioZonesMirrorStatusCallbackCallback callback = 4951 getAudioZonesMirrorStatusCallback(service); 4952 assignOccupantToAudioZones(); 4953 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4954 callback.waitForCallback(); 4955 callback.reset(1); 4956 4957 IllegalArgumentException thrown = 4958 assertThrows(IllegalArgumentException.class, () -> 4959 service.extendAudioMirrorRequest(requestId, 4960 new int[] {PRIMARY_AUDIO_ZONE})); 4961 4962 expectWithMessage("Primary audio zone to extend for mirror request exception") 4963 .that(thrown).hasMessageThat().contains( 4964 "Audio mirroring not allowed for primary audio zone"); 4965 } 4966 4967 @Test getAudioZoneConfigInfos()4968 public void getAudioZoneConfigInfos() throws Exception { 4969 CarAudioService service = setUpAudioService(); 4970 4971 List<CarAudioZoneConfigInfo> zoneConfigInfos = 4972 service.getAudioZoneConfigInfos(TEST_REAR_LEFT_ZONE_ID); 4973 4974 List<String> zoneConfigNames = zoneConfigInfos.stream().map(cf -> cf.getName()).toList(); 4975 expectWithMessage("Zone configurations for secondary zone").that(zoneConfigNames) 4976 .containsExactly(SECONDARY_ZONE_CONFIG_NAME_1, SECONDARY_ZONE_CONFIG_NAME_2); 4977 } 4978 4979 @Test getCurrentAudioZoneConfigInfo()4980 public void getCurrentAudioZoneConfigInfo() throws Exception { 4981 CarAudioService service = setUpAudioService(); 4982 4983 CarAudioZoneConfigInfo currentZoneConfigInfo = 4984 service.getCurrentAudioZoneConfigInfo(TEST_REAR_LEFT_ZONE_ID); 4985 4986 expectWithMessage("Name of current zone configuration for secondary zone") 4987 .that(currentZoneConfigInfo.getName()).isEqualTo(SECONDARY_ZONE_CONFIG_NAME_1); 4988 } 4989 4990 @Test switchZoneToConfig()4991 public void switchZoneToConfig() throws Exception { 4992 CarAudioService service = setUpAudioService(); 4993 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 4994 assignOccupantToAudioZones(); 4995 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 4996 TEST_REAR_LEFT_ZONE_ID); 4997 4998 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 4999 5000 callback.waitForCallback(); 5001 expectWithMessage("Updated zone configuration") 5002 .that(callback.getZoneConfig()) 5003 .isEqualTo(getUpdatedCarAudioZoneConfigInfo(zoneConfigSwitchTo, service)); 5004 expectWithMessage("Zone configuration switching status") 5005 .that(callback.getSwitchStatus()).isTrue(); 5006 } 5007 5008 @Test switchZoneToConfig_forNonAssignedZone_fails()5009 public void switchZoneToConfig_forNonAssignedZone_fails() throws Exception { 5010 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 5011 .thenReturn(UserManagerHelper.USER_NULL); 5012 CarAudioService service = setUpAudioService(); 5013 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5014 assignOccupantToAudioZones(); 5015 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 5016 TEST_REAR_LEFT_ZONE_ID); 5017 5018 IllegalStateException thrown = 5019 assertThrows(IllegalStateException.class, () -> 5020 service.switchZoneToConfig(zoneConfigSwitchTo, callback)); 5021 5022 expectWithMessage("Switching zone configuration for unoccupied audio zone exception") 5023 .that(thrown).hasMessageThat().contains("must have an active user"); 5024 } 5025 5026 @Test switchZoneToConfig_afterSharedInPrimaryZone_fails()5027 public void switchZoneToConfig_afterSharedInPrimaryZone_fails() throws Exception { 5028 CarAudioService service = setUpAudioService(); 5029 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5030 TestPrimaryZoneMediaAudioRequestCallback 5031 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 5032 service.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 5033 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 5034 assignOccupantToAudioZones(); 5035 long requestId = service.requestMediaAudioOnPrimaryZone(requestCallback, 5036 TEST_REAR_LEFT_PASSENGER_OCCUPANT); 5037 requestToken.waitForCallback(); 5038 requestToken.reset(); 5039 service.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allow= */ true); 5040 requestToken.waitForCallback(); 5041 requestToken.reset(); 5042 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 5043 TEST_REAR_LEFT_ZONE_ID); 5044 5045 IllegalStateException thrown = 5046 assertThrows(IllegalStateException.class, () -> 5047 service.switchZoneToConfig(zoneConfigSwitchTo, callback)); 5048 5049 expectWithMessage("Switching zone configuration while sharing in primary zone exception") 5050 .that(thrown).hasMessageThat().contains("currently sharing to primary zone"); 5051 } 5052 5053 @Test switchZoneToConfig_afterMirroring_fails()5054 public void switchZoneToConfig_afterMirroring_fails() throws Exception { 5055 CarAudioService service = setUpAudioService(); 5056 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5057 TestAudioZonesMirrorStatusCallbackCallback mirrorCallback = 5058 getAudioZonesMirrorStatusCallback(service); 5059 assignOccupantToAudioZones(); 5060 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5061 mirrorCallback.waitForCallback(); 5062 mirrorCallback.reset(/* count= */ 1); 5063 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 5064 TEST_REAR_LEFT_ZONE_ID); 5065 5066 IllegalStateException thrown = 5067 assertThrows(IllegalStateException.class, () -> 5068 service.switchZoneToConfig(zoneConfigSwitchTo, callback)); 5069 5070 expectWithMessage("Switching zone configuration while audio mirroring").that(thrown) 5071 .hasMessageThat().contains("currently in a mirroring configuration"); 5072 } 5073 5074 @Test switchZoneToConfig_withPendingFocus_regainsFocus()5075 public void switchZoneToConfig_withPendingFocus_regainsFocus() throws Exception { 5076 CarAudioService service = setUpAudioService(); 5077 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5078 assignOccupantToAudioZones(); 5079 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 5080 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 5081 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 5082 TEST_REAR_RIGHT_ZONE_ID); 5083 5084 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 5085 5086 callback.waitForCallback(); 5087 expectWithMessage("Updated zone configuration with pending focus") 5088 .that(callback.getZoneConfig()) 5089 .isEqualTo(getUpdatedCarAudioZoneConfigInfo(zoneConfigSwitchTo, service)); 5090 expectWithMessage("Zone configuration switching status with pending focus") 5091 .that(callback.getSwitchStatus()).isTrue(); 5092 List<Integer> focusChanges = getFocusChanges(audioFocusInfo); 5093 expectWithMessage("Media audio focus changes after switching zone") 5094 .that(focusChanges).containsExactly(AUDIOFOCUS_LOSS_TRANSIENT, AUDIOFOCUS_GAIN); 5095 } 5096 5097 @Test switchZoneToConfig_withPendingFocus_updatesDuckingInfo()5098 public void switchZoneToConfig_withPendingFocus_updatesDuckingInfo() throws Exception { 5099 CarAudioService service = setUpAudioService(); 5100 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5101 assignOccupantToAudioZones(); 5102 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 5103 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 5104 ArgumentCaptor<List<CarDuckingInfo>> carDuckingInfosCaptor = 5105 ArgumentCaptor.forClass(List.class); 5106 verify(mAudioControlWrapperAidl).onDevicesToDuckChange(carDuckingInfosCaptor.capture()); 5107 verifyMediaDuckingInfoInZone(carDuckingInfosCaptor, TEST_REAR_RIGHT_ZONE_ID, 5108 " before switching zone"); 5109 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 5110 TEST_REAR_RIGHT_ZONE_ID); 5111 5112 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 5113 5114 callback.waitForCallback(); 5115 expectWithMessage("Updated zone configuration with pending focus") 5116 .that(callback.getZoneConfig()) 5117 .isEqualTo(getUpdatedCarAudioZoneConfigInfo(zoneConfigSwitchTo, service)); 5118 expectWithMessage("Zone configuration switching status with pending focus") 5119 .that(callback.getSwitchStatus()).isTrue(); 5120 verify(mAudioControlWrapperAidl, times(2)) 5121 .onDevicesToDuckChange(carDuckingInfosCaptor.capture()); 5122 verifyMediaDuckingInfoInZone(carDuckingInfosCaptor, TEST_REAR_RIGHT_ZONE_ID, 5123 " after switching zone"); 5124 } 5125 5126 @Test switchZoneToConfig_withCurrentZoneConfigAndPendingFocus_notLoseAndRegainFocus()5127 public void switchZoneToConfig_withCurrentZoneConfigAndPendingFocus_notLoseAndRegainFocus() 5128 throws Exception { 5129 CarAudioService service = setUpAudioService(); 5130 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5131 assignOccupantToAudioZones(); 5132 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 5133 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 5134 CarAudioZoneConfigInfo currentZoneConfig = 5135 service.getCurrentAudioZoneConfigInfo(TEST_REAR_RIGHT_ZONE_ID); 5136 5137 service.switchZoneToConfig(currentZoneConfig, callback); 5138 5139 callback.waitForCallback(); 5140 expectWithMessage("Updated zone configuration with current configuration") 5141 .that(callback.getZoneConfig()).isEqualTo(currentZoneConfig); 5142 expectWithMessage("Zone configuration switching status with current configuration") 5143 .that(callback.getSwitchStatus()).isTrue(); 5144 verify(mAudioManager, never()).dispatchAudioFocusChange(eq(audioFocusInfo), anyInt(), 5145 any(AudioPolicy.class)); 5146 } 5147 5148 @Test switchZoneToConfig_withVolumeGroupEventCallbackRegistered_invokesEvent()5149 public void switchZoneToConfig_withVolumeGroupEventCallbackRegistered_invokesEvent() 5150 throws Exception { 5151 CarAudioService service = setUpAudioService(); 5152 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5153 TestCarVolumeEventCallback volumeEventCallback = 5154 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 5155 assignOccupantToAudioZones(); 5156 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 5157 TEST_REAR_LEFT_ZONE_ID); 5158 service.registerCarVolumeEventCallback(volumeEventCallback); 5159 5160 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 5161 5162 callback.waitForCallback(); 5163 expectWithMessage("Updated zone configuration") 5164 .that(callback.getZoneConfig()) 5165 .isEqualTo(getUpdatedCarAudioZoneConfigInfo(zoneConfigSwitchTo, service)); 5166 expectWithMessage("Zone configuration switching status") 5167 .that(callback.getSwitchStatus()).isTrue(); 5168 volumeEventCallback.waitForCallback(); 5169 expectWithMessage("Volume events count after switching zone configuration") 5170 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 5171 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 5172 expectWithMessage("Volume event type after switching zone configuration") 5173 .that(groupEvent.getEventTypes()) 5174 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_ZONE_CONFIGURATION_CHANGED); 5175 expectWithMessage("Volume group infos after switching zone configuration") 5176 .that(groupEvent.getCarVolumeGroupInfos()) 5177 .containsExactly(mTestSecondaryZoneConfig1VolumeInfo0, 5178 mTestSecondaryZoneConfig1VolumeInfo1); 5179 } 5180 5181 @Test switchZoneToConfig_updatesVolumeGroupInfos()5182 public void switchZoneToConfig_updatesVolumeGroupInfos() 5183 throws Exception { 5184 CarAudioService service = setUpAudioService(); 5185 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5186 assignOccupantToAudioZones(); 5187 Log.e(TAG, "Current volume group " + service.getVolumeGroupInfosForZone( 5188 TEST_REAR_LEFT_ZONE_ID)); 5189 expectWithMessage("Volume group infos before switching zone configuration") 5190 .that(service.getVolumeGroupInfosForZone(TEST_REAR_LEFT_ZONE_ID)) 5191 .containsExactly(mTestSecondaryConfig0VolumeGroup0Info); 5192 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 5193 TEST_REAR_LEFT_ZONE_ID); 5194 5195 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 5196 5197 callback.waitForCallback(); 5198 expectWithMessage("Volume group infos after switching zone configuration") 5199 .that(service.getVolumeGroupInfosForZone(TEST_REAR_LEFT_ZONE_ID)) 5200 .containsExactly(mTestSecondaryZoneConfig1VolumeInfo0, 5201 mTestSecondaryZoneConfig1VolumeInfo1); 5202 } 5203 5204 @Test switchZoneToConfig_withDynamicDevicesFlagEnabled()5205 public void switchZoneToConfig_withDynamicDevicesFlagEnabled() throws Exception { 5206 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 5207 CarAudioService service = setUpAudioService(); 5208 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5209 assignOccupantToAudioZones(); 5210 CarAudioZoneConfigInfo previousConfig = service 5211 .getCurrentAudioZoneConfigInfo(TEST_REAR_LEFT_ZONE_ID); 5212 CarAudioZoneConfigInfo zoneConfigSwitchTo = 5213 getZoneConfigToSwitch(service, TEST_REAR_LEFT_ZONE_ID); 5214 5215 service.switchZoneToConfig(zoneConfigSwitchTo, callback); 5216 5217 callback.waitForCallback(); 5218 expectWithMessage("Updated zone configuration, with dynamic devices enabled") 5219 .that(callback.getZoneConfig().hasSameConfigInfo(zoneConfigSwitchTo)).isTrue(); 5220 expectWithMessage("Zone configuration switched status, with dynamic devices enabled") 5221 .that(callback.getSwitchStatus()).isTrue(); 5222 CarAudioZoneConfigInfo switchedInfo = service 5223 .getCurrentAudioZoneConfigInfo(TEST_REAR_LEFT_ZONE_ID); 5224 expectWithMessage("Switched config active status") 5225 .that(switchedInfo.isActive()).isTrue(); 5226 expectWithMessage("Switched config selected status") 5227 .that(switchedInfo.isSelected()).isTrue(); 5228 CarAudioZoneConfigInfo previousUpdated = 5229 getUpdatedCarAudioZoneConfigInfo(previousConfig, service); 5230 expectWithMessage("Previous config active status") 5231 .that(previousUpdated.isActive()).isTrue(); 5232 expectWithMessage("Previous config selected status") 5233 .that(previousUpdated.isSelected()).isFalse(); 5234 } 5235 5236 @Test switchZoneToConfig_toDynamicConfig_withDynamicDevicesInMultipleZones()5237 public void switchZoneToConfig_toDynamicConfig_withDynamicDevicesInMultipleZones() 5238 throws Exception { 5239 setUpTempFileForAudioConfiguration( 5240 R.raw.car_audio_configuration_with_dynamic_devices_for_primary_zone); 5241 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 5242 CarAudioService dynamicDeviceService = 5243 setUpAudioServiceWithDynamicDevices(mTempCarAudioConfigFile, 5244 mTempCarAudioFadeConfigFile); 5245 initServiceAndWaitForComplete(dynamicDeviceService); 5246 assignOccupantToAudioZones(); 5247 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5248 TestAudioZoneConfigurationsChangeCallback configCallback = 5249 getRegisteredZoneConfigCallback(dynamicDeviceService); 5250 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5251 deviceCallback.onAudioDevicesAdded( 5252 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5253 configCallback.waitForCallback(); 5254 configCallback.reset(); 5255 List<CarAudioZoneConfigInfo> zoneConfigInfos = 5256 dynamicDeviceService.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 5257 CarAudioZoneConfigInfo zoneConfigSwitchTo = zoneConfigInfos.stream() 5258 .filter(c -> c.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5259 .findFirst().orElseThrow(); 5260 5261 dynamicDeviceService.switchZoneToConfig(zoneConfigSwitchTo, callback); 5262 5263 configCallback.waitForCallback(); 5264 callback.waitForCallback(); 5265 CarAudioZoneConfigInfo secondaryZoneBTConfig = configCallback.mInfos.stream() 5266 .filter(c -> c.getName().equals(SECONDARY_ZONE_BT_CONFIG_NAME)) 5267 .findFirst().orElseThrow(); 5268 expectWithMessage("Inactive dynamic config due to dynamic device being used") 5269 .that(secondaryZoneBTConfig.isActive()).isFalse(); 5270 } 5271 5272 @Test switchZoneToConfig_backFromDynamicConfig_withDynamicDevicesInMultipleZones()5273 public void switchZoneToConfig_backFromDynamicConfig_withDynamicDevicesInMultipleZones() 5274 throws Exception { 5275 setUpTempFileForAudioConfiguration( 5276 R.raw.car_audio_configuration_with_dynamic_devices_for_primary_zone); 5277 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 5278 CarAudioService dynamicDeviceService = 5279 setUpAudioServiceWithDynamicDevices(mTempCarAudioConfigFile, 5280 mTempCarAudioFadeConfigFile); 5281 initServiceAndWaitForComplete(dynamicDeviceService); 5282 assignOccupantToAudioZones(); 5283 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 5284 TestAudioZoneConfigurationsChangeCallback configCallback = 5285 getRegisteredZoneConfigCallback(dynamicDeviceService); 5286 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5287 deviceCallback.onAudioDevicesAdded( 5288 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5289 configCallback.waitForCallback(); 5290 configCallback.reset(); 5291 List<CarAudioZoneConfigInfo> zoneConfigInfos = 5292 dynamicDeviceService.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 5293 CarAudioZoneConfigInfo dynamicConfig = zoneConfigInfos.stream() 5294 .filter(c -> c.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5295 .findFirst().orElseThrow(); 5296 dynamicDeviceService.switchZoneToConfig(dynamicConfig, callback); 5297 callback.waitForCallback(); 5298 callback.reset(); 5299 configCallback.waitForCallback(); 5300 configCallback.reset(); 5301 CarAudioZoneConfigInfo defaultConfig = zoneConfigInfos.stream() 5302 .filter(CarAudioZoneConfigInfo::isDefault).findFirst().orElseThrow(); 5303 5304 dynamicDeviceService.switchZoneToConfig(defaultConfig, callback); 5305 5306 configCallback.waitForCallback(); 5307 callback.waitForCallback(); 5308 CarAudioZoneConfigInfo secondaryZoneBTConfig = configCallback.mInfos.stream() 5309 .filter(c -> c.getName().equals(SECONDARY_ZONE_BT_CONFIG_NAME)) 5310 .findFirst().orElseThrow(); 5311 expectWithMessage("Re-activated dynamic config due to dynamic device not used") 5312 .that(secondaryZoneBTConfig.isActive()).isTrue(); 5313 } 5314 5315 @Test registerAudioZoneConfigsChangeCallback()5316 public void registerAudioZoneConfigsChangeCallback() throws Exception { 5317 IAudioZoneConfigurationsChangeCallback callback = 5318 new TestAudioZoneConfigurationsChangeCallback(); 5319 CarAudioService service = setUpAudioService(); 5320 5321 boolean registered = service.registerAudioZoneConfigsChangeCallback(callback); 5322 5323 expectWithMessage("Car audio zone configuration change register status") 5324 .that(registered).isTrue(); 5325 } 5326 5327 @Test registerAudioZoneConfigsChangeCallback_multipleTimes()5328 public void registerAudioZoneConfigsChangeCallback_multipleTimes() throws Exception { 5329 IAudioZoneConfigurationsChangeCallback callback = 5330 new TestAudioZoneConfigurationsChangeCallback(); 5331 CarAudioService service = setUpAudioService(); 5332 service.registerAudioZoneConfigsChangeCallback(callback); 5333 5334 boolean registered = service.registerAudioZoneConfigsChangeCallback(callback); 5335 5336 expectWithMessage("Car audio zone configuration change re-register status") 5337 .that(registered).isTrue(); 5338 } 5339 5340 @Test registerAudioZoneConfigsChangeCallback_withNullCallback()5341 public void registerAudioZoneConfigsChangeCallback_withNullCallback() throws Exception { 5342 CarAudioService service = setUpAudioService(); 5343 5344 NullPointerException thrown = assertThrows(NullPointerException.class, 5345 () -> service.registerAudioZoneConfigsChangeCallback(null)); 5346 5347 expectWithMessage("Car audio zone configuration change registration exception") 5348 .that(thrown).hasMessageThat().contains("Car audio zone configs"); 5349 } 5350 5351 @Test onAudioDevicesAdded_forDynamicDevicesEnabled()5352 public void onAudioDevicesAdded_forDynamicDevicesEnabled() throws Exception { 5353 CarAudioService audioServiceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 5354 initServiceAndWaitForComplete(audioServiceWithDynamicDevices); 5355 TestAudioZoneConfigurationsChangeCallback 5356 configCallback = getRegisteredZoneConfigCallback(audioServiceWithDynamicDevices); 5357 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5358 5359 deviceCallback.onAudioDevicesAdded( 5360 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5361 5362 configCallback.waitForCallback(); 5363 List<CarAudioZoneConfigInfo> zoneConfigInfos = 5364 audioServiceWithDynamicDevices.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 5365 CarAudioZoneConfigInfo btConfig = zoneConfigInfos.stream() 5366 .filter(config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5367 .findFirst().orElseThrow(); 5368 expectWithMessage("Enabled bluetooth configuration").that(btConfig.isActive()).isTrue(); 5369 } 5370 5371 @Test onAudioDevicesAdded_forDynamicDevicesEnabled_triggersCallback()5372 public void onAudioDevicesAdded_forDynamicDevicesEnabled_triggersCallback() throws Exception { 5373 CarAudioService serviceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 5374 initServiceAndWaitForComplete(serviceWithDynamicDevices); 5375 TestAudioZoneConfigurationsChangeCallback 5376 configCallback = getRegisteredZoneConfigCallback(serviceWithDynamicDevices); 5377 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5378 5379 deviceCallback.onAudioDevicesAdded( 5380 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5381 5382 configCallback.waitForCallback(); 5383 expectWithMessage("Enabled dynamic config callback status").that(configCallback.mStatus) 5384 .isEqualTo(CONFIG_STATUS_CHANGED); 5385 CarAudioZoneConfigInfo btConfig = configCallback.mInfos.stream() 5386 .filter(config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5387 .findFirst().orElseThrow(); 5388 expectWithMessage("Callback enabled bluetooth configuration").that(btConfig.isActive()) 5389 .isTrue(); 5390 } 5391 5392 @Test onAudioDevicesAdded_forDynamicDevicesEnabled_withAudioServerDown()5393 public void onAudioDevicesAdded_forDynamicDevicesEnabled_withAudioServerDown() 5394 throws Exception { 5395 CarAudioService audioServiceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 5396 initServiceAndWaitForComplete(audioServiceWithDynamicDevices); 5397 TestAudioZoneConfigurationsChangeCallback 5398 configCallback = getRegisteredZoneConfigCallback(audioServiceWithDynamicDevices); 5399 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5400 audioServiceWithDynamicDevices.releaseAudioCallbacks(/* isAudioServerDown= */ true); 5401 5402 deviceCallback.onAudioDevicesAdded( 5403 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5404 5405 configCallback.waitForCallback(); 5406 List<CarAudioZoneConfigInfo> zoneConfigInfos = 5407 audioServiceWithDynamicDevices.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 5408 CarAudioZoneConfigInfo btConfig = zoneConfigInfos.stream() 5409 .filter(config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5410 .findFirst().orElseThrow(); 5411 expectWithMessage("Disabled bluetooth configuration with audio server down") 5412 .that(btConfig.isActive()).isFalse(); 5413 } 5414 5415 @Test onAudioDevicesRemoved_forDynamicDevicesEnabled_triggersCallback()5416 public void onAudioDevicesRemoved_forDynamicDevicesEnabled_triggersCallback() 5417 throws Exception { 5418 CarAudioService serviceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 5419 initServiceAndWaitForComplete(serviceWithDynamicDevices); 5420 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5421 TestAudioZoneConfigurationsChangeCallback 5422 configCallback = getRegisteredZoneConfigCallback(serviceWithDynamicDevices); 5423 deviceCallback.onAudioDevicesAdded( 5424 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5425 configCallback.waitForCallback(); 5426 configCallback.reset(); 5427 5428 deviceCallback.onAudioDevicesRemoved( 5429 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5430 5431 configCallback.waitForCallback(); 5432 expectWithMessage("Disabled dynamic config callback status").that(configCallback.mStatus) 5433 .isEqualTo(CONFIG_STATUS_CHANGED); 5434 CarAudioZoneConfigInfo btConfig = configCallback.mInfos.stream() 5435 .filter(config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5436 .findFirst().orElseThrow(); 5437 expectWithMessage("Callback disabled bluetooth configuration").that(btConfig.isActive()) 5438 .isFalse(); 5439 } 5440 5441 @Test onAudioDevicesRemoved_afterAdded_forDynamicDevicesEnabled()5442 public void onAudioDevicesRemoved_afterAdded_forDynamicDevicesEnabled() throws Exception { 5443 CarAudioService audioServiceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 5444 initServiceAndWaitForComplete(audioServiceWithDynamicDevices); 5445 TestAudioZoneConfigurationsChangeCallback 5446 configCallback = getRegisteredZoneConfigCallback(audioServiceWithDynamicDevices); 5447 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5448 deviceCallback.onAudioDevicesAdded( 5449 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5450 configCallback.waitForCallback(); 5451 configCallback.reset(); 5452 5453 deviceCallback.onAudioDevicesRemoved( 5454 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5455 5456 configCallback.waitForCallback(); 5457 List<CarAudioZoneConfigInfo> zoneConfigInfos = 5458 audioServiceWithDynamicDevices.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 5459 CarAudioZoneConfigInfo btConfig = zoneConfigInfos.stream() 5460 .filter(config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5461 .findFirst().orElseThrow(); 5462 expectWithMessage("Enabled bluetooth configuration after removed device") 5463 .that(btConfig.isActive()).isFalse(); 5464 } 5465 5466 @Test onAudioDevicesRemoved_forSelectedDynamicDevicesEnabled_triggersCallback()5467 public void onAudioDevicesRemoved_forSelectedDynamicDevicesEnabled_triggersCallback() 5468 throws Exception { 5469 SwitchAudioZoneConfigCallbackImpl switchCallback = new SwitchAudioZoneConfigCallbackImpl(); 5470 CarAudioService serviceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 5471 initServiceAndWaitForComplete(serviceWithDynamicDevices); 5472 assignOccupantToAudioZones(); 5473 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5474 TestAudioZoneConfigurationsChangeCallback 5475 configCallback = getRegisteredZoneConfigCallback(serviceWithDynamicDevices); 5476 deviceCallback.onAudioDevicesAdded( 5477 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5478 configCallback.waitForCallback(); 5479 configCallback.reset(); 5480 List<CarAudioZoneConfigInfo> infos = 5481 serviceWithDynamicDevices.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 5482 CarAudioZoneConfigInfo btConfig = infos.stream().filter( 5483 config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5484 .findFirst().orElseThrow(); 5485 serviceWithDynamicDevices.switchZoneToConfig(btConfig, switchCallback); 5486 switchCallback.waitForCallback(); 5487 5488 deviceCallback.onAudioDevicesRemoved( 5489 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5490 5491 configCallback.waitForCallback(); 5492 CarAudioZoneConfigInfo updatedBTConfig = configCallback.mInfos.stream().filter( 5493 config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5494 .findFirst().orElseThrow(); 5495 expectWithMessage("Disabled selected dynamic config callback status") 5496 .that(configCallback.mStatus).isEqualTo(CONFIG_STATUS_AUTO_SWITCHED); 5497 expectWithMessage("Callback disabled selected bluetooth configuration") 5498 .that(updatedBTConfig.isActive()).isFalse(); 5499 } 5500 5501 @Test onAudioDevicesRemoved_forDynamicDevicesEnabled_afterAddedWithAudioServerDown()5502 public void onAudioDevicesRemoved_forDynamicDevicesEnabled_afterAddedWithAudioServerDown() 5503 throws Exception { 5504 CarAudioService audioServiceWithDynamicDevices = setUpAudioServiceWithDynamicDevices(); 5505 initServiceAndWaitForComplete(audioServiceWithDynamicDevices); 5506 TestAudioZoneConfigurationsChangeCallback 5507 configCallback = getRegisteredZoneConfigCallback(audioServiceWithDynamicDevices); 5508 AudioDeviceCallback deviceCallback = captureAudioDeviceCallback(); 5509 deviceCallback.onAudioDevicesAdded( 5510 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5511 configCallback.waitForCallback(); 5512 configCallback.reset(); 5513 audioServiceWithDynamicDevices.releaseAudioCallbacks(/* isAudioServerDown= */ true); 5514 5515 deviceCallback.onAudioDevicesRemoved( 5516 new AudioDeviceInfo[]{mCarAudioDeviceUtils.mBTAudioDeviceInfo}); 5517 5518 configCallback.waitForCallback(); 5519 List<CarAudioZoneConfigInfo> zoneConfigInfos = 5520 audioServiceWithDynamicDevices.getAudioZoneConfigInfos(PRIMARY_AUDIO_ZONE); 5521 CarAudioZoneConfigInfo btConfig = zoneConfigInfos.stream() 5522 .filter(config -> config.getName().equals(PRIMARY_CONFIG_NAME_DYNAMIC_DEVICES)) 5523 .findFirst().orElseThrow(); 5524 expectWithMessage( 5525 "Enabled bluetooth configuration after removed device with audio server down") 5526 .that(btConfig.isActive()).isTrue(); 5527 } 5528 5529 @Test unregisterAudioZoneConfigsChangeCallback()5530 public void unregisterAudioZoneConfigsChangeCallback() throws Exception { 5531 IAudioZoneConfigurationsChangeCallback callback = 5532 new TestAudioZoneConfigurationsChangeCallback(); 5533 CarAudioService service = setUpAudioService(); 5534 service.registerAudioZoneConfigsChangeCallback(callback); 5535 5536 boolean registered = service.unregisterAudioZoneConfigsChangeCallback(callback); 5537 5538 expectWithMessage("Car audio zone configuration change un-register status") 5539 .that(registered).isTrue(); 5540 } 5541 5542 @Test unregisterAudioZoneConfigsChangeCallback_afterUnregister_fails()5543 public void unregisterAudioZoneConfigsChangeCallback_afterUnregister_fails() throws Exception { 5544 IAudioZoneConfigurationsChangeCallback callback = 5545 new TestAudioZoneConfigurationsChangeCallback(); 5546 CarAudioService service = setUpAudioService(); 5547 service.registerAudioZoneConfigsChangeCallback(callback); 5548 service.unregisterAudioZoneConfigsChangeCallback(callback); 5549 5550 boolean registered = service.unregisterAudioZoneConfigsChangeCallback(callback); 5551 5552 expectWithMessage("Car audio zone configuration change un-register multiple times status") 5553 .that(registered).isFalse(); 5554 } 5555 5556 @Test unregisterAudioZoneConfigsChangeCallback_withNullCallback()5557 public void unregisterAudioZoneConfigsChangeCallback_withNullCallback() throws Exception { 5558 CarAudioService service = setUpAudioService(); 5559 5560 NullPointerException thrown = assertThrows(NullPointerException.class, 5561 () -> service.unregisterAudioZoneConfigsChangeCallback(null)); 5562 5563 expectWithMessage("Car audio zone configuration change un-registration exception") 5564 .that(thrown).hasMessageThat().contains("Car audio zone configs"); 5565 } 5566 5567 @Test disableAudioMirrorForZone_withInvalidZone()5568 public void disableAudioMirrorForZone_withInvalidZone() throws Exception { 5569 CarAudioService service = setUpAudioService(); 5570 assignOccupantToAudioZones(); 5571 5572 IllegalArgumentException thrown = 5573 assertThrows(IllegalArgumentException.class, () -> 5574 service.disableAudioMirrorForZone(INVALID_AUDIO_ZONE)); 5575 5576 expectWithMessage("Disable mirror for invalid audio zone exception").that(thrown) 5577 .hasMessageThat().contains("Invalid audio zone"); 5578 } 5579 5580 @Test disableAudioMirrorForZone_withMirroringDisabled()5581 public void disableAudioMirrorForZone_withMirroringDisabled() throws Exception { 5582 CarAudioService service = setUpCarAudioServiceWithoutMirroring(); 5583 5584 IllegalStateException thrown = 5585 assertThrows(IllegalStateException.class, () -> 5586 service.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID)); 5587 5588 expectWithMessage("Disable mirror for zone with audio mirroring disabled") 5589 .that(thrown).hasMessageThat().contains("Audio zones mirroring is required"); 5590 } 5591 5592 @Test disableAudioMirrorForZone_forNonMirroringZone()5593 public void disableAudioMirrorForZone_forNonMirroringZone() throws Exception { 5594 CarAudioService service = setUpAudioService(); 5595 TestAudioZonesMirrorStatusCallbackCallback callback = 5596 getAudioZonesMirrorStatusCallback(service); 5597 assignOccupantToAudioZones(); 5598 5599 service.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID); 5600 5601 callback.waitForCallback(); 5602 expectWithMessage("Disable audio mirror for non-mirroring zone callback count") 5603 .that(callback.mNumberOfCalls).isEqualTo(0); 5604 } 5605 5606 @Test disableAudioMirrorForZone_forMirroringZones()5607 public void disableAudioMirrorForZone_forMirroringZones() throws Exception { 5608 CarAudioService service = setUpAudioService(); 5609 TestAudioZonesMirrorStatusCallbackCallback callback = 5610 getAudioZonesMirrorStatusCallback(service); 5611 assignOccupantToAudioZones(); 5612 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5613 callback.waitForCallback(); 5614 callback.reset(/* count= */ 1); 5615 5616 service.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID); 5617 5618 callback.waitForCallback(); 5619 expectWithMessage("Callback count for disable audio mirror") 5620 .that(callback.mNumberOfCalls).isEqualTo(2); 5621 expectWithMessage("Callback status disable audio mirror for mirroring zone") 5622 .that(callback.getLastStatus()) 5623 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 5624 expectWithMessage("Callback zones disable audio mirror for mirroring zone") 5625 .that(callback.getLastZoneIds()).asList() 5626 .containsExactly(TEST_REAR_RIGHT_ZONE_ID, TEST_REAR_LEFT_ZONE_ID); 5627 } 5628 5629 @Test disableAudioMirrorForZone_forMirroringZones_forFirstMirroringConfig()5630 public void disableAudioMirrorForZone_forMirroringZones_forFirstMirroringConfig() 5631 throws Exception { 5632 CarAudioService service = setUpAudioService(); 5633 TestAudioZonesMirrorStatusCallbackCallback callback = 5634 getAudioZonesMirrorStatusCallback(service); 5635 assignOccupantToAudioZones(); 5636 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5637 callback.waitForCallback(); 5638 callback.reset(/* count= */ 1); 5639 5640 service.disableAudioMirrorForZone(TEST_REAR_RIGHT_ZONE_ID); 5641 5642 callback.waitForCallback(); 5643 expectWithMessage("Callback count for disable audio mirror") 5644 .that(callback.mNumberOfCalls).isEqualTo(2); 5645 expectWithMessage("Callback status disable audio mirror for mirroring zone") 5646 .that(callback.getLastStatus()) 5647 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 5648 expectWithMessage("Callback zones disable audio mirror for mirroring zone") 5649 .that(callback.getLastZoneIds()).asList() 5650 .containsExactly(TEST_REAR_RIGHT_ZONE_ID, TEST_REAR_LEFT_ZONE_ID); 5651 String audioMirrorOffCommand = captureAudioMirrorInfoCommand(2); 5652 expectWithMessage("Audio HAL off source for mirroring zone") 5653 .that(audioMirrorOffCommand).contains(MIRROR_TEST_DEVICE); 5654 expectWithMessage("Audio HAL off signal for mirroring zone") 5655 .that(audioMirrorOffCommand).contains(MIRROR_OFF_SIGNAL); 5656 } 5657 5658 @Test disableAudioMirrorForZone_withPendingFocus()5659 public void disableAudioMirrorForZone_withPendingFocus() 5660 throws Exception { 5661 CarAudioService service = setUpAudioService(); 5662 TestAudioZonesMirrorStatusCallbackCallback callback = 5663 getAudioZonesMirrorStatusCallback(service); 5664 assignOccupantToAudioZones(); 5665 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5666 callback.waitForCallback(); 5667 callback.reset(/* count= */ 2); 5668 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 5669 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 5670 5671 service.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID); 5672 5673 callback.waitForCallback(); 5674 List<Integer> focusChanges = getFocusChanges(audioFocusInfo); 5675 expectWithMessage("Media audio focus changes after disable mirror for zone") 5676 .that(focusChanges).containsExactly(AUDIOFOCUS_LOSS_TRANSIENT, AUDIOFOCUS_GAIN); 5677 } 5678 5679 @Test disableAudioMirror_withoutMirroringDisabled()5680 public void disableAudioMirror_withoutMirroringDisabled() throws Exception { 5681 CarAudioService service = setUpCarAudioServiceWithoutMirroring(); 5682 5683 IllegalStateException thrown = 5684 assertThrows(IllegalStateException.class, () -> 5685 service.disableAudioMirror(INVALID_REQUEST_ID)); 5686 5687 expectWithMessage("Disable mirror for audio zones with audio mirroring disabled") 5688 .that(thrown).hasMessageThat().contains("Audio zones mirroring is required"); 5689 } 5690 5691 @Test disableAudioMirror_withInvalidRequestId()5692 public void disableAudioMirror_withInvalidRequestId() throws Exception { 5693 CarAudioService service = setUpAudioService(); 5694 5695 IllegalArgumentException thrown = 5696 assertThrows(IllegalArgumentException.class, () -> 5697 service.disableAudioMirror(INVALID_REQUEST_ID)); 5698 5699 expectWithMessage("Disable mirror for audio zones with audio invalid request id") 5700 .that(thrown).hasMessageThat().contains("INVALID_REQUEST_ID"); 5701 } 5702 5703 @Test disableAudioMirror_forNonMirroringZone()5704 public void disableAudioMirror_forNonMirroringZone() throws Exception { 5705 CarAudioService service = setUpAudioService(); 5706 TestAudioZonesMirrorStatusCallbackCallback callback = 5707 getAudioZonesMirrorStatusCallback(service); 5708 assignOccupantToAudioZones(); 5709 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5710 callback.waitForCallback(); 5711 callback.reset(1); 5712 service.disableAudioMirror(requestId); 5713 callback.waitForCallback(); 5714 callback.reset(1); 5715 5716 service.disableAudioMirror(requestId); 5717 5718 expectWithMessage("Disable audio mirror for non-mirroring zone callback count") 5719 .that(callback.mNumberOfCalls).isEqualTo(2); 5720 } 5721 5722 @Test disableAudioMirror_forMirroringZones()5723 public void disableAudioMirror_forMirroringZones() throws Exception { 5724 CarAudioService service = setUpAudioService(); 5725 TestAudioZonesMirrorStatusCallbackCallback callback = 5726 getAudioZonesMirrorStatusCallback(service); 5727 assignOccupantToAudioZones(); 5728 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5729 callback.waitForCallback(); 5730 callback.reset(/* count= */ 1); 5731 5732 service.disableAudioMirror(requestId); 5733 5734 callback.waitForCallback(); 5735 expectWithMessage("Callback count for disable mirror in audio zones") 5736 .that(callback.mNumberOfCalls).isEqualTo(2); 5737 expectWithMessage("Callback status disable audio mirror for mirroring zones") 5738 .that(callback.getLastStatus()) 5739 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 5740 expectWithMessage("Callback zones disable audio mirror for mirroring zones") 5741 .that(callback.getLastZoneIds()).asList() 5742 .containsExactly(TEST_REAR_RIGHT_ZONE_ID, TEST_REAR_LEFT_ZONE_ID); 5743 String audioMirrorOffCommand = captureAudioMirrorInfoCommand(2); 5744 expectWithMessage("Audio HAL off source for mirroring zones") 5745 .that(audioMirrorOffCommand).contains(MIRROR_TEST_DEVICE); 5746 expectWithMessage("Audio HAL off signal for mirroring zones") 5747 .that(audioMirrorOffCommand).contains(MIRROR_OFF_SIGNAL); 5748 } 5749 5750 @Test disableAudioMirror_withPendingFocus()5751 public void disableAudioMirror_withPendingFocus() throws Exception { 5752 CarAudioService service = setUpAudioService(); 5753 TestAudioZonesMirrorStatusCallbackCallback callback = 5754 getAudioZonesMirrorStatusCallback(service); 5755 assignOccupantToAudioZones(); 5756 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5757 callback.waitForCallback(); 5758 callback.reset(/* count= */ 2); 5759 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 5760 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 5761 5762 service.disableAudioMirror(requestId); 5763 5764 callback.waitForCallback(); 5765 List<Integer> focusChanges = getFocusChanges(audioFocusInfo); 5766 expectWithMessage("Media audio focus changes after disable audio" 5767 + "mirror for zones config").that(focusChanges) 5768 .containsExactly(AUDIOFOCUS_LOSS_TRANSIENT, AUDIOFOCUS_GAIN); 5769 } 5770 5771 @Test getMirrorAudioZonesForAudioZone_withoutMirroringEnabled()5772 public void getMirrorAudioZonesForAudioZone_withoutMirroringEnabled() 5773 throws Exception { 5774 CarAudioService service = setUpAudioService(); 5775 assignOccupantToAudioZones(); 5776 5777 int[] zones = service.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 5778 5779 expectWithMessage("Mirroring zones for non mirror zone %s", TEST_REAR_RIGHT_ZONE_ID) 5780 .that(zones).asList().isEmpty(); 5781 } 5782 5783 @Test getMirrorAudioZonesForAudioZone_withMirroringEnabled()5784 public void getMirrorAudioZonesForAudioZone_withMirroringEnabled() throws Exception { 5785 CarAudioService service = setUpAudioService(); 5786 TestAudioZonesMirrorStatusCallbackCallback callback = 5787 getAudioZonesMirrorStatusCallback(service); 5788 assignOccupantToAudioZones(); 5789 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5790 callback.waitForCallback(); 5791 5792 int[] zones = service.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 5793 5794 expectWithMessage("Mirroring zones for mirror zone %s", TEST_REAR_RIGHT_ZONE_ID).that(zones) 5795 .asList().containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID); 5796 } 5797 5798 @Test getMirrorAudioZonesForAudioZone_afterDisableMirror()5799 public void getMirrorAudioZonesForAudioZone_afterDisableMirror() throws Exception { 5800 CarAudioService service = setUpAudioService(); 5801 TestAudioZonesMirrorStatusCallbackCallback callback = 5802 getAudioZonesMirrorStatusCallback(service); 5803 assignOccupantToAudioZones(); 5804 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5805 callback.waitForCallback(); 5806 callback.reset(1); 5807 service.disableAudioMirror(requestId); 5808 callback.waitForCallback(); 5809 5810 int[] zones = service.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 5811 5812 expectWithMessage("Mirroring zones for mirror zone %s after disabling mirroring", 5813 TEST_REAR_RIGHT_ZONE_ID).that(zones).asList().isEmpty(); 5814 } 5815 5816 @Test getMirrorAudioZonesForAudioZone_afterPassengerLogout()5817 public void getMirrorAudioZonesForAudioZone_afterPassengerLogout() throws Exception { 5818 CarAudioService service = setUpAudioService(); 5819 TestAudioZonesMirrorStatusCallbackCallback callback = 5820 getAudioZonesMirrorStatusCallback(service); 5821 assignOccupantToAudioZones(); 5822 service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5823 callback.waitForCallback(); 5824 callback.reset(1); 5825 simulateLogoutRightPassengers(); 5826 callback.waitForCallback(); 5827 5828 int[] zones = service.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 5829 5830 expectWithMessage("Mirroring zones for mirror zone %s after logout", 5831 TEST_REAR_RIGHT_ZONE_ID).that(zones).asList().isEmpty(); 5832 } 5833 5834 @Test getMirrorAudioZonesForMirrorRequest_withMirroringEnabled()5835 public void getMirrorAudioZonesForMirrorRequest_withMirroringEnabled() throws Exception { 5836 CarAudioService service = setUpAudioService(); 5837 TestAudioZonesMirrorStatusCallbackCallback callback = 5838 getAudioZonesMirrorStatusCallback(service); 5839 assignOccupantToAudioZones(); 5840 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5841 callback.waitForCallback(); 5842 5843 int[] zones = service.getMirrorAudioZonesForMirrorRequest(requestId); 5844 5845 expectWithMessage("Mirroring zones for mirror request %s", requestId).that(zones).asList() 5846 .containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID); 5847 } 5848 5849 @Test getMirrorAudioZonesForMirrorRequest_afterDisableMirror()5850 public void getMirrorAudioZonesForMirrorRequest_afterDisableMirror() throws Exception { 5851 CarAudioService service = setUpAudioService(); 5852 TestAudioZonesMirrorStatusCallbackCallback callback = 5853 getAudioZonesMirrorStatusCallback(service); 5854 assignOccupantToAudioZones(); 5855 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5856 callback.waitForCallback(); 5857 callback.reset(1); 5858 service.disableAudioMirror(requestId); 5859 callback.waitForCallback(); 5860 5861 int[] zones = service.getMirrorAudioZonesForMirrorRequest(TEST_REAR_RIGHT_ZONE_ID); 5862 5863 expectWithMessage("Mirroring zones for mirror request %s after disabling mirroring", 5864 requestId).that(zones).asList().isEmpty(); 5865 } 5866 5867 @Test getMirrorAudioZonesForMirrorRequest_afterPassengerLogout()5868 public void getMirrorAudioZonesForMirrorRequest_afterPassengerLogout() throws Exception { 5869 CarAudioService service = setUpAudioService(); 5870 TestAudioZonesMirrorStatusCallbackCallback callback = 5871 getAudioZonesMirrorStatusCallback(service); 5872 assignOccupantToAudioZones(); 5873 long requestId = service.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 5874 callback.waitForCallback(); 5875 callback.reset(1); 5876 simulateLogoutRightPassengers(); 5877 callback.waitForCallback(); 5878 5879 int[] zones = service.getMirrorAudioZonesForMirrorRequest(requestId); 5880 5881 expectWithMessage("Mirroring zones for mirror request %s after logout", 5882 TEST_REAR_RIGHT_ZONE_ID).that(zones).asList().isEmpty(); 5883 } 5884 5885 @Test onAudioVolumeGroupChanged_whenNoPlayback_dispatchCallbackEvent()5886 public void onAudioVolumeGroupChanged_whenNoPlayback_dispatchCallbackEvent() throws Exception { 5887 CarAudioService useCoreAudioCarAudioService = 5888 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 5889 int expectedFlags = FLAG_SHOW_UI | FLAG_PLAY_SOUND; 5890 int musicIndex = useCoreAudioCarAudioService.getGroupVolume( 5891 PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID); 5892 // Report a volume change 5893 when(mAudioManager.getVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 5894 .thenReturn(musicIndex + 1); 5895 when(mAudioManager.getLastAudibleVolumeForVolumeGroup(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 5896 .thenReturn(musicIndex + 1); 5897 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 5898 .thenReturn(false); 5899 5900 useCoreAudioCarAudioService.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 5901 CoreAudioRoutingUtils.MUSIC_GROUP_NAME, FLAG_SHOW_UI); 5902 5903 verify(mCarVolumeCallbackHandler) 5904 .onVolumeGroupChange(PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, 5905 expectedFlags); 5906 } 5907 5908 @Test onAudioVolumeGroupChanged_noDispatchCallbackEvent_whenAlreadySynced()5909 public void onAudioVolumeGroupChanged_noDispatchCallbackEvent_whenAlreadySynced() 5910 throws Exception { 5911 CarAudioService useCoreAudioCarAudioService = 5912 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 5913 useCoreAudioCarAudioService.setGroupVolume(PRIMARY_AUDIO_ZONE, 5914 CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, CoreAudioRoutingUtils.MUSIC_AM_INIT_INDEX, 5915 /* flags= */ 0); 5916 reset(mCarVolumeCallbackHandler); 5917 5918 useCoreAudioCarAudioService.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 5919 CoreAudioRoutingUtils.MUSIC_GROUP_NAME, /* flags= */ 0); 5920 5921 verify(mCarVolumeCallbackHandler, never()) 5922 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 5923 } 5924 5925 @Test onAudioVolumeGroupChanged_dispatchCallbackEvent_whenMuted()5926 public void onAudioVolumeGroupChanged_dispatchCallbackEvent_whenMuted() throws Exception { 5927 CarAudioService useCoreAudioCarAudioService = 5928 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 5929 int expectedFlags = FLAG_SHOW_UI; 5930 // Report a mute change 5931 when(mAudioManager.getVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 5932 .thenReturn(CoreAudioRoutingUtils.MUSIC_MIN_INDEX); 5933 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 5934 .thenReturn(true); 5935 5936 useCoreAudioCarAudioService.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 5937 CoreAudioRoutingUtils.MUSIC_GROUP_NAME, expectedFlags); 5938 5939 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 5940 CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, expectedFlags); 5941 } 5942 5943 @Test onAudioVolumeGroupChanged_withInvalidVolumeGroupName()5944 public void onAudioVolumeGroupChanged_withInvalidVolumeGroupName() throws Exception { 5945 CarAudioService useCoreAudioCarAudioService = 5946 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 5947 5948 useCoreAudioCarAudioService.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 5949 CoreAudioRoutingUtils.INVALID_GROUP_NAME, /* flags= */ 0); 5950 5951 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 5952 anyInt(), anyInt()); 5953 } 5954 5955 @Test onAudioVolumeGroupChanged_withIndexChange_reportsGroupEvent()5956 public void onAudioVolumeGroupChanged_withIndexChange_reportsGroupEvent() throws Exception { 5957 CarAudioService service = 5958 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume(); 5959 TestCarVolumeEventCallback volumeEventCallback = 5960 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 5961 service.registerCarVolumeEventCallback(volumeEventCallback); 5962 int musicIndex = service.getGroupVolume(PRIMARY_AUDIO_ZONE, 5963 CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID); 5964 when(mAudioManager.getVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 5965 .thenReturn(musicIndex + 1); 5966 when(mAudioManager.getLastAudibleVolumeForVolumeGroup(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 5967 .thenReturn(musicIndex + 1); 5968 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 5969 .thenReturn(false); 5970 5971 // Report a volume change 5972 service.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 5973 CoreAudioRoutingUtils.MUSIC_GROUP_NAME, FLAG_SHOW_UI); 5974 5975 expectWithMessage("Volume event callback for volume change from AudioManager callback") 5976 .that(volumeEventCallback.waitForCallback()).isTrue(); 5977 expectWithMessage("Volume events count for volume change from AudioManager callback") 5978 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 5979 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 5980 expectWithMessage("Volume event type after volume change from AudioManager callback") 5981 .that(groupEvent.getEventTypes()) 5982 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 5983 expectWithMessage("Volume group info after volume change from AudioManager callback") 5984 .that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 5985 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 5986 CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID)); 5987 expectWithMessage("Volume group extra info after volume change from AudioManager callback") 5988 .that(groupEvent.getExtraInfos()).containsExactly( 5989 CarVolumeGroupEvent.EXTRA_INFO_SHOW_UI, 5990 CarVolumeGroupEvent.EXTRA_INFO_PLAY_SOUND); 5991 } 5992 5993 @Test callbackVolumeGroupEvent_withEmptyEventList()5994 public void callbackVolumeGroupEvent_withEmptyEventList() throws Exception { 5995 CarAudioService service = setUpAudioService(); 5996 TestCarVolumeEventCallback volumeEventCallback = 5997 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 5998 service.registerCarVolumeEventCallback(volumeEventCallback); 5999 6000 service.callbackVolumeGroupEvent(Collections.EMPTY_LIST); 6001 6002 expectWithMessage("Volume group event callback reception status for empty event list") 6003 .that(volumeEventCallback.waitForCallback()).isFalse(); 6004 } 6005 6006 @Test onVolumeGroupEvent_withVolumeEvent_triggersCallback()6007 public void onVolumeGroupEvent_withVolumeEvent_triggersCallback() throws Exception { 6008 CarAudioService service = setUpAudioService(); 6009 TestCarVolumeEventCallback volumeEventCallback = 6010 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6011 service.registerCarVolumeEventCallback(volumeEventCallback); 6012 6013 service.onVolumeGroupEvent(List.of(mTestCarVolumeGroupEvent)); 6014 6015 expectWithMessage("Volume event callback reception status") 6016 .that(volumeEventCallback.waitForCallback()).isTrue(); 6017 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 6018 verify(mCarVolumeCallbackHandler) 6019 .onVolumeGroupChange(PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, 6020 /* flags= */ 0); 6021 expectWithMessage("Volume events count after volume event") 6022 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6023 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6024 expectWithMessage("Volume event type after volume event") 6025 .that(groupEvent.getEventTypes()) 6026 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6027 expectWithMessage("Volume group infos after unmute") 6028 .that(groupEvent.getCarVolumeGroupInfos()) 6029 .containsExactly(mTestPrimaryZoneUmMutedVolueInfo0); 6030 } 6031 6032 @Test onVolumeGroupEvent_withMuteEvent_triggersCallback()6033 public void onVolumeGroupEvent_withMuteEvent_triggersCallback() throws Exception { 6034 CarAudioService service = setUpAudioService(); 6035 TestCarVolumeEventCallback volumeEventCallback = 6036 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6037 service.registerCarVolumeEventCallback(volumeEventCallback); 6038 6039 service.onVolumeGroupEvent(List.of(mTestCarMuteGroupEvent)); 6040 6041 expectWithMessage("Volume event callback reception status") 6042 .that(volumeEventCallback.waitForCallback()).isTrue(); 6043 verify(mCarVolumeCallbackHandler, never()) 6044 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 6045 verify(mCarVolumeCallbackHandler) 6046 .onGroupMuteChange(PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, 6047 /* flags= */ 0); 6048 expectWithMessage("Volume events count after mute event") 6049 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6050 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6051 expectWithMessage("Volume event type after mute event") 6052 .that(groupEvent.getEventTypes()) 6053 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 6054 expectWithMessage("Volume group infos after mute event") 6055 .that(groupEvent.getCarVolumeGroupInfos()) 6056 .containsExactly(mTestPrimaryZoneUmMutedVolueInfo0); 6057 } 6058 6059 @Test onVolumeGroupEvent_withoutMuteOrVolumeEvent_triggersCallback()6060 public void onVolumeGroupEvent_withoutMuteOrVolumeEvent_triggersCallback() 6061 throws Exception { 6062 CarAudioService service = setUpAudioService(); 6063 TestCarVolumeEventCallback volumeEventCallback = 6064 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6065 service.registerCarVolumeEventCallback(volumeEventCallback); 6066 6067 service.onVolumeGroupEvent(List.of(mTestCarZoneReconfigurationEvent)); 6068 6069 expectWithMessage("Volume event callback reception status") 6070 .that(volumeEventCallback.waitForCallback()).isTrue(); 6071 verify(mCarVolumeCallbackHandler, never()) 6072 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 6073 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 6074 expectWithMessage("Volume events count after reconfiguration event") 6075 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6076 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6077 expectWithMessage("Volume event type after reconfiguration event") 6078 .that(groupEvent.getEventTypes()) 6079 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_ZONE_CONFIGURATION_CHANGED); 6080 expectWithMessage("Volume group infos after reconfiguration event") 6081 .that(groupEvent.getCarVolumeGroupInfos()) 6082 .containsExactly(mTestPrimaryZoneUmMutedVolueInfo0); 6083 } 6084 6085 @Test setMuted_whenUnmuted_onActivation_triggersCallback()6086 public void setMuted_whenUnmuted_onActivation_triggersCallback() throws Exception { 6087 CarAudioService service = setUpAudioService(); 6088 TestCarVolumeEventCallback volumeEventCallback = 6089 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6090 service.registerCarVolumeEventCallback(volumeEventCallback); 6091 6092 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6093 /* mute= */ true, TEST_FLAGS); 6094 6095 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 6096 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 6097 expectWithMessage("Volume event callback reception status after mute") 6098 .that(volumeEventCallback.waitForCallback()).isTrue(); 6099 expectWithMessage("Volume events count after mute") 6100 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6101 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6102 expectWithMessage("Volume event type after mute") 6103 .that(groupEvent.getEventTypes()) 6104 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 6105 expectWithMessage("Volume group infos after mute") 6106 .that(groupEvent.getCarVolumeGroupInfos()) 6107 .containsExactly(mTestPrimaryZoneVolumeInfo0); 6108 } 6109 6110 @Test setMuted_whenUnmuted_onDeactivation_doesNotTriggerCallback()6111 public void setMuted_whenUnmuted_onDeactivation_doesNotTriggerCallback() throws Exception { 6112 CarAudioService service = setUpAudioService(); 6113 TestCarVolumeEventCallback volumeEventCallback = 6114 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6115 service.registerCarVolumeEventCallback(volumeEventCallback); 6116 6117 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6118 /* mute= */ false, TEST_FLAGS); 6119 6120 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 6121 expectWithMessage("Volume event callback reception status") 6122 .that(volumeEventCallback.waitForCallback()).isFalse(); 6123 } 6124 6125 @Test setMuted_whenMuted_onDeactivation_triggersCallback()6126 public void setMuted_whenMuted_onDeactivation_triggersCallback() throws Exception { 6127 CarAudioService service = setUpAudioService(); 6128 TestCarVolumeEventCallback volumeEventCallback = 6129 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6130 service.registerCarVolumeEventCallback(volumeEventCallback); 6131 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6132 /* mute= */ true, TEST_FLAGS); 6133 resetVolumeCallbacks(volumeEventCallback); 6134 6135 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6136 /* mute= */ false, TEST_FLAGS); 6137 6138 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 6139 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 6140 expectWithMessage("Volume event callback reception status after unmute") 6141 .that(volumeEventCallback.waitForCallback()).isTrue(); 6142 expectWithMessage("Volume events count after mute") 6143 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6144 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6145 expectWithMessage("Volume event type after unmute") 6146 .that(groupEvent.getEventTypes()) 6147 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 6148 expectWithMessage("Volume group infos after unmute") 6149 .that(groupEvent.getCarVolumeGroupInfos()) 6150 .containsExactly(mTestPrimaryZoneUmMutedVolueInfo0); 6151 } 6152 6153 @Test setUnmuted_whenMutedBySystem_triggersCallback()6154 public void setUnmuted_whenMutedBySystem_triggersCallback() throws Exception { 6155 CarAudioService service = setUpAudioService(); 6156 TestCarVolumeEventCallback volumeEventCallback = 6157 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6158 service.registerCarVolumeEventCallback(volumeEventCallback); 6159 CarAudioGainConfigInfo primaryAudioZoneCarGain = createCarAudioGainConfigInfo( 6160 PRIMARY_AUDIO_ZONE, MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 6161 HalAudioGainCallback halAudioGainCallback = getHalAudioGainCallback(); 6162 halAudioGainCallback.onAudioDeviceGainsChanged(List.of(Reasons.TCU_MUTE), 6163 List.of(primaryAudioZoneCarGain)); 6164 resetVolumeCallbacks(volumeEventCallback); 6165 6166 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6167 /* mute= */ false, TEST_FLAGS); 6168 6169 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 6170 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 6171 expectWithMessage("Volume event callback reception status after unmute when muted by " 6172 + "system").that(volumeEventCallback.waitForCallback()).isTrue(); 6173 expectWithMessage("Volume events count after mute when muted by system") 6174 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6175 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6176 expectWithMessage("Volume event type after unmute when muted by system") 6177 .that(groupEvent.getEventTypes()) 6178 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 6179 } 6180 6181 @Test setMuted_whenMutedByApiAndSystem_doesNotTriggerCallback()6182 public void setMuted_whenMutedByApiAndSystem_doesNotTriggerCallback() throws Exception { 6183 CarAudioService service = setUpAudioService(); 6184 TestCarVolumeEventCallback volumeEventCallback = 6185 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6186 service.registerCarVolumeEventCallback(volumeEventCallback); 6187 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, /* mute= */ true, 6188 TEST_FLAGS); 6189 resetVolumeCallbacks(volumeEventCallback); 6190 CarAudioGainConfigInfo primaryAudioZoneCarGain = createCarAudioGainConfigInfo( 6191 PRIMARY_AUDIO_ZONE, MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 6192 HalAudioGainCallback halAudioGainCallback = getHalAudioGainCallback(); 6193 halAudioGainCallback.onAudioDeviceGainsChanged(List.of(Reasons.TCU_MUTE), 6194 List.of(primaryAudioZoneCarGain)); 6195 resetVolumeCallbacks(volumeEventCallback); 6196 6197 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, /* mute= */ true, 6198 TEST_FLAGS); 6199 6200 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 6201 expectWithMessage("Volume event callback reception status after mute when muted by " 6202 + "both API and system").that(volumeEventCallback.waitForCallback()).isFalse(); 6203 } 6204 6205 @Test setMuted_whenMuted_onActivation_doesNotTriggerCallback()6206 public void setMuted_whenMuted_onActivation_doesNotTriggerCallback() throws Exception { 6207 CarAudioService service = setUpAudioService(); 6208 TestCarVolumeEventCallback volumeEventCallback = 6209 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6210 service.registerCarVolumeEventCallback(volumeEventCallback); 6211 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6212 /* mute= */ true, TEST_FLAGS); 6213 resetVolumeCallbacks(volumeEventCallback); 6214 6215 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6216 /* mute= */ true, TEST_FLAGS); 6217 6218 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 6219 expectWithMessage("Volume event callback reception status") 6220 .that(volumeEventCallback.waitForCallback()).isFalse(); 6221 } 6222 6223 @Test handleActivationVolumeWithAudioAttributes_withMultipleAudioAttributes()6224 public void handleActivationVolumeWithAudioAttributes_withMultipleAudioAttributes() 6225 throws Exception { 6226 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6227 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6228 TestCarVolumeEventCallback volumeEventCallback = 6229 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6230 service.registerCarVolumeEventCallback(volumeEventCallback); 6231 int currentConfigId = service.getCurrentAudioZoneConfigInfo(PRIMARY_AUDIO_ZONE) 6232 .getConfigId(); 6233 int mediaMaxActivationGainIndex = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6234 TEST_PRIMARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex(); 6235 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6236 TEST_PRIMARY_ZONE_GROUP_0, mediaMaxActivationGainIndex + 1); 6237 int navMinActivationGainIndex = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6238 TEST_PRIMARY_ZONE_GROUP_1).getMinActivationVolumeGainIndex(); 6239 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6240 TEST_PRIMARY_ZONE_GROUP_1, navMinActivationGainIndex - 1); 6241 6242 service.handleActivationVolumeWithActivationInfos(List.of( 6243 new CarAudioPlaybackMonitor.ActivationInfo(TEST_PRIMARY_ZONE_GROUP_0, 6244 CarActivationVolumeConfig.ACTIVATION_VOLUME_ON_BOOT), 6245 new CarAudioPlaybackMonitor.ActivationInfo(TEST_PRIMARY_ZONE_GROUP_1, 6246 CarActivationVolumeConfig.ACTIVATION_VOLUME_ON_BOOT)), 6247 PRIMARY_AUDIO_ZONE, currentConfigId); 6248 6249 expectWithMessage("Media volume for above-activation gain index") 6250 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6251 .isEqualTo(mediaMaxActivationGainIndex); 6252 expectWithMessage("Navigation volume for below-activation gain index") 6253 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1)) 6254 .isEqualTo(navMinActivationGainIndex); 6255 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6256 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 6257 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6258 eq(TEST_PRIMARY_ZONE_GROUP_1), anyInt()); 6259 expectWithMessage("Volume event callback for volume out of activation gain index range") 6260 .that(volumeEventCallback.waitForCallback()).isTrue(); 6261 expectWithMessage("Volume events count after activation gain index adjustment") 6262 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6263 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6264 expectWithMessage("Volume event type after activation gain index adjustment") 6265 .that(groupEvent.getEventTypes()) 6266 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6267 expectWithMessage("Volume group info after activation gain index adjustment" 6268 + " adjustment").that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6269 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0), 6270 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1)); 6271 } 6272 6273 @Test handleActivationVolumeWithAudioAttributes_withNonCurrentZoneConfig()6274 public void handleActivationVolumeWithAudioAttributes_withNonCurrentZoneConfig() 6275 throws Exception { 6276 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6277 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6278 TestCarVolumeEventCallback volumeEventCallback = 6279 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6280 service.registerCarVolumeEventCallback(volumeEventCallback); 6281 int nonCurrentConfigId = getZoneConfigToSwitch(service, TEST_REAR_LEFT_ZONE_ID) 6282 .getConfigId(); 6283 int mediaGainIndexAboveMaxActivation = service.getVolumeGroupInfo(TEST_REAR_LEFT_ZONE_ID, 6284 SECONDARY_ZONE_VOLUME_GROUP_ID).getMaxActivationVolumeGainIndex() + 1; 6285 setVolumeForGroup(service, volumeEventCallback, TEST_REAR_LEFT_ZONE_ID, 6286 SECONDARY_ZONE_VOLUME_GROUP_ID, mediaGainIndexAboveMaxActivation); 6287 6288 service.handleActivationVolumeWithActivationInfos(List.of( 6289 new CarAudioPlaybackMonitor.ActivationInfo(TEST_REAR_LEFT_ZONE_ID, 6290 CarActivationVolumeConfig.ACTIVATION_VOLUME_ON_BOOT)), 6291 TEST_REAR_LEFT_ZONE_ID, nonCurrentConfigId); 6292 6293 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(TEST_REAR_LEFT_ZONE_ID), 6294 eq(SECONDARY_ZONE_VOLUME_GROUP_ID), anyInt()); 6295 expectWithMessage("Volume event callback for non-current zone config activation volume") 6296 .that(volumeEventCallback.waitForCallback()).isFalse(); 6297 } 6298 6299 @Test onPlaybackConfigChanged_withActivationVolumeFlagDisabled()6300 public void onPlaybackConfigChanged_withActivationVolumeFlagDisabled() throws Exception { 6301 mSetFlagsRule.disableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6302 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6303 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6304 TestCarVolumeEventCallback volumeEventCallback = 6305 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6306 service.registerCarVolumeEventCallback(volumeEventCallback); 6307 int gainIndex = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6308 TEST_PRIMARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex() + 1; 6309 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6310 TEST_PRIMARY_ZONE_GROUP_0, gainIndex); 6311 6312 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6313 .setUsage(USAGE_MEDIA).setDeviceAddress(MEDIA_TEST_DEVICE) 6314 .setClientUid(TEST_PLAYBACK_UID).build())); 6315 6316 expectWithMessage("Playback group volume with activation volume flag disabled") 6317 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6318 .isEqualTo(gainIndex); 6319 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6320 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 6321 expectWithMessage("No volume event callback for activation volume flag disabled") 6322 .that(volumeEventCallback.waitForCallback()).isFalse(); 6323 } 6324 6325 @Test onPlaybackConfigChanged_withActivationVolumeFeatureDisabled()6326 public void onPlaybackConfigChanged_withActivationVolumeFeatureDisabled() throws Exception { 6327 mSetFlagsRule.disableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6328 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ false); 6329 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6330 TestCarVolumeEventCallback volumeEventCallback = 6331 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6332 service.registerCarVolumeEventCallback(volumeEventCallback); 6333 int gainIndex = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6334 TEST_PRIMARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex() + 1; 6335 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6336 TEST_PRIMARY_ZONE_GROUP_0, gainIndex); 6337 6338 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6339 .setUsage(USAGE_MEDIA).setDeviceAddress(MEDIA_TEST_DEVICE) 6340 .setClientUid(TEST_PLAYBACK_UID).build())); 6341 6342 expectWithMessage("Playback group volume with activation volume feature disabled") 6343 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6344 .isEqualTo(gainIndex); 6345 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6346 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 6347 expectWithMessage("No volume event callback for activation volume feature disabled") 6348 .that(volumeEventCallback.waitForCallback()).isFalse(); 6349 } 6350 6351 @Test onPlaybackConfigChanged_withVolumeAboveMaxActivationVolume()6352 public void onPlaybackConfigChanged_withVolumeAboveMaxActivationVolume() throws Exception { 6353 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6354 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6355 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6356 TestCarVolumeEventCallback volumeEventCallback = 6357 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6358 service.registerCarVolumeEventCallback(volumeEventCallback); 6359 int maxActivationVolume = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6360 TEST_PRIMARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex(); 6361 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6362 TEST_PRIMARY_ZONE_GROUP_0, maxActivationVolume + 1); 6363 6364 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6365 .setUsage(USAGE_MEDIA).setDeviceAddress(MEDIA_TEST_DEVICE) 6366 .setClientUid(TEST_PLAYBACK_UID).build())); 6367 6368 expectWithMessage("Playback group volume for above-activation gain index") 6369 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6370 .isEqualTo(maxActivationVolume); 6371 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6372 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 6373 expectWithMessage("Volume event callback for above-activation gain index") 6374 .that(volumeEventCallback.waitForCallback()).isTrue(); 6375 expectWithMessage("Volume events count after above-activation gain index adjustment") 6376 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6377 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6378 expectWithMessage("Volume event type after above-activation gain index adjustment") 6379 .that(groupEvent.getEventTypes()) 6380 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6381 expectWithMessage("Volume group info after above-activation gain index adjustment") 6382 .that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6383 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)); 6384 } 6385 6386 @Test onPlaybackConfigChanged_withVolumeBelowMinActivationVolume()6387 public void onPlaybackConfigChanged_withVolumeBelowMinActivationVolume() throws Exception { 6388 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6389 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6390 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6391 TestCarVolumeEventCallback volumeEventCallback = 6392 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6393 service.registerCarVolumeEventCallback(volumeEventCallback); 6394 int minActivationVolume = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6395 TEST_PRIMARY_ZONE_GROUP_1).getMinActivationVolumeGainIndex(); 6396 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6397 TEST_PRIMARY_ZONE_GROUP_1, minActivationVolume - 1); 6398 6399 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6400 .setUsage(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) 6401 .setDeviceAddress(NAVIGATION_TEST_DEVICE).setClientUid(TEST_PLAYBACK_UID) 6402 .build())); 6403 6404 expectWithMessage("Playback group volume for below-activation gain index") 6405 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1)) 6406 .isEqualTo(minActivationVolume); 6407 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6408 eq(TEST_PRIMARY_ZONE_GROUP_1), anyInt()); 6409 expectWithMessage("Volume event callback for below-activation gain index") 6410 .that(volumeEventCallback.waitForCallback()).isTrue(); 6411 expectWithMessage("Volume events count after below-activation gain index adjustment") 6412 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6413 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6414 expectWithMessage("Volume event type after below-activation gain index adjustment") 6415 .that(groupEvent.getEventTypes()) 6416 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6417 expectWithMessage("Volume group info after below-activation gain index adjustment") 6418 .that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6419 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1)); 6420 } 6421 6422 @Test onPlaybackConfigChanged_withVolumeInActivationVolumeRange()6423 public void onPlaybackConfigChanged_withVolumeInActivationVolumeRange() throws Exception { 6424 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6425 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6426 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6427 TestCarVolumeEventCallback volumeEventCallback = 6428 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6429 service.registerCarVolumeEventCallback(volumeEventCallback); 6430 int gainIndexInActivationVolumeRange = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6431 TEST_PRIMARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex() - 1; 6432 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6433 TEST_PRIMARY_ZONE_GROUP_0, gainIndexInActivationVolumeRange); 6434 6435 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6436 .setUsage(USAGE_MEDIA).setDeviceAddress(MEDIA_TEST_DEVICE) 6437 .setClientUid(TEST_PLAYBACK_UID).build())); 6438 6439 expectWithMessage("Playback group volume in activation volume range") 6440 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6441 .isEqualTo(gainIndexInActivationVolumeRange); 6442 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6443 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 6444 expectWithMessage("No volume event callback for no activation volume adjustment") 6445 .that(volumeEventCallback.waitForCallback()).isFalse(); 6446 } 6447 6448 @Test onPlaybackConfigChanged_withVolumeGroupMute()6449 public void onPlaybackConfigChanged_withVolumeGroupMute() throws Exception { 6450 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6451 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6452 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6453 TestCarVolumeEventCallback volumeEventCallback = 6454 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6455 service.registerCarVolumeEventCallback(volumeEventCallback); 6456 int gainIndexAboveActivationVolume = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6457 TEST_PRIMARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex() + 1; 6458 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6459 TEST_PRIMARY_ZONE_GROUP_0, gainIndexAboveActivationVolume); 6460 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6461 /* mute= */ true, TEST_FLAGS); 6462 resetVolumeCallbacks(volumeEventCallback); 6463 6464 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6465 .setUsage(USAGE_MEDIA).setDeviceAddress(MEDIA_TEST_DEVICE) 6466 .setClientUid(TEST_PLAYBACK_UID).build())); 6467 6468 expectWithMessage("Mute state with playback volume higher than max activation volume") 6469 .that(service.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6470 .isTrue(); 6471 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6472 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 6473 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 6474 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 6475 expectWithMessage("No volume event callback for activation volume when mute") 6476 .that(volumeEventCallback.waitForCallback()).isFalse(); 6477 } 6478 6479 @Test onPlaybackConfigChanged_afterZoneConfigSwitched()6480 public void onPlaybackConfigChanged_afterZoneConfigSwitched() throws Exception { 6481 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6482 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6483 SwitchAudioZoneConfigCallbackImpl zoneConfigSwitchCallback = 6484 new SwitchAudioZoneConfigCallbackImpl(); 6485 assignOccupantToAudioZones(); 6486 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6487 TestCarVolumeEventCallback volumeEventCallback = 6488 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6489 service.registerCarVolumeEventCallback(volumeEventCallback); 6490 int maxActivationVolume = service.getVolumeGroupInfo(TEST_REAR_LEFT_ZONE_ID, 6491 TEST_SECONDARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex(); 6492 setVolumeForGroup(service, volumeEventCallback, TEST_REAR_LEFT_ZONE_ID, 6493 TEST_SECONDARY_ZONE_GROUP_0, maxActivationVolume + 1); 6494 createActivePlayback(callback, volumeEventCallback, USAGE_MEDIA, 6495 SECONDARY_TEST_DEVICE_CONFIG_0, TEST_PLAYBACK_UID); 6496 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(service, 6497 TEST_REAR_LEFT_ZONE_ID); 6498 service.switchZoneToConfig(zoneConfigSwitchTo, zoneConfigSwitchCallback); 6499 zoneConfigSwitchCallback.waitForCallback(); 6500 resetVolumeCallbacks(volumeEventCallback); 6501 maxActivationVolume = service.getVolumeGroupInfo(TEST_REAR_LEFT_ZONE_ID, 6502 TEST_SECONDARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex(); 6503 setVolumeForGroup(service, volumeEventCallback, TEST_REAR_LEFT_ZONE_ID, 6504 TEST_SECONDARY_ZONE_GROUP_0, maxActivationVolume + 1); 6505 6506 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6507 .setUsage(USAGE_MEDIA).setDeviceAddress(SECONDARY_TEST_DEVICE_CONFIG_1_0) 6508 .setClientUid(TEST_PLAYBACK_UID).build())); 6509 6510 expectWithMessage("Playback group volume after zone config switch") 6511 .that(service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_0)) 6512 .isEqualTo(maxActivationVolume); 6513 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(TEST_REAR_LEFT_ZONE_ID), 6514 eq(TEST_SECONDARY_ZONE_GROUP_0), anyInt()); 6515 expectWithMessage("Volume event callback after zone config switch") 6516 .that(volumeEventCallback.waitForCallback()).isTrue(); 6517 expectWithMessage("Volume events count after zone config switch") 6518 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6519 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6520 expectWithMessage("Volume event type after zone config switch") 6521 .that(groupEvent.getEventTypes()) 6522 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6523 expectWithMessage("Volume group info after zone config switch") 6524 .that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6525 service.getVolumeGroupInfo(TEST_REAR_LEFT_ZONE_ID, 6526 TEST_SECONDARY_ZONE_GROUP_0)); 6527 } 6528 6529 @Test onPlaybackConfigChanged_afterOccupantZoneConfigChanged()6530 public void onPlaybackConfigChanged_afterOccupantZoneConfigChanged() throws Exception { 6531 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6532 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6533 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6534 TestCarVolumeEventCallback volumeEventCallback = 6535 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6536 service.registerCarVolumeEventCallback(volumeEventCallback); 6537 int maxActivationVolume = service.getVolumeGroupInfo(TEST_REAR_LEFT_ZONE_ID, 6538 TEST_SECONDARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex(); 6539 setVolumeForGroup(service, volumeEventCallback, TEST_REAR_LEFT_ZONE_ID, 6540 TEST_SECONDARY_ZONE_GROUP_0, maxActivationVolume + 1); 6541 createActivePlayback(callback, volumeEventCallback, USAGE_MEDIA, 6542 SECONDARY_TEST_DEVICE_CONFIG_0, TEST_PLAYBACK_UID); 6543 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6544 .setUsage(USAGE_MEDIA).setDeviceAddress(SECONDARY_TEST_DEVICE_CONFIG_0) 6545 .setClientUid(TEST_PLAYBACK_UID).setInactive().build())); 6546 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 6547 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 6548 .thenReturn(TEST_REAR_LEFT_USER_ID, TEST_REAR_RIGHT_USER_ID); 6549 ICarOccupantZoneCallback occupantZoneCallback = getOccupantZoneCallback(); 6550 occupantZoneCallback.onOccupantZoneConfigChanged( 6551 CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 6552 setVolumeForGroup(service, volumeEventCallback, TEST_REAR_LEFT_ZONE_ID, 6553 TEST_SECONDARY_ZONE_GROUP_0, maxActivationVolume + 1); 6554 6555 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 6556 .setUsage(USAGE_MEDIA).setDeviceAddress(SECONDARY_TEST_DEVICE_CONFIG_0) 6557 .setClientUid(TEST_PLAYBACK_UID).build())); 6558 6559 expectWithMessage("Playback group volume after zone user switch") 6560 .that(service.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_0)) 6561 .isEqualTo(maxActivationVolume); 6562 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(TEST_REAR_LEFT_ZONE_ID), 6563 eq(TEST_SECONDARY_ZONE_GROUP_0), anyInt()); 6564 expectWithMessage("Volume event callback after zone user switch") 6565 .that(volumeEventCallback.waitForCallback()).isTrue(); 6566 expectWithMessage("Volume events count after zone user switch") 6567 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6568 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6569 expectWithMessage("Volume event type after zone user switch") 6570 .that(groupEvent.getEventTypes()) 6571 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6572 expectWithMessage("Volume group info after zone user switch") 6573 .that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6574 service.getVolumeGroupInfo(TEST_REAR_LEFT_ZONE_ID, 6575 TEST_SECONDARY_ZONE_GROUP_0)); 6576 } 6577 6578 @Test setVolumeGroupMute_withUnMuteAfterPlaybackConfigChangedWhenMute()6579 public void setVolumeGroupMute_withUnMuteAfterPlaybackConfigChangedWhenMute() throws Exception { 6580 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6581 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6582 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 6583 TestCarVolumeEventCallback volumeEventCallback = 6584 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6585 service.registerCarVolumeEventCallback(volumeEventCallback); 6586 int maxActivationVolume = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6587 TEST_PRIMARY_ZONE_GROUP_0).getMaxActivationVolumeGainIndex(); 6588 int gainIndexAboveActivationVolume = maxActivationVolume + 1; 6589 service.setGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6590 gainIndexAboveActivationVolume, TEST_FLAGS); 6591 resetVolumeCallbacks(volumeEventCallback); 6592 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6593 /* mute= */ true, TEST_FLAGS); 6594 resetVolumeCallbacks(volumeEventCallback); 6595 createActivePlayback(callback, volumeEventCallback, USAGE_MEDIA, MEDIA_TEST_DEVICE, 6596 TEST_PLAYBACK_UID); 6597 6598 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6599 /* mute= */ false, TEST_FLAGS); 6600 6601 expectWithMessage("Mute state after playback changed and unmute") 6602 .that(service.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6603 .isFalse(); 6604 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 6605 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 6606 expectWithMessage("Volume gain index after playback changed and unmute") 6607 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 6608 .isEqualTo(maxActivationVolume); 6609 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6610 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 6611 expectWithMessage("Volume event callback for activation volume adjustment and unmute") 6612 .that(volumeEventCallback.waitForCallback()).isTrue(); 6613 expectWithMessage("Volume events count for activation volume adjustment and unmute") 6614 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6615 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6616 expectWithMessage("Volume event type after activation volume adjustment and unmute") 6617 .that(groupEvent.getEventTypes()) 6618 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 6619 expectWithMessage("Volume group info after activation volume adjustment and unmute") 6620 .that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6621 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)); 6622 } 6623 6624 @Test requestHalAudioFocus_withVolumeAboveActivationVolume_adjustsToActivationVolume()6625 public void requestHalAudioFocus_withVolumeAboveActivationVolume_adjustsToActivationVolume() 6626 throws Exception { 6627 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6628 when(mAudioManager.requestAudioFocus(any())).thenReturn( 6629 AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 6630 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6631 TestCarVolumeEventCallback volumeEventCallback = 6632 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6633 service.registerCarVolumeEventCallback(volumeEventCallback); 6634 int maxActivationVolume = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6635 TEST_PRIMARY_ZONE_GROUP_1).getMaxActivationVolumeGainIndex(); 6636 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6637 TEST_PRIMARY_ZONE_GROUP_1, maxActivationVolume + 1); 6638 6639 requestHalAudioFocus(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE); 6640 6641 expectWithMessage("Playback group volume for HAL focus and above-activation gain index") 6642 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1)) 6643 .isEqualTo(maxActivationVolume); 6644 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6645 eq(TEST_PRIMARY_ZONE_GROUP_1), anyInt()); 6646 expectWithMessage("Volume event callback for HAL focus and above-activation gain index") 6647 .that(volumeEventCallback.waitForCallback()).isTrue(); 6648 expectWithMessage("Volume events count after HAL focus and above-activation gain" 6649 + " index adjustment").that(volumeEventCallback.getVolumeGroupEvents()) 6650 .hasSize(1); 6651 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6652 expectWithMessage("Volume event type after HAL focus and above-activation gain" 6653 + " index adjustment").that(groupEvent.getEventTypes()) 6654 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6655 expectWithMessage("Volume group info after HAL focus and above-activation gain" 6656 + " index adjustment").that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6657 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1)); 6658 } 6659 6660 @Test requestHalAudioFocus_withVolumeInActivationVolumeRange()6661 public void requestHalAudioFocus_withVolumeInActivationVolumeRange() 6662 throws Exception { 6663 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6664 when(mAudioManager.requestAudioFocus(any())).thenReturn( 6665 AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 6666 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6667 TestCarVolumeEventCallback volumeEventCallback = 6668 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6669 service.registerCarVolumeEventCallback(volumeEventCallback); 6670 int gainIndexInActivationVolumeRange = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6671 TEST_PRIMARY_ZONE_GROUP_1).getMaxActivationVolumeGainIndex() - 1; 6672 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, 6673 TEST_PRIMARY_ZONE_GROUP_1, gainIndexInActivationVolumeRange); 6674 6675 requestHalAudioFocus(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE); 6676 6677 expectWithMessage("Playback group volume for HAL focus in activation volume index range") 6678 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1)) 6679 .isEqualTo(gainIndexInActivationVolumeRange); 6680 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6681 eq(TEST_PRIMARY_ZONE_GROUP_1), anyInt()); 6682 expectWithMessage("No volume event callback for HAL focus in activation volume" 6683 + " index range").that(volumeEventCallback.waitForCallback()).isFalse(); 6684 } 6685 6686 @Test onCallStateChanged_withOffHookStateAndVolumeBelowMinActivationVolume()6687 public void onCallStateChanged_withOffHookStateAndVolumeBelowMinActivationVolume() 6688 throws Exception { 6689 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6690 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6691 TelephonyCallback.CallStateListener callStateListener = getCallStateListener(); 6692 TestCarVolumeEventCallback volumeEventCallback = 6693 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6694 service.registerCarVolumeEventCallback(volumeEventCallback); 6695 int voiceGroupId = service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 6696 USAGE_VOICE_COMMUNICATION); 6697 int minActivationVolume = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6698 TEST_PRIMARY_ZONE_GROUP_1).getMinActivationVolumeGainIndex(); 6699 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, voiceGroupId, 6700 minActivationVolume - 1); 6701 6702 callStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK); 6703 6704 expectWithMessage("Playback group volume for off-hook and below-activation gain index") 6705 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, voiceGroupId)) 6706 .isEqualTo(minActivationVolume); 6707 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6708 eq(voiceGroupId), anyInt()); 6709 expectWithMessage("Volume event callback for off-hook and below-activation gain index") 6710 .that(volumeEventCallback.waitForCallback()).isTrue(); 6711 expectWithMessage("Volume events count for off-hook after below-activation gain index " 6712 + "adjustment").that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6713 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6714 expectWithMessage("Volume event type for off-hook after below-activation gain index " 6715 + "adjustment").that(groupEvent.getEventTypes()) 6716 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6717 expectWithMessage("Volume group info for off-hook after below-activation gain index " 6718 + "adjustment").that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6719 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, voiceGroupId)); 6720 } 6721 6722 @Test onCallStateChanged_withRingingStateAndVolumeBelowMinActivationVolume()6723 public void onCallStateChanged_withRingingStateAndVolumeBelowMinActivationVolume() 6724 throws Exception { 6725 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6726 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6727 TelephonyCallback.CallStateListener callStateListener = getCallStateListener(); 6728 TestCarVolumeEventCallback volumeEventCallback = 6729 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6730 service.registerCarVolumeEventCallback(volumeEventCallback); 6731 int ringGroupId = service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 6732 USAGE_NOTIFICATION_RINGTONE); 6733 int minActivationVolume = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6734 TEST_PRIMARY_ZONE_GROUP_1).getMinActivationVolumeGainIndex(); 6735 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, ringGroupId, 6736 minActivationVolume - 1); 6737 6738 callStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING); 6739 6740 expectWithMessage("Playback group volume for ringing and below-activation gain index") 6741 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, ringGroupId)) 6742 .isEqualTo(minActivationVolume); 6743 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6744 eq(ringGroupId), anyInt()); 6745 expectWithMessage("Volume event callback for ringing and below-activation gain index") 6746 .that(volumeEventCallback.waitForCallback()).isTrue(); 6747 expectWithMessage("Volume events count for ringing after below-activation gain index " 6748 + "adjustment").that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 6749 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 6750 expectWithMessage("Volume event type for ringing after below-activation gain index " 6751 + "adjustment").that(groupEvent.getEventTypes()) 6752 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 6753 expectWithMessage("Volume group info for ringing after below-activation gain index " 6754 + "adjustment").that(groupEvent.getCarVolumeGroupInfos()).containsExactly( 6755 service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, ringGroupId)); 6756 } 6757 6758 @Test onCallStateChanged_withRingingStateAndWithinActivationVolumeRange()6759 public void onCallStateChanged_withRingingStateAndWithinActivationVolumeRange() 6760 throws Exception { 6761 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_MIN_MAX_ACTIVATION_VOLUME); 6762 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6763 TelephonyCallback.CallStateListener callStateListener = getCallStateListener(); 6764 TestCarVolumeEventCallback volumeEventCallback = 6765 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6766 service.registerCarVolumeEventCallback(volumeEventCallback); 6767 int ringGroupId = service.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 6768 USAGE_NOTIFICATION_RINGTONE); 6769 int gainIndexInActivationVolumeRange = service.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 6770 TEST_PRIMARY_ZONE_GROUP_0).getMinActivationVolumeGainIndex() + 1; 6771 setVolumeForGroup(service, volumeEventCallback, PRIMARY_AUDIO_ZONE, ringGroupId, 6772 gainIndexInActivationVolumeRange); 6773 6774 callStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_RINGING); 6775 6776 expectWithMessage("Playback group volume for ring state in activation volume index range") 6777 .that(service.getGroupVolume(PRIMARY_AUDIO_ZONE, ringGroupId)) 6778 .isEqualTo(gainIndexInActivationVolumeRange); 6779 verify(mCarVolumeCallbackHandler, never()).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 6780 eq(ringGroupId), anyInt()); 6781 expectWithMessage("No volume event callback for ring state in activation volume" 6782 + " index range").that(volumeEventCallback.waitForCallback()).isFalse(); 6783 } 6784 6785 @Test unregisterCarVolumeEventCallback_forCarVolumeEventHandler()6786 public void unregisterCarVolumeEventCallback_forCarVolumeEventHandler() throws Exception { 6787 CarAudioService service = setUpAudioServiceWithMinMaxActivationVolume(/* enabled= */ true); 6788 TestCarVolumeEventCallback volumeEventCallback = 6789 new TestCarVolumeEventCallback(TEST_CALLBACK_TIMEOUT_MS); 6790 service.registerCarVolumeEventCallback(volumeEventCallback); 6791 6792 service.unregisterCarVolumeEventCallback(volumeEventCallback); 6793 6794 service.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 6795 /* mute= */ true, TEST_FLAGS); 6796 expectWithMessage("Volume event callback reception status with callback unregistered") 6797 .that(volumeEventCallback.waitForCallback()).isFalse(); 6798 } 6799 6800 @Test 6801 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) onDevicesToDuckChange_withDuckingConfigEnabledAndMatchedRRO()6802 public void onDevicesToDuckChange_withDuckingConfigEnabledAndMatchedRRO() throws Exception { 6803 boolean useHALDucking = true; 6804 CarAudioService service = setUpCarAudioServiceWithDuckingConfiguredInFile( 6805 R.raw.car_audio_configuration_with_HAL_ducking_config_enabled, 6806 useHALDucking); 6807 assignOccupantToAudioZones(); 6808 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 6809 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 6810 ArgumentCaptor<List<CarDuckingInfo>> carDuckingInfosCaptor = 6811 ArgumentCaptor.forClass(List.class); 6812 6813 verify(mAudioControlWrapperAidl).onDevicesToDuckChange(carDuckingInfosCaptor.capture()); 6814 6815 verifyMediaDuckingInfoInZone(carDuckingInfosCaptor, TEST_REAR_RIGHT_ZONE_ID, 6816 " with HAL ducking config enabled and matched RRO"); 6817 } 6818 6819 @Test 6820 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) onDevicesToDuckChange_withDuckingConfigEnabledAndUnmatchedRRO()6821 public void onDevicesToDuckChange_withDuckingConfigEnabledAndUnmatchedRRO() throws Exception { 6822 boolean useHALDucking = false; 6823 CarAudioService service = setUpCarAudioServiceWithDuckingConfiguredInFile( 6824 R.raw.car_audio_configuration_with_HAL_ducking_config_enabled, 6825 useHALDucking); 6826 assignOccupantToAudioZones(); 6827 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 6828 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 6829 ArgumentCaptor<List<CarDuckingInfo>> carDuckingInfosCaptor = 6830 ArgumentCaptor.forClass(List.class); 6831 6832 verify(mAudioControlWrapperAidl).onDevicesToDuckChange(carDuckingInfosCaptor.capture()); 6833 6834 verifyMediaDuckingInfoInZone(carDuckingInfosCaptor, TEST_REAR_RIGHT_ZONE_ID, 6835 " with HAL ducking config enabled and unmatched RRO"); 6836 } 6837 6838 @Test 6839 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) onDevicesToDuckChange_withDuckingConfigDisabledAndMatchedRRO()6840 public void onDevicesToDuckChange_withDuckingConfigDisabledAndMatchedRRO() throws Exception { 6841 boolean useHALDucking = false; 6842 CarAudioService service = setUpCarAudioServiceWithDuckingConfiguredInFile( 6843 R.raw.car_audio_configuration_with_HAL_ducking_config_disabled, 6844 useHALDucking); 6845 assignOccupantToAudioZones(); 6846 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 6847 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 6848 6849 verify(mAudioControlWrapperAidl, never()).onDevicesToDuckChange(any()); 6850 } 6851 6852 @Test 6853 @EnableFlags({Flags.FLAG_AUDIO_VENDOR_FREEZE_IMPROVEMENTS}) onDevicesToDuckChange_withDuckingConfigDisabledAndUnmatchedRRO()6854 public void onDevicesToDuckChange_withDuckingConfigDisabledAndUnmatchedRRO() throws Exception { 6855 boolean useHALDucking = true; 6856 CarAudioService service = setUpCarAudioServiceWithDuckingConfiguredInFile( 6857 R.raw.car_audio_configuration_with_HAL_ducking_config_disabled, 6858 useHALDucking); 6859 assignOccupantToAudioZones(); 6860 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 6861 service.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 6862 6863 verify(mAudioControlWrapperAidl, never()).onDevicesToDuckChange(any()); 6864 } 6865 waitForInternalCallback()6866 private void waitForInternalCallback() throws Exception { 6867 CountDownLatch latch = new CountDownLatch(1); 6868 mHandler.post(latch::countDown); 6869 latch.await(TEST_ZONE_CONFIG_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 6870 } 6871 initServiceAndWaitForComplete(CarAudioService service)6872 private void initServiceAndWaitForComplete(CarAudioService service) throws Exception { 6873 service.init(); 6874 assertWithMessage("waitForInitComplete succeeded").that( 6875 service.waitForInitComplete(INIT_TIMEOUT_MS)).isTrue(); 6876 } 6877 setupAudioServiceUsingAudioControlWithoutInit()6878 private CarAudioService setupAudioServiceUsingAudioControlWithoutInit() throws Exception { 6879 when(mAudioControlWrapperAidl.supportsFeature( 6880 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_CONFIGURATION)).thenReturn(true); 6881 var deviceConfig = new AudioDeviceConfiguration(); 6882 deviceConfig.routingConfig = RoutingDeviceConfiguration.DYNAMIC_AUDIO_ROUTING; 6883 when(mAudioControlWrapperAidl.getAudioDeviceConfiguration()).thenReturn(deviceConfig); 6884 when(mAudioControlWrapperAidl.getCarAudioZones()) 6885 .thenReturn(createAudioServiceAudioZones()); 6886 // File not use for configuration for to differentiate between HAL config and file config 6887 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration_without_zone_mapping); 6888 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6889 return new CarAudioService(mMockContext, mAudioManager, 6890 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6891 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 6892 } 6893 setUpCarAudioServiceWithoutZoneMapping()6894 private CarAudioService setUpCarAudioServiceWithoutZoneMapping() throws Exception { 6895 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration_without_zone_mapping); 6896 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6897 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 6898 .thenReturn(SUCCESS); 6899 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, mAudioManager, 6900 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6901 /* audioFadeConfigurationPath= */ null); 6902 initServiceAndWaitForComplete(noZoneMappingAudioService); 6903 return noZoneMappingAudioService; 6904 } 6905 setUpAudioService()6906 private CarAudioService setUpAudioService() throws Exception { 6907 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration); 6908 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6909 CarAudioService service = new CarAudioService(mMockContext, mAudioManager, 6910 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6911 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 6912 initServiceAndWaitForComplete(service); 6913 return service; 6914 } 6915 setUpAudioServiceWithoutInit()6916 private CarAudioService setUpAudioServiceWithoutInit() throws Exception { 6917 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration); 6918 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6919 CarAudioService service = new CarAudioService(mMockContext, mAudioManager, 6920 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6921 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 6922 return service; 6923 } 6924 setUpAudioServiceWithoutDynamicRouting()6925 private CarAudioService setUpAudioServiceWithoutDynamicRouting() throws Exception { 6926 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration); 6927 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6928 when(mMockResources.getBoolean(audioUseDynamicRouting)).thenReturn(false); 6929 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, mAudioManager, 6930 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6931 /* audioFadeConfigurationPath= */ null); 6932 initServiceAndWaitForComplete(nonDynamicAudioService); 6933 return nonDynamicAudioService; 6934 } 6935 setUpAudioServiceWithDisabledResource(int resource)6936 private CarAudioService setUpAudioServiceWithDisabledResource(int resource) throws Exception { 6937 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration); 6938 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6939 when(mMockResources.getBoolean(resource)).thenReturn(false); 6940 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, mAudioManager, 6941 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6942 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 6943 initServiceAndWaitForComplete(nonDynamicAudioService); 6944 return nonDynamicAudioService; 6945 } 6946 getRegisteredZoneConfigCallback( CarAudioService audioServiceWithDynamicDevices)6947 private static TestAudioZoneConfigurationsChangeCallback getRegisteredZoneConfigCallback( 6948 CarAudioService audioServiceWithDynamicDevices) { 6949 TestAudioZoneConfigurationsChangeCallback configCallback = 6950 new TestAudioZoneConfigurationsChangeCallback(); 6951 audioServiceWithDynamicDevices.registerAudioZoneConfigsChangeCallback(configCallback); 6952 return configCallback; 6953 } 6954 captureAudioDeviceCallback()6955 private AudioDeviceCallback captureAudioDeviceCallback() { 6956 ArgumentCaptor<AudioDeviceCallback> captor = 6957 ArgumentCaptor.forClass(AudioDeviceCallback.class); 6958 verify(mAudioManager).registerAudioDeviceCallback(captor.capture(), any()); 6959 return captor.getValue(); 6960 } 6961 setUpAudioServiceWithDynamicDevices()6962 private CarAudioService setUpAudioServiceWithDynamicDevices() throws Exception { 6963 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration_using_dynamic_routing); 6964 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6965 return setUpAudioServiceWithDynamicDevices(mTempCarAudioConfigFile, 6966 mTempCarAudioFadeConfigFile); 6967 } 6968 setUpAudioServiceWithDynamicDevices(TemporaryFile fileAudio, TemporaryFile fileFade)6969 private CarAudioService setUpAudioServiceWithDynamicDevices(TemporaryFile fileAudio, 6970 TemporaryFile fileFade) { 6971 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_DYNAMIC_DEVICES); 6972 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(true); 6973 when(mMockResources.getBoolean(audioUseCoreRouting)).thenReturn(false); 6974 CarAudioService audioServiceWithDynamicDevices = new CarAudioService(mMockContext, 6975 mAudioManager, fileAudio.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6976 fileFade.getFile().getAbsolutePath()); 6977 return audioServiceWithDynamicDevices; 6978 } 6979 setUpAudioServiceWithMinMaxActivationVolume(boolean enabled)6980 private CarAudioService setUpAudioServiceWithMinMaxActivationVolume(boolean enabled) 6981 throws Exception { 6982 setUpTempFileForAudioConfiguration( 6983 R.raw.car_audio_configuration_with_min_max_activation_volume); 6984 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 6985 when(mMockResources.getBoolean(audioUseMinMaxActivationVolume)).thenReturn(enabled); 6986 CarAudioService service = new CarAudioService(mMockContext, mAudioManager, 6987 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 6988 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 6989 initServiceAndWaitForComplete(service); 6990 return service; 6991 } 6992 getUpdatedCarAudioZoneConfigInfo( CarAudioZoneConfigInfo previousConfig, CarAudioService service)6993 private CarAudioZoneConfigInfo getUpdatedCarAudioZoneConfigInfo( 6994 CarAudioZoneConfigInfo previousConfig, CarAudioService service) { 6995 List<CarAudioZoneConfigInfo> infos = 6996 service.getAudioZoneConfigInfos(previousConfig.getZoneId()); 6997 CarAudioZoneConfigInfo previousUpdated = infos.stream() 6998 .filter(i-> i.hasSameConfigInfo(previousConfig)).findFirst().orElseThrow( 6999 () -> new NoSuchPropertyException("Missing previously selected config")); 7000 return previousUpdated; 7001 } 7002 getOccupantZoneCallback()7003 private ICarOccupantZoneCallback getOccupantZoneCallback() { 7004 ArgumentCaptor<ICarOccupantZoneCallback> captor = 7005 ArgumentCaptor.forClass(ICarOccupantZoneCallback.class); 7006 verify(mMockOccupantZoneService).registerCallback(captor.capture()); 7007 return captor.getValue(); 7008 } 7009 getAudioServerStateCallback()7010 private AudioServerStateCallback getAudioServerStateCallback() { 7011 ArgumentCaptor<AudioServerStateCallback> captor = ArgumentCaptor.forClass( 7012 AudioServerStateCallback.class); 7013 verify(mAudioManager, timeout(INIT_TIMEOUT_MS)).setAudioServerStateCallback( 7014 any(), captor.capture()); 7015 return captor.getValue(); 7016 } 7017 removeUpToEquals(String command)7018 private String removeUpToEquals(String command) { 7019 return command.replaceAll("^[^=]*=", ""); 7020 } 7021 captureAudioMirrorInfoCommand(int count)7022 private String captureAudioMirrorInfoCommand(int count) { 7023 ArgumentCaptor<String> capture = ArgumentCaptor.forClass(String.class); 7024 verify(mAudioManager, times(count)).setParameters(capture.capture()); 7025 return capture.getValue(); 7026 } 7027 getAudioZonesMirrorStatusCallback( CarAudioService service)7028 private TestAudioZonesMirrorStatusCallbackCallback getAudioZonesMirrorStatusCallback( 7029 CarAudioService service) { 7030 TestAudioZonesMirrorStatusCallbackCallback callback = 7031 new TestAudioZonesMirrorStatusCallbackCallback(/* count= */ 1); 7032 service.registerAudioZonesMirrorStatusCallback(callback); 7033 return callback; 7034 } 7035 assignOccupantToAudioZones()7036 private void assignOccupantToAudioZones() throws RemoteException { 7037 ICarOccupantZoneCallback occupantZoneCallback = getOccupantZoneCallback(); 7038 occupantZoneCallback.onOccupantZoneConfigChanged( 7039 CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 7040 } 7041 simulateLogoutPassengers()7042 private void simulateLogoutPassengers() throws Exception { 7043 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 7044 .thenReturn(UserManagerHelper.USER_NULL); 7045 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 7046 .thenReturn(UserManagerHelper.USER_NULL); 7047 7048 assignOccupantToAudioZones(); 7049 } 7050 simulateLogoutRightPassengers()7051 private void simulateLogoutRightPassengers() throws Exception { 7052 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 7053 .thenReturn(UserManagerHelper.USER_NULL); 7054 7055 assignOccupantToAudioZones(); 7056 } 7057 simulatePassengersSwitch()7058 private void simulatePassengersSwitch() throws Exception { 7059 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 7060 .thenReturn(TEST_REAR_RIGHT_USER_ID); 7061 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 7062 .thenReturn(TEST_REAR_LEFT_USER_ID); 7063 7064 assignOccupantToAudioZones(); 7065 } 7066 createCarAudioGainConfigInfo(int zoneId, String devicePortAddress, int volumeIndex)7067 private CarAudioGainConfigInfo createCarAudioGainConfigInfo(int zoneId, 7068 String devicePortAddress, int volumeIndex) { 7069 AudioGainConfigInfo configInfo = new AudioGainConfigInfo(); 7070 configInfo.zoneId = zoneId; 7071 configInfo.devicePortAddress = devicePortAddress; 7072 configInfo.volumeIndex = volumeIndex; 7073 return new CarAudioGainConfigInfo(configInfo); 7074 } 7075 getHalAudioGainCallback()7076 private HalAudioGainCallback getHalAudioGainCallback() { 7077 ArgumentCaptor<HalAudioGainCallback> captor = ArgumentCaptor.forClass( 7078 HalAudioGainCallback.class); 7079 verify(mAudioControlWrapperAidl).registerAudioGainCallback(captor.capture()); 7080 return captor.getValue(); 7081 } 7082 createHalAudioDeviceInfo(int id, String name, int minVal, int maxVal, int defaultVal, int stepVal, int type, String address)7083 private HalAudioDeviceInfo createHalAudioDeviceInfo(int id, String name, int minVal, 7084 int maxVal, int defaultVal, int stepVal, int type, String address) { 7085 AudioPortDeviceExt deviceExt = new AudioPortDeviceExt(); 7086 deviceExt.device = new AudioDevice(); 7087 deviceExt.device.type = new AudioDeviceDescription(); 7088 deviceExt.device.type.type = type; 7089 deviceExt.device.type.connection = CONNECTION_BUS; 7090 deviceExt.device.address = AudioDeviceAddress.id(address); 7091 AudioPort audioPort = new AudioPort(); 7092 audioPort.id = id; 7093 audioPort.name = name; 7094 audioPort.gains = new android.media.audio.common.AudioGain[] { 7095 new android.media.audio.common.AudioGain() {{ 7096 mode = JOINT; 7097 minValue = minVal; 7098 maxValue = maxVal; 7099 defaultValue = defaultVal; 7100 stepValue = stepVal; 7101 }} 7102 }; 7103 audioPort.ext = AudioPortExt.device(deviceExt); 7104 return new HalAudioDeviceInfo(audioPort); 7105 } 7106 getHalModuleChangeCallback()7107 private HalAudioModuleChangeCallback getHalModuleChangeCallback() { 7108 ArgumentCaptor<HalAudioModuleChangeCallback> captor = ArgumentCaptor.forClass( 7109 HalAudioModuleChangeCallback.class); 7110 verify(mAudioControlWrapperAidl).setModuleChangeCallback(captor.capture()); 7111 return captor.getValue(); 7112 } 7113 getCarAudioPlaybackCallback()7114 private AudioPlaybackCallback getCarAudioPlaybackCallback() { 7115 ArgumentCaptor<AudioPlaybackCallback> captor = ArgumentCaptor.forClass( 7116 AudioPlaybackCallback.class); 7117 verify(mAudioManager).registerAudioPlaybackCallback(captor.capture(), any()); 7118 return captor.getValue(); 7119 } 7120 getAudioKeyEventListener()7121 private KeyEventListener getAudioKeyEventListener() { 7122 ArgumentCaptor<KeyEventListener> captor = ArgumentCaptor.forClass(KeyEventListener.class); 7123 verify(mMockCarInputService).registerKeyEventListener(captor.capture(), any()); 7124 return captor.getValue(); 7125 } 7126 getCallStateListener()7127 private TelephonyCallback.CallStateListener getCallStateListener() { 7128 ArgumentCaptor<TelephonyCallback> captor = 7129 ArgumentCaptor.forClass(TelephonyCallback.class); 7130 verify(mMockTelephonyManager).registerTelephonyCallback(any(), captor.capture()); 7131 return (TelephonyCallback.CallStateListener) captor.getValue(); 7132 } 7133 requestHalAudioFocus(int usage)7134 private void requestHalAudioFocus(int usage) { 7135 ArgumentCaptor<HalFocusListener> captor = 7136 ArgumentCaptor.forClass(HalFocusListener.class); 7137 verify(mAudioControlWrapperAidl).registerFocusListener(captor.capture()); 7138 HalFocusListener halFocusListener = captor.getValue(); 7139 halFocusListener.requestAudioFocus(usageToMetadata(usage), PRIMARY_AUDIO_ZONE, 7140 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 7141 } 7142 mockActivePlayback()7143 private void mockActivePlayback() { 7144 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 7145 callback.onPlaybackConfigChanged(List.of(getPlaybackConfig())); 7146 } 7147 getPlaybackConfig()7148 private AudioPlaybackConfiguration getPlaybackConfig() { 7149 AudioAttributes audioAttributes = new AudioAttributes.Builder() 7150 .setUsage(USAGE_MEDIA).build(); 7151 AudioPlaybackConfiguration config = mock(AudioPlaybackConfiguration.class); 7152 when(config.getAudioAttributes()).thenReturn(audioAttributes); 7153 when(config.getAudioDeviceInfo()).thenReturn(mCarAudioDeviceUtils.mMediaOutputDevice); 7154 when(config.isActive()).thenReturn(true); 7155 7156 return config; 7157 } 7158 setUpCarAudioServiceWithoutMirroring()7159 private CarAudioService setUpCarAudioServiceWithoutMirroring() throws Exception { 7160 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration_without_mirroring); 7161 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 7162 AudioDeviceInfo[] outputDevices = mCarAudioDeviceUtils.generateOutputDeviceInfos(); 7163 when(mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)).thenReturn(outputDevices); 7164 CarAudioService service = new CarAudioService(mMockContext, mAudioManager, 7165 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 7166 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 7167 initServiceAndWaitForComplete(service); 7168 return service; 7169 } 7170 setUpCarAudioServiceWithVersionTwoVolumeList()7171 private CarAudioService setUpCarAudioServiceWithVersionTwoVolumeList() throws Exception { 7172 setUpTempFileForAudioConfiguration(R.raw.car_audio_configuration); 7173 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 7174 when(mMockResources.getInteger(audioVolumeAdjustmentContextsVersion)) 7175 .thenReturn(AUDIO_CONTEXT_PRIORITY_LIST_VERSION_TWO); 7176 CarAudioService service = new CarAudioService(mMockContext, mAudioManager, 7177 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 7178 mTempCarAudioFadeConfigFile.getFile().getAbsolutePath()); 7179 initServiceAndWaitForComplete(service); 7180 return service; 7181 } 7182 setUpTempFileForAudioConfiguration(int resource)7183 private void setUpTempFileForAudioConfiguration(int resource) throws Exception { 7184 try (InputStream configurationStream = mContext.getResources().openRawResource(resource)) { 7185 mTempCarAudioConfigFile = new TemporaryFile("xml"); 7186 mTempCarAudioConfigFile.write(new String(configurationStream.readAllBytes())); 7187 } 7188 } 7189 setUpTempFileForAudioFadeConfiguration(int resource)7190 private void setUpTempFileForAudioFadeConfiguration(int resource) throws Exception { 7191 try (InputStream configurationStream = mContext.getResources().openRawResource(resource)) { 7192 mTempCarAudioFadeConfigFile = new TemporaryFile("xml"); 7193 mTempCarAudioFadeConfigFile.write(new String(configurationStream.readAllBytes())); 7194 } 7195 } 7196 setUpCarAudioServiceWithFadeManagerEnabled()7197 private CarAudioService setUpCarAudioServiceWithFadeManagerEnabled() throws Exception { 7198 mSetFlagsRule.enableFlags(FLAG_ENABLE_FADE_MANAGER_CONFIGURATION); 7199 mSetFlagsRule.enableFlags(Flags.FLAG_CAR_AUDIO_FADE_MANAGER_CONFIGURATION); 7200 when(mMockResources.getBoolean(audioUseFadeManagerConfiguration)).thenReturn(true); 7201 return setUpAudioService(); 7202 } 7203 setUpCarAudioServiceUsingCoreAudioRoutingAndVolume()7204 private CarAudioService setUpCarAudioServiceUsingCoreAudioRoutingAndVolume() throws Exception { 7205 when(mMockResources.getBoolean(audioUseCoreVolume)).thenReturn(true); 7206 when(mMockResources.getBoolean(audioUseCoreRouting)).thenReturn(true); 7207 setUpTempFileForAudioConfiguration( 7208 R.raw.car_audio_configuration_using_core_routing_and_volume); 7209 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 7210 7211 CarAudioService useCoreAudioCarAudioService = new CarAudioService(mMockContext, 7212 mAudioManager, 7213 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 7214 /* audioFadeConfigurationPath= */ null); 7215 initServiceAndWaitForComplete(useCoreAudioCarAudioService); 7216 return useCoreAudioCarAudioService; 7217 } 7218 setUpCarAudioServiceUsingCoreAudioRoutingAndVolumeInConfigFile()7219 private CarAudioService setUpCarAudioServiceUsingCoreAudioRoutingAndVolumeInConfigFile() 7220 throws Exception { 7221 setUpTempFileForAudioConfiguration( 7222 R.raw.car_audio_configuration_with_core_audio_routing_and_volume_configs_enabled); 7223 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 7224 7225 CarAudioService useCoreAudioCarAudioService = new CarAudioService(mMockContext, 7226 mAudioManager, 7227 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 7228 /* audioFadeConfigurationPath= */ null); 7229 initServiceAndWaitForComplete(useCoreAudioCarAudioService); 7230 return useCoreAudioCarAudioService; 7231 } 7232 setUpCarAudioServiceWithCoreAudioRoutingAndVolumeDisabledInConfigFile()7233 private CarAudioService setUpCarAudioServiceWithCoreAudioRoutingAndVolumeDisabledInConfigFile() 7234 throws Exception { 7235 setUpTempFileForAudioConfiguration( 7236 R.raw.car_audio_configuration_with_core_audio_routing_and_volume_configs_disabled); 7237 setUpTempFileForAudioFadeConfiguration(R.raw.car_audio_fade_configuration); 7238 7239 CarAudioService useCoreAudioCarAudioService = new CarAudioService(mMockContext, 7240 mAudioManager, 7241 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 7242 /* audioFadeConfigurationPath= */ null); 7243 initServiceAndWaitForComplete(useCoreAudioCarAudioService); 7244 return useCoreAudioCarAudioService; 7245 } 7246 setUpCarAudioServiceWithVolumeGroupMutingConfiguredInFile( int resourceId, boolean useGroupMuting)7247 private CarAudioService setUpCarAudioServiceWithVolumeGroupMutingConfiguredInFile( 7248 int resourceId, boolean useGroupMuting) 7249 throws Exception { 7250 setUpTempFileForAudioConfiguration(resourceId); 7251 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)).thenReturn(useGroupMuting); 7252 7253 CarAudioService audioCarAudioService = new CarAudioService(mMockContext, mAudioManager, 7254 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 7255 /* audioFadeConfigurationPath= */ null); 7256 initServiceAndWaitForComplete(audioCarAudioService); 7257 return audioCarAudioService; 7258 } 7259 setUpCarAudioServiceWithDuckingConfiguredInFile(int resourceId, boolean useHALDucking)7260 private CarAudioService setUpCarAudioServiceWithDuckingConfiguredInFile(int resourceId, 7261 boolean useHALDucking) throws Exception { 7262 setUpTempFileForAudioConfiguration(resourceId); 7263 when(mMockResources.getBoolean(audioUseHalDuckingSignals)).thenReturn(useHALDucking); 7264 7265 CarAudioService audioCarAudioService = new CarAudioService(mMockContext, mAudioManager, 7266 mTempCarAudioConfigFile.getFile().getAbsolutePath(), mCarVolumeCallbackHandler, 7267 /* audioFadeConfigurationPath= */ null); 7268 initServiceAndWaitForComplete(audioCarAudioService); 7269 return audioCarAudioService; 7270 } 7271 mockGrantCarControlAudioSettingsPermission()7272 private void mockGrantCarControlAudioSettingsPermission() { 7273 mockContextCheckCallingOrSelfPermission(mMockContext, 7274 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS, PERMISSION_GRANTED); 7275 } 7276 mockDenyCarControlAudioSettingsPermission()7277 private void mockDenyCarControlAudioSettingsPermission() { 7278 mockContextCheckCallingOrSelfPermission(mMockContext, 7279 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS, PERMISSION_DENIED); 7280 } 7281 mockDenyCarControlAudioVolumePermission()7282 private void mockDenyCarControlAudioVolumePermission() { 7283 mockContextCheckCallingOrSelfPermission(mMockContext, 7284 PERMISSION_CAR_CONTROL_AUDIO_VOLUME, PERMISSION_DENIED); 7285 } 7286 generateInputDeviceInfos()7287 private AudioDeviceInfo[] generateInputDeviceInfos() { 7288 mMicrophoneInputDevice = new AudioDeviceInfoBuilder() 7289 .setAddressName(PRIMARY_ZONE_MICROPHONE_ADDRESS) 7290 .setType(TYPE_BUILTIN_MIC) 7291 .setIsSource(true) 7292 .build(); 7293 mFmTunerInputDevice = new AudioDeviceInfoBuilder() 7294 .setAddressName(PRIMARY_ZONE_FM_TUNER_ADDRESS) 7295 .setType(TYPE_FM_TUNER) 7296 .setIsSource(true) 7297 .build(); 7298 return new AudioDeviceInfo[]{mMicrophoneInputDevice, mFmTunerInputDevice}; 7299 } 7300 mockCoreAudioRoutingAndVolume()7301 private void mockCoreAudioRoutingAndVolume() { 7302 doReturn(CoreAudioRoutingUtils.getProductStrategies()) 7303 .when(AudioManagerWrapper::getAudioProductStrategies); 7304 doReturn(CoreAudioRoutingUtils.getVolumeGroups()) 7305 .when(AudioManagerWrapper::getAudioVolumeGroups); 7306 7307 when(mAudioManager.getMinVolumeIndexForAttributes( 7308 eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 7309 .thenReturn(CoreAudioRoutingUtils.MUSIC_MIN_INDEX); 7310 when(mAudioManager.getMaxVolumeIndexForAttributes( 7311 eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 7312 .thenReturn(CoreAudioRoutingUtils.MUSIC_MAX_INDEX); 7313 when(mAudioManager.getVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 7314 .thenReturn(CoreAudioRoutingUtils.MUSIC_AM_INIT_INDEX); 7315 when(mAudioManager.getLastAudibleVolumeForVolumeGroup(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 7316 .thenReturn(CoreAudioRoutingUtils.MUSIC_AM_INIT_INDEX); 7317 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 7318 .thenReturn(false); 7319 7320 when(mAudioManager.getMinVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.NAV_ATTRIBUTES))) 7321 .thenReturn(CoreAudioRoutingUtils.NAV_MIN_INDEX); 7322 when(mAudioManager.getMaxVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.NAV_ATTRIBUTES))) 7323 .thenReturn(CoreAudioRoutingUtils.NAV_MAX_INDEX); 7324 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.NAV_GROUP_ID)) 7325 .thenReturn(false); 7326 7327 when(mAudioManager.getMinVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.OEM_ATTRIBUTES))) 7328 .thenReturn(CoreAudioRoutingUtils.OEM_MIN_INDEX); 7329 when(mAudioManager.getMaxVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.OEM_ATTRIBUTES))) 7330 .thenReturn(CoreAudioRoutingUtils.OEM_MAX_INDEX); 7331 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.OEM_GROUP_ID)) 7332 .thenReturn(false); 7333 7334 doReturn(CoreAudioRoutingUtils.MUSIC_GROUP_ID) 7335 .when(() -> CoreAudioHelper.getVolumeGroupIdForAudioAttributes( 7336 CoreAudioRoutingUtils.MUSIC_ATTRIBUTES)); 7337 doReturn(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES) 7338 .when(() -> CoreAudioHelper.selectAttributesForVolumeGroupName( 7339 CoreAudioRoutingUtils.MUSIC_GROUP_NAME)); 7340 7341 doReturn(CoreAudioRoutingUtils.NAV_GROUP_ID) 7342 .when(() -> CoreAudioHelper.getVolumeGroupIdForAudioAttributes( 7343 CoreAudioRoutingUtils.NAV_ATTRIBUTES)); 7344 doReturn(CoreAudioRoutingUtils.NAV_ATTRIBUTES) 7345 .when(() -> CoreAudioHelper.selectAttributesForVolumeGroupName( 7346 CoreAudioRoutingUtils.NAV_GROUP_NAME)); 7347 7348 doReturn(CoreAudioRoutingUtils.OEM_GROUP_ID) 7349 .when(() -> CoreAudioHelper.getVolumeGroupIdForAudioAttributes( 7350 CoreAudioRoutingUtils.OEM_ATTRIBUTES)); 7351 doReturn(CoreAudioRoutingUtils.OEM_ATTRIBUTES) 7352 .when(() -> CoreAudioHelper.selectAttributesForVolumeGroupName( 7353 CoreAudioRoutingUtils.OEM_GROUP_NAME)); 7354 } 7355 createAudioFocusInfoForMedia()7356 private static AudioFocusInfo createAudioFocusInfoForMedia() { 7357 return createAudioFocusInfoForMedia(MEDIA_APP_UID); 7358 } 7359 createAudioFocusInfoForMedia(int uid)7360 private static AudioFocusInfo createAudioFocusInfoForMedia(int uid) { 7361 AudioAttributes.Builder builder = new AudioAttributes.Builder(); 7362 builder.setUsage(USAGE_MEDIA); 7363 7364 return new AudioFocusInfo(builder.build(), uid, MEDIA_CLIENT_ID, 7365 MEDIA_PACKAGE_NAME, AUDIOFOCUS_GAIN, AUDIOFOCUS_LOSS, MEDIA_EMPTY_FLAG, SDK_INT); 7366 } 7367 getFocusChanges(AudioFocusInfo info)7368 private List<Integer> getFocusChanges(AudioFocusInfo info) { 7369 ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class); 7370 verify(mAudioManager, atLeastOnce()).dispatchAudioFocusChange(eq(info), captor.capture(), 7371 any()); 7372 return captor.getAllValues(); 7373 } 7374 verifyMediaDuckingInfoInZone(ArgumentCaptor<List<CarDuckingInfo>> carDuckingInfosCaptor, int zoneId, String message)7375 private void verifyMediaDuckingInfoInZone(ArgumentCaptor<List<CarDuckingInfo>> 7376 carDuckingInfosCaptor, int zoneId, String message) { 7377 expectWithMessage("Zone size of notified ducking info " + message) 7378 .that(carDuckingInfosCaptor.getValue().size()).isEqualTo(1); 7379 CarDuckingInfo duckingInfo = carDuckingInfosCaptor.getValue().get(0); 7380 expectWithMessage("Ducking info zone id " + message) 7381 .that(duckingInfo.mZoneId).isEqualTo(zoneId); 7382 expectWithMessage("Audio attributes holding focus " + message) 7383 .that(CarHalAudioUtils.metadataToAudioAttributes(duckingInfo 7384 .mPlaybackMetaDataHoldingFocus)) 7385 .containsExactly(CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA)); 7386 } 7387 getZoneConfigToSwitch(CarAudioService service, int zoneId)7388 private CarAudioZoneConfigInfo getZoneConfigToSwitch(CarAudioService service, int zoneId) { 7389 CarAudioZoneConfigInfo currentZoneConfigInfo = 7390 service.getCurrentAudioZoneConfigInfo(zoneId); 7391 List<CarAudioZoneConfigInfo> zoneConfigInfos = service.getAudioZoneConfigInfos(zoneId); 7392 7393 for (int index = 0; index < zoneConfigInfos.size(); index++) { 7394 if (currentZoneConfigInfo.equals(zoneConfigInfos.get(index))) { 7395 continue; 7396 } 7397 return zoneConfigInfos.get(index); 7398 } 7399 return null; 7400 } 7401 setVolumeForGroup(CarAudioService service, TestCarVolumeEventCallback volumeEventCallback, int zoneId, int groupId, int volumeIndex)7402 private void setVolumeForGroup(CarAudioService service, 7403 TestCarVolumeEventCallback volumeEventCallback, 7404 int zoneId, int groupId, int volumeIndex) throws Exception { 7405 service.setGroupVolume(zoneId, groupId, volumeIndex, TEST_FLAGS); 7406 resetVolumeCallbacks(volumeEventCallback); 7407 } 7408 createActivePlayback(AudioPlaybackCallback callback, TestCarVolumeEventCallback volumeEventCallback, int playbackUsage, String deviceAddress, int playbackUid)7409 private void createActivePlayback(AudioPlaybackCallback callback, 7410 TestCarVolumeEventCallback volumeEventCallback, 7411 int playbackUsage, String deviceAddress, int playbackUid) 7412 throws Exception { 7413 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 7414 .setUsage(playbackUsage).setDeviceAddress(deviceAddress) 7415 .setClientUid(playbackUid).build())); 7416 resetVolumeCallbacks(volumeEventCallback); 7417 } 7418 resetVolumeCallbacks(TestCarVolumeEventCallback volumeEventCallback)7419 private void resetVolumeCallbacks(TestCarVolumeEventCallback volumeEventCallback) 7420 throws Exception { 7421 volumeEventCallback.waitForCallback(); 7422 volumeEventCallback.reset(); 7423 reset(mCarVolumeCallbackHandler); 7424 } 7425 7426 private static final class TestAudioZoneConfigurationsChangeCallback 7427 extends IAudioZoneConfigurationsChangeCallback.Stub { 7428 7429 private List<CarAudioZoneConfigInfo> mInfos; 7430 private int mStatus = INVALID_STATUS; 7431 7432 private CountDownLatch mStatusLatch = new CountDownLatch(1); 7433 @Override onAudioZoneConfigurationsChanged(List<CarAudioZoneConfigInfo> configs, int status)7434 public void onAudioZoneConfigurationsChanged(List<CarAudioZoneConfigInfo> configs, 7435 int status) { 7436 mInfos = configs; 7437 mStatus = status; 7438 mStatusLatch.countDown(); 7439 } 7440 waitForCallback()7441 private void waitForCallback() throws Exception { 7442 mStatusLatch.await(TEST_ZONE_CONFIG_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 7443 } 7444 reset()7445 public void reset() { 7446 mInfos = null; 7447 mStatus = INVALID_STATUS; 7448 mStatusLatch = new CountDownLatch(1); 7449 } 7450 } 7451 7452 private static final class TestPrimaryZoneMediaAudioRequestCallback extends 7453 IPrimaryZoneMediaAudioRequestCallback.Stub { 7454 private long mRequestId = INVALID_REQUEST_ID; 7455 private CarOccupantZoneManager.OccupantZoneInfo mInfo; 7456 private CountDownLatch mStatusLatch = new CountDownLatch(1); 7457 private int mStatus; 7458 private DeathRecipient mDeathRecipient; 7459 7460 @Override linkToDeath(@onNull DeathRecipient recipient, int flags)7461 public void linkToDeath(@NonNull DeathRecipient recipient, int flags) { 7462 mDeathRecipient = recipient; 7463 super.linkToDeath(recipient, flags); 7464 } 7465 7466 @Override onRequestMediaOnPrimaryZone(CarOccupantZoneManager.OccupantZoneInfo info, long requestId)7467 public void onRequestMediaOnPrimaryZone(CarOccupantZoneManager.OccupantZoneInfo info, 7468 long requestId) { 7469 mInfo = info; 7470 mRequestId = requestId; 7471 mStatusLatch.countDown(); 7472 } 7473 7474 @Override onMediaAudioRequestStatusChanged( @onNull CarOccupantZoneManager.OccupantZoneInfo info, long requestId, int status)7475 public void onMediaAudioRequestStatusChanged( 7476 @NonNull CarOccupantZoneManager.OccupantZoneInfo info, 7477 long requestId, int status) { 7478 mInfo = info; 7479 mRequestId = requestId; 7480 mStatus = status; 7481 mStatusLatch.countDown(); 7482 } 7483 waitForCallback()7484 private void waitForCallback() throws Exception { 7485 mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 7486 } 7487 reset()7488 public void reset() { 7489 mInfo = null; 7490 mRequestId = INVALID_REQUEST_ID; 7491 mStatus = INVALID_STATUS; 7492 mStatusLatch = new CountDownLatch(1); 7493 } 7494 } 7495 7496 private static final class TestMediaRequestStatusCallback extends 7497 IMediaAudioRequestStatusCallback.Stub { 7498 private long mRequestId = INVALID_REQUEST_ID; 7499 private CarOccupantZoneManager.OccupantZoneInfo mInfo; 7500 private int mStatus; 7501 private CountDownLatch mStatusLatch = new CountDownLatch(1); 7502 7503 @Override onMediaAudioRequestStatusChanged( @onNull CarOccupantZoneManager.OccupantZoneInfo info, long requestId, @CarAudioManager.MediaAudioRequestStatus int status)7504 public void onMediaAudioRequestStatusChanged( 7505 @NonNull CarOccupantZoneManager.OccupantZoneInfo info, 7506 long requestId, @CarAudioManager.MediaAudioRequestStatus int status) 7507 throws RemoteException { 7508 mInfo = info; 7509 mRequestId = requestId; 7510 mStatus = status; 7511 mStatusLatch.countDown(); 7512 } 7513 waitForCallback()7514 private void waitForCallback() throws Exception { 7515 mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 7516 } 7517 reset()7518 private void reset() { 7519 mInfo = null; 7520 mRequestId = INVALID_REQUEST_ID; 7521 mStatus = INVALID_STATUS; 7522 mStatusLatch = new CountDownLatch(1); 7523 } 7524 } 7525 7526 private static final class TestAudioZonesMirrorStatusCallbackCallback extends 7527 IAudioZonesMirrorStatusCallback.Stub { 7528 7529 private static final long TEST_CALLBACK_TIMEOUT_MS = 300; 7530 7531 private List<int[]> mZoneIds = new ArrayList<>(); 7532 private List<Integer> mStatus = new ArrayList<>(); 7533 private int mNumberOfCalls = 0; 7534 private CountDownLatch mStatusLatch; 7535 TestAudioZonesMirrorStatusCallbackCallback(int count)7536 private TestAudioZonesMirrorStatusCallbackCallback(int count) { 7537 mStatusLatch = new CountDownLatch(count); 7538 } 7539 7540 @Override onAudioZonesMirrorStatusChanged(int[] zoneIds, int status)7541 public void onAudioZonesMirrorStatusChanged(int[] zoneIds, int status) { 7542 mZoneIds.add(zoneIds); 7543 mStatus.add(status); 7544 mNumberOfCalls++; 7545 mStatusLatch.countDown(); 7546 } 7547 waitForCallback()7548 private void waitForCallback() throws Exception { 7549 mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 7550 } 7551 reset(int count)7552 public void reset(int count) { 7553 mStatusLatch = new CountDownLatch(count); 7554 } 7555 getLastZoneIds()7556 private int[] getLastZoneIds() { 7557 return mZoneIds.get(mZoneIds.size() - 1); 7558 } 7559 getLastStatus()7560 public int getLastStatus() { 7561 return mStatus.get(mStatus.size() - 1); 7562 } 7563 } 7564 7565 private static final class SwitchAudioZoneConfigCallbackImpl extends 7566 ISwitchAudioZoneConfigCallback.Stub { 7567 private CountDownLatch mStatusLatch = new CountDownLatch(1); 7568 private CarAudioZoneConfigInfo mZoneConfig; 7569 private boolean mIsSuccessful; 7570 7571 @Override onAudioZoneConfigSwitched(CarAudioZoneConfigInfo zoneConfig, boolean isSuccessful)7572 public void onAudioZoneConfigSwitched(CarAudioZoneConfigInfo zoneConfig, 7573 boolean isSuccessful) { 7574 mZoneConfig = zoneConfig; 7575 mIsSuccessful = isSuccessful; 7576 mStatusLatch.countDown(); 7577 } 7578 waitForCallback()7579 private void waitForCallback() throws Exception { 7580 mStatusLatch.await(TEST_ZONE_CONFIG_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 7581 } 7582 getZoneConfig()7583 CarAudioZoneConfigInfo getZoneConfig() { 7584 return mZoneConfig; 7585 } 7586 getSwitchStatus()7587 boolean getSwitchStatus() { 7588 return mIsSuccessful; 7589 } 7590 reset()7591 public void reset() { 7592 mZoneConfig = null; 7593 mIsSuccessful = false; 7594 mStatusLatch = new CountDownLatch(1); 7595 } 7596 } 7597 } 7598