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