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.TIRAMISU_1; 22 import static android.car.PlatformVersion.VERSION_CODES.UPSIDE_DOWN_CAKE_0; 23 import static android.car.media.CarAudioManager.AUDIO_FEATURE_AUDIO_MIRRORING; 24 import static android.car.media.CarAudioManager.AUDIO_FEATURE_DYNAMIC_ROUTING; 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.INVALID_AUDIO_ZONE; 31 import static android.car.media.CarAudioManager.INVALID_REQUEST_ID; 32 import static android.car.media.CarAudioManager.INVALID_VOLUME_GROUP_ID; 33 import static android.car.media.CarAudioManager.PRIMARY_AUDIO_ZONE; 34 import static android.car.test.mocks.AndroidMockitoHelper.mockCarGetPlatformVersion; 35 import static android.car.test.mocks.AndroidMockitoHelper.mockContextCheckCallingOrSelfPermission; 36 import static android.content.pm.PackageManager.PERMISSION_DENIED; 37 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 38 import static android.media.AudioAttributes.USAGE_ALARM; 39 import static android.media.AudioAttributes.USAGE_ANNOUNCEMENT; 40 import static android.media.AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY; 41 import static android.media.AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE; 42 import static android.media.AudioAttributes.USAGE_ASSISTANCE_SONIFICATION; 43 import static android.media.AudioAttributes.USAGE_ASSISTANT; 44 import static android.media.AudioAttributes.USAGE_CALL_ASSISTANT; 45 import static android.media.AudioAttributes.USAGE_EMERGENCY; 46 import static android.media.AudioAttributes.USAGE_GAME; 47 import static android.media.AudioAttributes.USAGE_MEDIA; 48 import static android.media.AudioAttributes.USAGE_NOTIFICATION; 49 import static android.media.AudioAttributes.USAGE_NOTIFICATION_EVENT; 50 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; 51 import static android.media.AudioAttributes.USAGE_SAFETY; 52 import static android.media.AudioAttributes.USAGE_UNKNOWN; 53 import static android.media.AudioAttributes.USAGE_VEHICLE_STATUS; 54 import static android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION; 55 import static android.media.AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING; 56 import static android.media.AudioDeviceInfo.TYPE_BUILTIN_MIC; 57 import static android.media.AudioDeviceInfo.TYPE_FM_TUNER; 58 import static android.media.AudioManager.AUDIOFOCUS_GAIN; 59 import static android.media.AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK; 60 import static android.media.AudioManager.AUDIOFOCUS_LOSS; 61 import static android.media.AudioManager.AUDIOFOCUS_LOSS_TRANSIENT; 62 import static android.media.AudioManager.AUDIOFOCUS_NONE; 63 import static android.media.AudioManager.AUDIOFOCUS_REQUEST_GRANTED; 64 import static android.media.AudioManager.EXTRA_VOLUME_STREAM_TYPE; 65 import static android.media.AudioManager.FLAG_FROM_KEY; 66 import static android.media.AudioManager.FLAG_PLAY_SOUND; 67 import static android.media.AudioManager.FLAG_SHOW_UI; 68 import static android.media.AudioManager.MASTER_MUTE_CHANGED_ACTION; 69 import static android.media.AudioManager.STREAM_MUSIC; 70 import static android.media.AudioManager.SUCCESS; 71 import static android.media.AudioManager.VOLUME_CHANGED_ACTION; 72 import static android.media.audio.common.AudioDeviceDescription.CONNECTION_BUS; 73 import static android.media.audio.common.AudioDeviceType.OUT_DEVICE; 74 import static android.media.audio.common.AudioGainMode.JOINT; 75 import static android.os.Build.VERSION.SDK_INT; 76 import static android.view.KeyEvent.ACTION_DOWN; 77 import static android.view.KeyEvent.ACTION_UP; 78 import static android.view.KeyEvent.KEYCODE_UNKNOWN; 79 import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN; 80 import static android.view.KeyEvent.KEYCODE_VOLUME_MUTE; 81 import static android.view.KeyEvent.KEYCODE_VOLUME_UP; 82 83 import static com.android.car.R.bool.audioPersistMasterMuteState; 84 import static com.android.car.R.bool.audioUseCarVolumeGroupEvent; 85 import static com.android.car.R.bool.audioUseCarVolumeGroupMuting; 86 import static com.android.car.R.bool.audioUseCoreRouting; 87 import static com.android.car.R.bool.audioUseCoreVolume; 88 import static com.android.car.R.bool.audioUseDynamicRouting; 89 import static com.android.car.R.bool.audioUseHalDuckingSignals; 90 import static com.android.car.R.integer.audioVolumeAdjustmentContextsVersion; 91 import static com.android.car.R.integer.audioVolumeKeyEventTimeoutMs; 92 import static com.android.car.audio.CarAudioService.CAR_DEFAULT_AUDIO_ATTRIBUTE; 93 import static com.android.car.audio.GainBuilder.DEFAULT_GAIN; 94 import static com.android.car.audio.GainBuilder.MAX_GAIN; 95 import static com.android.car.audio.GainBuilder.MIN_GAIN; 96 import static com.android.car.audio.GainBuilder.STEP_SIZE; 97 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 98 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 99 100 import static org.junit.Assert.assertThrows; 101 import static org.mockito.ArgumentMatchers.any; 102 import static org.mockito.ArgumentMatchers.anyBoolean; 103 import static org.mockito.ArgumentMatchers.anyInt; 104 import static org.mockito.ArgumentMatchers.anyString; 105 import static org.mockito.ArgumentMatchers.eq; 106 import static org.mockito.Mockito.atLeastOnce; 107 import static org.mockito.Mockito.mock; 108 import static org.mockito.Mockito.never; 109 import static org.mockito.Mockito.reset; 110 import static org.mockito.Mockito.times; 111 import static org.mockito.Mockito.when; 112 113 import android.annotation.NonNull; 114 import android.car.Car; 115 import android.car.CarOccupantZoneManager; 116 import android.car.ICarOccupantZoneCallback; 117 import android.car.VehicleAreaSeat; 118 import android.car.builtin.media.AudioManagerHelper; 119 import android.car.builtin.media.AudioManagerHelper.AudioPatchInfo; 120 import android.car.builtin.os.UserManagerHelper; 121 import android.car.media.CarAudioManager; 122 import android.car.media.CarAudioPatchHandle; 123 import android.car.media.CarAudioZoneConfigInfo; 124 import android.car.media.CarVolumeGroupEvent; 125 import android.car.media.CarVolumeGroupInfo; 126 import android.car.media.IAudioZonesMirrorStatusCallback; 127 import android.car.media.ICarVolumeEventCallback; 128 import android.car.media.IMediaAudioRequestStatusCallback; 129 import android.car.media.IPrimaryZoneMediaAudioRequestCallback; 130 import android.car.media.ISwitchAudioZoneConfigCallback; 131 import android.car.settings.CarSettings; 132 import android.car.test.mocks.AbstractExtendedMockitoTestCase; 133 import android.car.test.mocks.MockSettings; 134 import android.content.BroadcastReceiver; 135 import android.content.ContentResolver; 136 import android.content.Context; 137 import android.content.Intent; 138 import android.content.pm.PackageManager; 139 import android.content.res.Resources; 140 import android.hardware.automotive.audiocontrol.AudioGainConfigInfo; 141 import android.hardware.automotive.audiocontrol.IAudioControl; 142 import android.hardware.automotive.audiocontrol.Reasons; 143 import android.media.AudioAttributes; 144 import android.media.AudioDeviceAttributes; 145 import android.media.AudioDeviceInfo; 146 import android.media.AudioFocusInfo; 147 import android.media.AudioGain; 148 import android.media.AudioManager; 149 import android.media.AudioManager.AudioPlaybackCallback; 150 import android.media.AudioPlaybackConfiguration; 151 import android.media.IAudioService; 152 import android.media.audio.common.AudioDevice; 153 import android.media.audio.common.AudioDeviceAddress; 154 import android.media.audio.common.AudioDeviceDescription; 155 import android.media.audio.common.AudioPort; 156 import android.media.audio.common.AudioPortDeviceExt; 157 import android.media.audio.common.AudioPortExt; 158 import android.media.audiopolicy.AudioPolicy; 159 import android.net.Uri; 160 import android.os.Binder; 161 import android.os.Build; 162 import android.os.IBinder; 163 import android.os.RemoteException; 164 import android.os.ServiceManager; 165 import android.os.SystemProperties; 166 import android.os.UserHandle; 167 import android.provider.Settings; 168 import android.telephony.TelephonyManager; 169 import android.util.Log; 170 import android.view.KeyEvent; 171 172 import androidx.test.core.app.ApplicationProvider; 173 174 import com.android.car.CarInputService; 175 import com.android.car.CarLocalServices; 176 import com.android.car.CarOccupantZoneService; 177 import com.android.car.R; 178 import com.android.car.audio.hal.AudioControlFactory; 179 import com.android.car.audio.hal.AudioControlWrapper; 180 import com.android.car.audio.hal.AudioControlWrapper.AudioControlDeathRecipient; 181 import com.android.car.audio.hal.AudioControlWrapperAidl; 182 import com.android.car.audio.hal.HalAudioDeviceInfo; 183 import com.android.car.audio.hal.HalAudioGainCallback; 184 import com.android.car.audio.hal.HalAudioModuleChangeCallback; 185 import com.android.car.audio.hal.HalFocusListener; 186 import com.android.car.oem.CarOemAudioDuckingProxyService; 187 import com.android.car.oem.CarOemAudioFocusProxyService; 188 import com.android.car.oem.CarOemAudioVolumeProxyService; 189 import com.android.car.oem.CarOemProxyService; 190 import com.android.car.test.utils.TemporaryFile; 191 192 import org.junit.After; 193 import org.junit.Before; 194 import org.junit.Test; 195 import org.mockito.ArgumentCaptor; 196 import org.mockito.Captor; 197 import org.mockito.Mock; 198 199 import java.io.InputStream; 200 import java.util.ArrayList; 201 import java.util.Arrays; 202 import java.util.List; 203 import java.util.concurrent.CountDownLatch; 204 import java.util.concurrent.TimeUnit; 205 206 public final class CarAudioServiceUnitTest extends AbstractExtendedMockitoTestCase { 207 private static final String TAG = CarAudioServiceUnitTest.class.getSimpleName(); 208 private static final long TEST_CALLBACK_TIMEOUT_MS = 100; 209 private static final int VOLUME_KEY_EVENT_TIMEOUT_MS = 3000; 210 private static final int AUDIO_CONTEXT_PRIORITY_LIST_VERSION_ONE = 1; 211 private static final int AUDIO_CONTEXT_PRIORITY_LIST_VERSION_TWO = 2; 212 private static final String MEDIA_TEST_DEVICE = "media_bus_device"; 213 private static final String OEM_TEST_DEVICE = "oem_bus_device"; 214 private static final String MIRROR_TEST_DEVICE = "mirror_bus_device"; 215 private static final String NAVIGATION_TEST_DEVICE = "navigation_bus_device"; 216 private static final String CALL_TEST_DEVICE = "call_bus_device"; 217 private static final String NOTIFICATION_TEST_DEVICE = "notification_bus_device"; 218 private static final String VOICE_TEST_DEVICE = "voice_bus_device"; 219 private static final String RING_TEST_DEVICE = "ring_bus_device"; 220 private static final String ALARM_TEST_DEVICE = "alarm_bus_device"; 221 private static final String SYSTEM_BUS_DEVICE = "system_bus_device"; 222 private static final String SECONDARY_TEST_DEVICE_CONFIG_0 = "secondary_zone_bus_100"; 223 private static final String SECONDARY_TEST_DEVICE_CONFIG_1_0 = "secondary_zone_bus_200"; 224 private static final String SECONDARY_TEST_DEVICE_CONFIG_1_1 = "secondary_zone_bus_201"; 225 private static final String TERTIARY_TEST_DEVICE_1 = "tertiary_zone_bus_100"; 226 private static final String TERTIARY_TEST_DEVICE_2 = "tertiary_zone_bus_200"; 227 private static final String QUATERNARY_TEST_DEVICE_1 = "quaternary_zone_bus_1"; 228 private static final String TEST_REAR_ROW_3_DEVICE = "rear_row_three_zone_bus_1"; 229 private static final String PRIMARY_ZONE_MICROPHONE_ADDRESS = "Built-In Mic"; 230 private static final String PRIMARY_ZONE_FM_TUNER_ADDRESS = "FM Tuner"; 231 private static final String SECONDARY_ZONE_CONFIG_NAME_1 = "secondary zone config 1"; 232 private static final String SECONDARY_ZONE_CONFIG_NAME_2 = "secondary zone config 2"; 233 private static final String MIRROR_OFF_SIGNAL = "mirroring=off"; 234 // From the car audio configuration file in /res/raw/car_audio_configuration.xml 235 private static final int TEST_REAR_LEFT_ZONE_ID = 1; 236 private static final int TEST_REAR_RIGHT_ZONE_ID = 2; 237 private static final int TEST_FRONT_ZONE_ID = 3; 238 private static final int TEST_REAR_ROW_3_ZONE_ID = 4; 239 public static final int[] TEST_MIRROR_AUDIO_ZONES = new int[]{TEST_REAR_LEFT_ZONE_ID, 240 TEST_REAR_RIGHT_ZONE_ID}; 241 private static final int OUT_OF_RANGE_ZONE = TEST_REAR_ROW_3_ZONE_ID + 1; 242 private static final int PRIMARY_ZONE_VOLUME_GROUP_COUNT = 4; 243 private static final int SECONDARY_ZONE_VOLUME_GROUP_COUNT = 1; 244 private static final int SECONDARY_ZONE_VOLUME_GROUP_ID = SECONDARY_ZONE_VOLUME_GROUP_COUNT - 1; 245 private static final int TEST_PRIMARY_ZONE_GROUP_0 = 0; 246 private static final int TEST_PRIMARY_ZONE_GROUP_1 = 1; 247 private static final int TEST_PRIMARY_ZONE_GROUP_2 = 2; 248 private static final int TEST_SECONDARY_ZONE_GROUP_0 = 0; 249 private static final int TEST_SECONDARY_ZONE_GROUP_1 = 1; 250 private static final int TEST_FLAGS = 0; 251 private static final float TEST_VALUE = -.75f; 252 private static final float INVALID_TEST_VALUE = -1.5f; 253 private static final int TEST_DISPLAY_TYPE = 2; 254 private static final int TEST_SEAT = 2; 255 private static final int PRIMARY_OCCUPANT_ZONE = 0; 256 private static final int INVALID_STATUS = 0; 257 258 private static final int TEST_DRIVER_OCCUPANT_ZONE_ID = 1; 259 private static final int TEST_REAR_LEFT_OCCUPANT_ZONE_ID = 2; 260 private static final int TEST_REAR_RIGHT_OCCUPANT_ZONE_ID = 3; 261 private static final int TEST_FRONT_OCCUPANT_ZONE_ID = 4; 262 private static final int TEST_REAR_ROW_3_OCCUPANT_ZONE_ID = 5; 263 private static final int TEST_UNASSIGNED_OCCUPANT_ZONE_ID = 6; 264 265 private static final int TEST_MEDIA_PORT_ID = 0; 266 private static final int TEST_NAV_PORT_ID = 1; 267 private static final String TEST_MEDIA_PORT_NAME = "Media bus"; 268 private static final String TEST_NAV_PORT_NAME = "Nav bus"; 269 private static final int TEST_GAIN_MIN_VALUE = -3000; 270 private static final int TEST_GAIN_MAX_VALUE = -1000; 271 private static final int TEST_GAIN_DEFAULT_VALUE = -2000; 272 private static final int TEST_GAIN_STEP_VALUE = 2; 273 274 private static final CarOccupantZoneManager.OccupantZoneInfo TEST_DRIVER_OCCUPANT = 275 getOccupantInfo(TEST_DRIVER_OCCUPANT_ZONE_ID, 276 CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER, 277 VehicleAreaSeat.SEAT_ROW_1_LEFT); 278 private static final CarOccupantZoneManager.OccupantZoneInfo 279 TEST_REAR_RIGHT_PASSENGER_OCCUPANT = 280 getOccupantInfo(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID, 281 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 282 VehicleAreaSeat.SEAT_ROW_2_RIGHT); 283 private static final CarOccupantZoneManager.OccupantZoneInfo 284 TEST_FRONT_PASSENGER_OCCUPANT = 285 getOccupantInfo(TEST_FRONT_OCCUPANT_ZONE_ID, 286 CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER, 287 VehicleAreaSeat.SEAT_ROW_1_RIGHT); 288 private static final CarOccupantZoneManager.OccupantZoneInfo 289 TEST_REAR_LEFT_PASSENGER_OCCUPANT = 290 getOccupantInfo(TEST_REAR_LEFT_OCCUPANT_ZONE_ID, 291 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 292 VehicleAreaSeat.SEAT_ROW_2_LEFT); 293 294 private static final CarOccupantZoneManager.OccupantZoneInfo 295 TEST_REAR_ROW_3_PASSENGER_OCCUPANT = 296 getOccupantInfo(TEST_REAR_ROW_3_OCCUPANT_ZONE_ID, 297 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 298 VehicleAreaSeat.SEAT_ROW_3_LEFT); 299 300 private static final String PROPERTY_RO_ENABLE_AUDIO_PATCH = 301 "ro.android.car.audio.enableaudiopatch"; 302 303 private static final int MEDIA_APP_UID = 1086753; 304 private static final int TEST_REAR_RIGHT_UID = 1286753; 305 private static final String MEDIA_CLIENT_ID = "media-client-id"; 306 private static final String MEDIA_PACKAGE_NAME = "com.android.car.audio"; 307 private static final int MEDIA_EMPTY_FLAG = 0; 308 private static final String REGISTRATION_ID = "meh"; 309 private static final int MEDIA_VOLUME_GROUP_ID = 0; 310 private static final int NAVIGATION_VOLUME_GROUP_ID = 1; 311 private static final int INVALID_USAGE = -1; 312 private static final int INVALID_AUDIO_FEATURE = -1; 313 private static final int TEST_DRIVER_USER_ID = 10; 314 private static final int TEST_REAR_LEFT_USER_ID = 11; 315 private static final int TEST_REAR_RIGHT_USER_ID = 12; 316 private static final int TEST_FRONT_PASSENGER_USER_ID = 13; 317 private static final int TEST_REAR_ROW_3_PASSENGER_USER_ID = 14; 318 private static final int TEST_GAIN_INDEX = 4; 319 320 // TODO(b/273800524): create a utility test class for audio attributes. 321 private static final AudioAttributes ATTRIBUTES_UNKNOWN = 322 CarAudioContext.getAudioAttributeFromUsage(USAGE_UNKNOWN); 323 private static final AudioAttributes ATTRIBUTES_GAME = 324 CarAudioContext.getAudioAttributeFromUsage(USAGE_GAME); 325 private static final AudioAttributes ATTRIBUTES_MEDIA = 326 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA); 327 private static final AudioAttributes ATTRIBUTES_NOTIFICATION = 328 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION); 329 private static final AudioAttributes ATTRIBUTES_NOTIFICATION_EVENT = 330 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION_EVENT); 331 private static final AudioAttributes ATTRIBUTES_ANNOUNCEMENT = 332 CarAudioContext.getAudioAttributeFromUsage(USAGE_ANNOUNCEMENT); 333 private static final AudioAttributes ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE = 334 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE); 335 private static final AudioAttributes ATTRIBUTES_ASSISTANCE_ACCESSIBILITY = 336 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANCE_ACCESSIBILITY); 337 private static final AudioAttributes ATTRIBUTES_ASSISTANT = 338 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANT); 339 private static final AudioAttributes ATTRIBUTES_NOTIFICATION_RINGTONE = 340 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION_RINGTONE); 341 private static final AudioAttributes ATTRIBUTES_VOICE_COMMUNICATION = 342 CarAudioContext.getAudioAttributeFromUsage(USAGE_VOICE_COMMUNICATION); 343 private static final AudioAttributes ATTRIBUTES_CALL_ASSISTANT = 344 CarAudioContext.getAudioAttributeFromUsage(USAGE_CALL_ASSISTANT); 345 private static final AudioAttributes ATTRIBUTES_VOICE_COMMUNICATION_SIGNALLING = 346 CarAudioContext.getAudioAttributeFromUsage(USAGE_VOICE_COMMUNICATION_SIGNALLING); 347 private static final AudioAttributes ATTRIBUTES_ALARM = 348 CarAudioContext.getAudioAttributeFromUsage(USAGE_ALARM); 349 private static final AudioAttributes ATTRIBUTES_ASSISTANCE_SONIFICATION = 350 CarAudioContext.getAudioAttributeFromUsage(USAGE_ASSISTANCE_SONIFICATION); 351 private static final AudioAttributes ATTRIBUTES_EMERGENCY = 352 CarAudioContext.getAudioAttributeFromUsage(USAGE_EMERGENCY); 353 private static final AudioAttributes ATTRIBUTES_SAFETY = 354 CarAudioContext.getAudioAttributeFromUsage(USAGE_SAFETY); 355 private static final AudioAttributes ATTRIBUTES_VEHICLE_STATUS = 356 CarAudioContext.getAudioAttributeFromUsage(USAGE_VEHICLE_STATUS); 357 358 private static final List<AudioAttributes> TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_0 = List.of( 359 ATTRIBUTES_UNKNOWN, ATTRIBUTES_GAME, ATTRIBUTES_MEDIA, ATTRIBUTES_NOTIFICATION, 360 ATTRIBUTES_NOTIFICATION_EVENT, ATTRIBUTES_ANNOUNCEMENT); 361 362 private static final List<AudioAttributes> TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_1 = List.of( 363 ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE, ATTRIBUTES_ASSISTANCE_ACCESSIBILITY, 364 ATTRIBUTES_ASSISTANT); 365 366 private static final List<AudioAttributes> TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_DEFAULT = 367 List.of(ATTRIBUTES_UNKNOWN, ATTRIBUTES_GAME, ATTRIBUTES_MEDIA, 368 ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE, ATTRIBUTES_ASSISTANCE_ACCESSIBILITY, 369 ATTRIBUTES_ASSISTANT, ATTRIBUTES_NOTIFICATION_RINGTONE, 370 ATTRIBUTES_VOICE_COMMUNICATION, ATTRIBUTES_CALL_ASSISTANT, 371 ATTRIBUTES_VOICE_COMMUNICATION_SIGNALLING, ATTRIBUTES_ALARM, 372 ATTRIBUTES_NOTIFICATION, ATTRIBUTES_NOTIFICATION_EVENT, 373 ATTRIBUTES_ASSISTANCE_SONIFICATION, ATTRIBUTES_EMERGENCY, ATTRIBUTES_SAFETY, 374 ATTRIBUTES_VEHICLE_STATUS, ATTRIBUTES_ANNOUNCEMENT); 375 376 private static final List<AudioAttributes> TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_0 = List.of( 377 ATTRIBUTES_UNKNOWN, ATTRIBUTES_GAME, ATTRIBUTES_MEDIA, 378 ATTRIBUTES_ASSISTANCE_NAVIGATION_GUIDANCE, ATTRIBUTES_ASSISTANCE_ACCESSIBILITY, 379 ATTRIBUTES_ASSISTANT, ATTRIBUTES_NOTIFICATION, ATTRIBUTES_NOTIFICATION_EVENT, 380 ATTRIBUTES_ANNOUNCEMENT); 381 382 private static final List<AudioAttributes> TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_1 = List.of( 383 ATTRIBUTES_NOTIFICATION_RINGTONE, ATTRIBUTES_VOICE_COMMUNICATION, 384 ATTRIBUTES_CALL_ASSISTANT, ATTRIBUTES_VOICE_COMMUNICATION_SIGNALLING, ATTRIBUTES_ALARM, 385 ATTRIBUTES_ASSISTANCE_SONIFICATION, ATTRIBUTES_EMERGENCY, ATTRIBUTES_SAFETY, 386 ATTRIBUTES_VEHICLE_STATUS); 387 388 389 private static final CarVolumeGroupInfo TEST_PRIMARY_ZONE_VOLUME_INFO_0 = 390 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_PRIMARY_ZONE_GROUP_0, 391 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0).setMuted(true) 392 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 393 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 394 .setAudioAttributes(TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_0).build(); 395 396 private static final CarVolumeGroupInfo TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0 = 397 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_PRIMARY_ZONE_GROUP_0, 398 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0).setMuted(false) 399 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 400 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE) 401 .setAudioAttributes(TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_0).build(); 402 403 private static final CarVolumeGroupInfo TEST_PRIMARY_ZONE_VOLUME_INFO_1 = 404 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_PRIMARY_ZONE_GROUP_1, 405 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1).setMuted(true) 406 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 407 .setAudioAttributes(TEST_PRIMARY_ZONE_AUDIO_ATTRIBUTES_1) 408 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE).build(); 409 410 private static final CarVolumeGroupInfo TEST_SECONDARY_ZONE_CONFIG_0_VOLUME_INFO = 411 new CarVolumeGroupInfo.Builder("config 0 group " + TEST_SECONDARY_ZONE_GROUP_0, 412 TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_0) 413 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 414 .setAudioAttributes(TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_DEFAULT) 415 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE).build(); 416 417 private static final CarVolumeGroupInfo TEST_SECONDARY_ZONE_CONFIG_1_VOLUME_INFO_0 = 418 new CarVolumeGroupInfo.Builder("config 1 group " + TEST_SECONDARY_ZONE_GROUP_0, 419 TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_0) 420 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 421 .setAudioAttributes(TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_0) 422 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE).build(); 423 424 private static final CarVolumeGroupInfo TEST_SECONDARY_ZONE_CONFIG_1_VOLUME_INFO_1 = 425 new CarVolumeGroupInfo.Builder("config 1 group " + TEST_SECONDARY_ZONE_GROUP_1, 426 TEST_REAR_LEFT_ZONE_ID, TEST_SECONDARY_ZONE_GROUP_1) 427 .setMinVolumeGainIndex(0).setMaxVolumeGainIndex(MAX_GAIN / STEP_SIZE) 428 .setAudioAttributes(TEST_SECONDARY_ZONE_AUDIO_ATTRIBUTES_1) 429 .setVolumeGainIndex(DEFAULT_GAIN / STEP_SIZE).build(); 430 431 private static final AudioDeviceInfo MICROPHONE_TEST_DEVICE = 432 new AudioDeviceInfoBuilder().setAddressName(PRIMARY_ZONE_MICROPHONE_ADDRESS) 433 .setType(TYPE_BUILTIN_MIC) 434 .setIsSource(true) 435 .build(); 436 private static final AudioDeviceInfo FM_TUNER_TEST_DEVICE = 437 new AudioDeviceInfoBuilder().setAddressName(PRIMARY_ZONE_FM_TUNER_ADDRESS) 438 .setType(TYPE_FM_TUNER) 439 .setIsSource(true) 440 .build(); 441 442 private static final AudioFocusInfo TEST_AUDIO_FOCUS_INFO = 443 new AudioFocusInfo(CarAudioContext 444 .getAudioAttributeFromUsage(USAGE_VOICE_COMMUNICATION), MEDIA_APP_UID, 445 MEDIA_CLIENT_ID, "com.android.car.audio", 446 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, AUDIOFOCUS_NONE, /* loss= */ 0, 447 Build.VERSION.SDK_INT); 448 449 private static final AudioFocusInfo TEST_REAR_RIGHT_AUDIO_FOCUS_INFO = 450 new AudioFocusInfo(CarAudioContext 451 .getAudioAttributeFromUsage(USAGE_MEDIA), TEST_REAR_RIGHT_UID, 452 MEDIA_CLIENT_ID, "com.android.car.audio", 453 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, AUDIOFOCUS_NONE, /* loss= */ 0, 454 Build.VERSION.SDK_INT); 455 456 private static final CarVolumeGroupEvent TEST_CAR_VOLUME_GROUP_EVENT = 457 new CarVolumeGroupEvent.Builder(List.of(TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0), 458 CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED, 459 List.of(CarVolumeGroupEvent.EXTRA_INFO_VOLUME_INDEX_CHANGED_BY_UI)).build(); 460 461 private static final CarVolumeGroupEvent TEST_CAR_MUTE_GROUP_EVENT = 462 new CarVolumeGroupEvent.Builder(List.of(TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0), 463 CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED, 464 List.of(CarVolumeGroupEvent.EXTRA_INFO_VOLUME_INDEX_CHANGED_BY_UI)).build(); 465 466 private static final CarVolumeGroupEvent TEST_CAR_ZONE_RECONFIGURATION_EVENT = 467 new CarVolumeGroupEvent.Builder(List.of(TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0), 468 CarVolumeGroupEvent.EVENT_TYPE_ZONE_CONFIGURATION_CHANGED, 469 List.of(CarVolumeGroupEvent.EXTRA_INFO_VOLUME_INDEX_CHANGED_BY_UI)).build(); 470 471 private CarAudioService mCarAudioService; 472 @Mock 473 private Context mMockContext; 474 @Mock 475 private TelephonyManager mMockTelephonyManager; 476 @Mock 477 private AudioManager mAudioManager; 478 @Mock 479 private Resources mMockResources; 480 @Mock 481 private ContentResolver mMockContentResolver; 482 @Mock 483 IBinder mBinder; 484 @Mock 485 IBinder mVolumeCallbackBinder; 486 @Mock 487 IAudioControl mAudioControl; 488 @Mock 489 private PackageManager mMockPackageManager; 490 @Mock 491 private CarOccupantZoneService mMockOccupantZoneService; 492 @Mock 493 private CarOemProxyService mMockCarOemProxyService; 494 @Mock 495 private IAudioService mMockAudioService; 496 @Mock 497 private Uri mNavSettingUri; 498 @Mock 499 private AudioControlWrapperAidl mAudioControlWrapperAidl; 500 @Mock 501 private CarVolumeCallbackHandler mCarVolumeCallbackHandler; 502 @Mock 503 private CarInputService mMockCarInputService; 504 505 // Not used directly, but sets proper mockStatic() expectations on Settings 506 @SuppressWarnings("UnusedVariable") 507 private MockSettings mMockSettings; 508 509 private boolean mPersistMasterMute = true; 510 private boolean mUseDynamicRouting = true; 511 private boolean mUseHalAudioDucking = true; 512 private boolean mUseCarVolumeGroupMuting = true; 513 private boolean mUseCarVolumeGroupEvents = true; 514 515 private TemporaryFile mTemporaryAudioConfigurationUsingCoreAudioFile; 516 private TemporaryFile mTemporaryAudioConfigurationFile; 517 private TemporaryFile mTemporaryAudioConfigurationWithoutZoneMappingFile; 518 private TemporaryFile mTemporaryAudioConfigurationWithoutMirroringFile; 519 private TemporaryFile mTemporaryAudioConfigurationWithOEMContexts; 520 private Context mContext; 521 private AudioDeviceInfo mMicrophoneInputDevice; 522 private AudioDeviceInfo mFmTunerInputDevice; 523 private AudioDeviceInfo mMediaOutputDevice; 524 525 @Captor 526 private ArgumentCaptor<BroadcastReceiver> mVolumeReceiverCaptor; 527 CarAudioServiceUnitTest()528 public CarAudioServiceUnitTest() { 529 super(CarAudioService.TAG); 530 } 531 532 @Override onSessionBuilder(CustomMockitoSessionBuilder session)533 protected void onSessionBuilder(CustomMockitoSessionBuilder session) { 534 mMockSettings = new MockSettings(session); 535 session 536 .spyStatic(AudioManager.class) 537 .spyStatic(AudioManagerHelper.class) 538 .spyStatic(AudioControlWrapperAidl.class) 539 .spyStatic(CoreAudioHelper.class) 540 .spyStatic(AudioControlFactory.class) 541 .spyStatic(SystemProperties.class) 542 .spyStatic(ServiceManager.class) 543 .spyStatic(Car.class); 544 } 545 546 @Before setUp()547 public void setUp() throws Exception { 548 mContext = ApplicationProvider.getApplicationContext(); 549 550 try (InputStream configurationStream = mContext.getResources().openRawResource( 551 R.raw.car_audio_configuration)) { 552 mTemporaryAudioConfigurationFile = new TemporaryFile("xml"); 553 mTemporaryAudioConfigurationFile.write(new String(configurationStream.readAllBytes())); 554 Log.i(TAG, "Temporary Car Audio Configuration File Location: " 555 + mTemporaryAudioConfigurationFile.getPath()); 556 } 557 558 try (InputStream configurationStream = mContext.getResources().openRawResource( 559 R.raw.car_audio_configuration_using_oem_defined_context)) { 560 mTemporaryAudioConfigurationWithOEMContexts = new TemporaryFile("xml"); 561 mTemporaryAudioConfigurationWithOEMContexts.write( 562 new String(configurationStream.readAllBytes())); 563 Log.i(TAG, "Temporary Car Audio Configuration with OEM Context File Location: " 564 + mTemporaryAudioConfigurationWithOEMContexts.getPath()); 565 } 566 567 568 569 try (InputStream configurationStream = mContext.getResources().openRawResource( 570 R.raw.car_audio_configuration_without_zone_mapping)) { 571 mTemporaryAudioConfigurationWithoutZoneMappingFile = new TemporaryFile("xml"); 572 mTemporaryAudioConfigurationWithoutZoneMappingFile 573 .write(new String(configurationStream.readAllBytes())); 574 Log.i(TAG, "Temporary Car Audio Configuration without Zone mapping File Location: " 575 + mTemporaryAudioConfigurationWithoutZoneMappingFile.getPath()); 576 } 577 578 try (InputStream configurationStream = mContext.getResources().openRawResource( 579 R.raw.car_audio_configuration_using_core_audio_routing_and_volume)) { 580 mTemporaryAudioConfigurationUsingCoreAudioFile = new TemporaryFile("xml"); 581 mTemporaryAudioConfigurationUsingCoreAudioFile 582 .write(new String(configurationStream.readAllBytes())); 583 Log.i(TAG, "Temporary Car Audio Configuration using Core Audio File Location: " 584 + mTemporaryAudioConfigurationUsingCoreAudioFile.getPath()); 585 } 586 587 try (InputStream configurationStream = mContext.getResources().openRawResource( 588 R.raw.car_audio_configuration_without_mirroring)) { 589 mTemporaryAudioConfigurationWithoutMirroringFile = new TemporaryFile("xml"); 590 mTemporaryAudioConfigurationWithoutMirroringFile 591 .write(new String(configurationStream.readAllBytes())); 592 Log.i(TAG, "Temporary Car Audio Configuration Without Mirroring File Location: " 593 + mTemporaryAudioConfigurationWithoutMirroringFile.getPath()); 594 } 595 596 mockCarGetPlatformVersion(UPSIDE_DOWN_CAKE_0); 597 598 mockCoreAudioRoutingAndVolume(); 599 mockGrantCarControlAudioSettingsPermission(); 600 601 setupAudioControlHAL(); 602 setupService(); 603 604 when(Settings.Secure.getUriFor( 605 CarSettings.Secure.KEY_AUDIO_FOCUS_NAVIGATION_REJECTED_DURING_CALL)) 606 .thenReturn(mNavSettingUri); 607 } 608 609 @After tearDown()610 public void tearDown() throws Exception { 611 mTemporaryAudioConfigurationFile.close(); 612 mTemporaryAudioConfigurationWithoutZoneMappingFile.close(); 613 CarLocalServices.removeServiceForTest(CarOemProxyService.class); 614 CarLocalServices.removeServiceForTest(CarOccupantZoneService.class); 615 } 616 setupAudioControlHAL()617 private void setupAudioControlHAL() { 618 when(mBinder.queryLocalInterface(anyString())).thenReturn(mAudioControl); 619 doReturn(mBinder).when(AudioControlWrapperAidl::getService); 620 when(mAudioControlWrapperAidl.supportsFeature( 621 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_DUCKING)).thenReturn(true); 622 when(mAudioControlWrapperAidl.supportsFeature( 623 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_FOCUS)).thenReturn(true); 624 when(mAudioControlWrapperAidl.supportsFeature( 625 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_GAIN_CALLBACK)).thenReturn(true); 626 when(mAudioControlWrapperAidl.supportsFeature( 627 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_GROUP_MUTING)).thenReturn(true); 628 when(mAudioControlWrapperAidl.supportsFeature( 629 AudioControlWrapper.AUDIOCONTROL_FEATURE_AUDIO_MODULE_CALLBACK)).thenReturn(true); 630 doReturn(mAudioControlWrapperAidl) 631 .when(() -> AudioControlFactory.newAudioControl()); 632 } 633 setupService()634 private void setupService() throws Exception { 635 when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE)) 636 .thenReturn(mMockTelephonyManager); 637 when(mMockContext.getSystemService(Context.AUDIO_SERVICE)) 638 .thenReturn(mAudioManager); 639 when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager); 640 doReturn(true) 641 .when(() -> AudioManagerHelper 642 .setAudioDeviceGain(any(), any(), anyInt(), anyBoolean())); 643 doReturn(true) 644 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, false)); 645 646 when(mMockOccupantZoneService.getUserForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 647 .thenReturn(TEST_DRIVER_USER_ID); 648 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 649 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 650 .thenReturn(PRIMARY_AUDIO_ZONE); 651 when(mMockOccupantZoneService.getOccupantZoneForUser(UserHandle.of(TEST_DRIVER_USER_ID))) 652 .thenReturn(TEST_DRIVER_OCCUPANT); 653 654 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 655 .thenReturn(TEST_REAR_LEFT_USER_ID); 656 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 657 .thenReturn(TEST_REAR_RIGHT_USER_ID); 658 when(mMockOccupantZoneService.getUserForOccupant(TEST_FRONT_OCCUPANT_ZONE_ID)) 659 .thenReturn(TEST_FRONT_PASSENGER_USER_ID); 660 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_ROW_3_OCCUPANT_ZONE_ID)) 661 .thenReturn(TEST_REAR_ROW_3_PASSENGER_USER_ID); 662 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 663 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 664 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 665 .thenReturn(TEST_REAR_RIGHT_ZONE_ID); 666 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_FRONT_OCCUPANT_ZONE_ID)) 667 .thenReturn(TEST_FRONT_PASSENGER_USER_ID); 668 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_REAR_ROW_3_ZONE_ID)) 669 .thenReturn(TEST_REAR_ROW_3_PASSENGER_USER_ID); 670 when(mMockOccupantZoneService.getOccupantZoneForUser( 671 UserHandle.of(TEST_REAR_RIGHT_USER_ID))).thenReturn( 672 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 673 when(mMockOccupantZoneService.getOccupantZoneForUser( 674 UserHandle.of(TEST_FRONT_PASSENGER_USER_ID))).thenReturn( 675 TEST_FRONT_PASSENGER_OCCUPANT); 676 when(mMockOccupantZoneService.getOccupantZoneForUser( 677 UserHandle.of(TEST_REAR_LEFT_USER_ID))).thenReturn( 678 TEST_REAR_LEFT_PASSENGER_OCCUPANT); 679 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_REAR_ROW_3_ZONE_ID)) 680 .thenReturn(TEST_REAR_ROW_3_PASSENGER_OCCUPANT); 681 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_REAR_RIGHT_ZONE_ID)) 682 .thenReturn(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 683 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_FRONT_ZONE_ID)) 684 .thenReturn(TEST_FRONT_PASSENGER_OCCUPANT); 685 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_REAR_LEFT_ZONE_ID)) 686 .thenReturn(TEST_REAR_LEFT_PASSENGER_OCCUPANT); 687 when(mMockOccupantZoneService.getOccupantForAudioZoneId(TEST_REAR_ROW_3_ZONE_ID)) 688 .thenReturn(TEST_REAR_ROW_3_PASSENGER_OCCUPANT); 689 690 CarLocalServices.removeServiceForTest(CarOccupantZoneService.class); 691 CarLocalServices.addService(CarOccupantZoneService.class, mMockOccupantZoneService); 692 CarLocalServices.removeServiceForTest(CarInputService.class); 693 CarLocalServices.addService(CarInputService.class, mMockCarInputService); 694 695 CarLocalServices.removeServiceForTest(CarOemProxyService.class); 696 CarLocalServices.addService(CarOemProxyService.class, mMockCarOemProxyService); 697 698 setupAudioManager(); 699 700 setupResources(); 701 702 mCarAudioService = 703 new CarAudioService(mMockContext, 704 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 705 mCarVolumeCallbackHandler); 706 } 707 setupAudioManager()708 private void setupAudioManager() throws Exception { 709 AudioDeviceInfo[] outputDevices = generateOutputDeviceInfos(); 710 AudioDeviceInfo[] inputDevices = generateInputDeviceInfos(); 711 when(mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)) 712 .thenReturn(outputDevices); 713 when(mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) 714 .thenReturn(inputDevices); 715 when(mMockContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); 716 717 when(mAudioManager.registerAudioPolicy(any())).thenAnswer(invocation -> { 718 AudioPolicy policy = (AudioPolicy) invocation.getArguments()[0]; 719 policy.setRegistration(REGISTRATION_ID); 720 return SUCCESS; 721 }); 722 723 IBinder mockBinder = mock(IBinder.class); 724 when(mockBinder.queryLocalInterface(any())).thenReturn(mMockAudioService); 725 doReturn(mockBinder).when(() -> ServiceManager.getService(Context.AUDIO_SERVICE)); 726 } 727 setupResources()728 private void setupResources() { 729 when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); 730 when(mMockContext.createContextAsUser(any(), anyInt())).thenReturn(mMockContext); 731 when(mMockContext.getResources()).thenReturn(mMockResources); 732 when(mMockResources.getBoolean(audioUseDynamicRouting)).thenReturn(mUseDynamicRouting); 733 when(mMockResources.getInteger(audioVolumeKeyEventTimeoutMs)) 734 .thenReturn(VOLUME_KEY_EVENT_TIMEOUT_MS); 735 when(mMockResources.getBoolean(audioUseHalDuckingSignals)).thenReturn(mUseHalAudioDucking); 736 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)) 737 .thenReturn(mUseCarVolumeGroupMuting); 738 when(mMockResources.getBoolean(audioUseCarVolumeGroupEvent)) 739 .thenReturn(mUseCarVolumeGroupEvents); 740 when(mMockResources.getInteger(audioVolumeAdjustmentContextsVersion)) 741 .thenReturn(AUDIO_CONTEXT_PRIORITY_LIST_VERSION_TWO); 742 when(mMockResources.getBoolean(audioPersistMasterMuteState)).thenReturn(mPersistMasterMute); 743 } 744 745 @Test constructor_withNullContext_fails()746 public void constructor_withNullContext_fails() { 747 NullPointerException thrown = 748 assertThrows(NullPointerException.class, () -> new CarAudioService(null)); 749 750 expectWithMessage("Car Audio Service Construction") 751 .that(thrown).hasMessageThat().contains("Context"); 752 } 753 754 @Test constructor_withNullContextAndNullPath_fails()755 public void constructor_withNullContextAndNullPath_fails() { 756 NullPointerException thrown = 757 assertThrows(NullPointerException.class, 758 () -> new CarAudioService(/* context= */null, 759 /* audioConfigurationPath= */ null, 760 /* carVolumeCallbackHandler= */ null)); 761 762 expectWithMessage("Car Audio Service Construction") 763 .that(thrown).hasMessageThat().contains("Context"); 764 } 765 766 @Test constructor_withInvalidVolumeConfiguration_fails()767 public void constructor_withInvalidVolumeConfiguration_fails() { 768 when(mMockResources.getInteger(audioVolumeAdjustmentContextsVersion)) 769 .thenReturn(AUDIO_CONTEXT_PRIORITY_LIST_VERSION_ONE); 770 771 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 772 () -> new CarAudioService(mMockContext)); 773 774 expectWithMessage("Car Audio Service Construction") 775 .that(thrown).hasMessageThat() 776 .contains("requires audioVolumeAdjustmentContextsVersion 2"); 777 } 778 779 @Test getAudioZoneIds_withBaseConfiguration_returnAllTheZones()780 public void getAudioZoneIds_withBaseConfiguration_returnAllTheZones() { 781 mCarAudioService.init(); 782 783 expectWithMessage("Car Audio Service Zones") 784 .that(mCarAudioService.getAudioZoneIds()).asList() 785 .containsExactly(PRIMARY_AUDIO_ZONE, TEST_REAR_LEFT_ZONE_ID, 786 TEST_REAR_RIGHT_ZONE_ID, TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID); 787 } 788 789 @Test getVolumeGroupCount_onPrimaryZone_returnsAllGroups()790 public void getVolumeGroupCount_onPrimaryZone_returnsAllGroups() { 791 mCarAudioService.init(); 792 793 expectWithMessage("Primary zone car volume group count") 794 .that(mCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 795 .isEqualTo(PRIMARY_ZONE_VOLUME_GROUP_COUNT); 796 } 797 798 @Test getVolumeGroupCount_onPrimaryZone_withNonDynamicRouting_returnsAllGroups()799 public void getVolumeGroupCount_onPrimaryZone_withNonDynamicRouting_returnsAllGroups() { 800 when(mMockResources.getBoolean(audioUseDynamicRouting)) 801 .thenReturn(/* useDynamicRouting= */ false); 802 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 803 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 804 mCarVolumeCallbackHandler); 805 nonDynamicAudioService.init(); 806 807 expectWithMessage("Non dynamic routing primary zone car volume group count") 808 .that(nonDynamicAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 809 .isEqualTo(CarAudioDynamicRouting.STREAM_TYPES.length); 810 } 811 812 @Test getVolumeGroupIdForUsage_forMusicUsage()813 public void getVolumeGroupIdForUsage_forMusicUsage() { 814 mCarAudioService.init(); 815 816 expectWithMessage("Primary zone's media car volume group id") 817 .that(mCarAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, USAGE_MEDIA)) 818 .isEqualTo(MEDIA_VOLUME_GROUP_ID); 819 } 820 821 @Test getVolumeGroupIdForUsage_withNonDynamicRouting_forMusicUsage()822 public void getVolumeGroupIdForUsage_withNonDynamicRouting_forMusicUsage() { 823 when(mMockResources.getBoolean(audioUseDynamicRouting)) 824 .thenReturn(/* useDynamicRouting= */ false); 825 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 826 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 827 mCarVolumeCallbackHandler); 828 nonDynamicAudioService.init(); 829 830 expectWithMessage("Non dynamic routing primary zone's media car volume group id") 831 .that(nonDynamicAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 832 USAGE_MEDIA)).isEqualTo(MEDIA_VOLUME_GROUP_ID); 833 } 834 835 @Test getVolumeGroupIdForUsage_forNavigationUsage()836 public void getVolumeGroupIdForUsage_forNavigationUsage() { 837 mCarAudioService.init(); 838 839 expectWithMessage("Primary zone's navigation car volume group id") 840 .that(mCarAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 841 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)) 842 .isEqualTo(NAVIGATION_VOLUME_GROUP_ID); 843 } 844 845 @Test getVolumeGroupIdForUsage_withNonDynamicRouting_forNavigationUsage()846 public void getVolumeGroupIdForUsage_withNonDynamicRouting_forNavigationUsage() { 847 when(mMockResources.getBoolean(audioUseDynamicRouting)) 848 .thenReturn(/* useDynamicRouting= */ false); 849 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 850 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 851 mCarVolumeCallbackHandler); 852 nonDynamicAudioService.init(); 853 854 expectWithMessage("Non dynamic routing primary zone's navigation car volume group id") 855 .that(nonDynamicAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 856 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)) 857 .isEqualTo(INVALID_VOLUME_GROUP_ID); 858 } 859 860 @Test getVolumeGroupIdForUsage_forInvalidUsage_returnsInvalidGroupId()861 public void getVolumeGroupIdForUsage_forInvalidUsage_returnsInvalidGroupId() { 862 mCarAudioService.init(); 863 864 expectWithMessage("Primary zone's invalid car volume group id") 865 .that(mCarAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, INVALID_USAGE)) 866 .isEqualTo(INVALID_VOLUME_GROUP_ID); 867 } 868 869 @Test 870 public void getVolumeGroupIdForUsage_forInvalidUsage_withNonDynamicRouting_returnsInvalidGroupId()871 getVolumeGroupIdForUsage_forInvalidUsage_withNonDynamicRouting_returnsInvalidGroupId() { 872 when(mMockResources.getBoolean(audioUseDynamicRouting)) 873 .thenReturn(/* useDynamicRouting= */ false); 874 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 875 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 876 mCarVolumeCallbackHandler); 877 nonDynamicAudioService.init(); 878 879 expectWithMessage("Non dynamic routing primary zone's invalid car volume group id") 880 .that(nonDynamicAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 881 INVALID_USAGE)).isEqualTo(INVALID_VOLUME_GROUP_ID); 882 } 883 884 @Test getVolumeGroupIdForUsage_forUnknownUsage_returnsMediaGroupId()885 public void getVolumeGroupIdForUsage_forUnknownUsage_returnsMediaGroupId() { 886 mCarAudioService.init(); 887 888 expectWithMessage("Primary zone's unknown car volume group id") 889 .that(mCarAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, USAGE_UNKNOWN)) 890 .isEqualTo(MEDIA_VOLUME_GROUP_ID); 891 } 892 893 @Test getVolumeGroupIdForUsage_forVirtualUsage_returnsInvalidGroupId()894 public void getVolumeGroupIdForUsage_forVirtualUsage_returnsInvalidGroupId() { 895 mCarAudioService.init(); 896 897 expectWithMessage("Primary zone's virtual car volume group id") 898 .that(mCarAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, 899 AudioManagerHelper.getUsageVirtualSource())) 900 .isEqualTo(INVALID_VOLUME_GROUP_ID); 901 } 902 903 @Test getVolumeGroupCount_onSecondaryZone_returnsAllGroups()904 public void getVolumeGroupCount_onSecondaryZone_returnsAllGroups() { 905 mCarAudioService.init(); 906 907 expectWithMessage("Secondary Zone car volume group count") 908 .that(mCarAudioService.getVolumeGroupCount(TEST_REAR_LEFT_ZONE_ID)) 909 .isEqualTo(SECONDARY_ZONE_VOLUME_GROUP_COUNT); 910 } 911 912 @Test getUsagesForVolumeGroupId_forMusicContext()913 public void getUsagesForVolumeGroupId_forMusicContext() { 914 mCarAudioService.init(); 915 916 917 expectWithMessage("Primary zone's music car volume group id usages") 918 .that(mCarAudioService.getUsagesForVolumeGroupId(PRIMARY_AUDIO_ZONE, 919 MEDIA_VOLUME_GROUP_ID)).asList() 920 .containsExactly(USAGE_UNKNOWN, USAGE_GAME, USAGE_MEDIA, USAGE_ANNOUNCEMENT, 921 USAGE_NOTIFICATION, USAGE_NOTIFICATION_EVENT); 922 } 923 924 @Test getUsagesForVolumeGroupId_forSystemContext()925 public void getUsagesForVolumeGroupId_forSystemContext() { 926 mCarAudioService.init(); 927 int systemVolumeGroup = 928 mCarAudioService.getVolumeGroupIdForUsage(PRIMARY_AUDIO_ZONE, USAGE_EMERGENCY); 929 930 expectWithMessage("Primary zone's system car volume group id usages") 931 .that(mCarAudioService.getUsagesForVolumeGroupId(PRIMARY_AUDIO_ZONE, 932 systemVolumeGroup)).asList().containsExactly(USAGE_ALARM, USAGE_EMERGENCY, 933 USAGE_SAFETY, USAGE_VEHICLE_STATUS, USAGE_ASSISTANCE_SONIFICATION); 934 } 935 936 @Test getUsagesForVolumeGroupId_onSecondaryZone_forSingleVolumeGroupId_returnAllUsages()937 public void getUsagesForVolumeGroupId_onSecondaryZone_forSingleVolumeGroupId_returnAllUsages() { 938 mCarAudioService.init(); 939 940 expectWithMessage("Secondary Zone's car volume group id usages") 941 .that(mCarAudioService.getUsagesForVolumeGroupId(TEST_REAR_LEFT_ZONE_ID, 942 SECONDARY_ZONE_VOLUME_GROUP_ID)) 943 .asList().containsExactly(USAGE_UNKNOWN, USAGE_MEDIA, 944 USAGE_VOICE_COMMUNICATION, USAGE_VOICE_COMMUNICATION_SIGNALLING, 945 USAGE_ALARM, USAGE_NOTIFICATION, USAGE_NOTIFICATION_RINGTONE, 946 USAGE_NOTIFICATION_EVENT, USAGE_ASSISTANCE_ACCESSIBILITY, 947 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, USAGE_ASSISTANCE_SONIFICATION, 948 USAGE_GAME, USAGE_ASSISTANT, USAGE_CALL_ASSISTANT, USAGE_EMERGENCY, 949 USAGE_ANNOUNCEMENT, USAGE_SAFETY, USAGE_VEHICLE_STATUS); 950 } 951 952 @Test getUsagesForVolumeGroupId_withoutDynamicRouting()953 public void getUsagesForVolumeGroupId_withoutDynamicRouting() { 954 when(mMockResources.getBoolean(audioUseDynamicRouting)) 955 .thenReturn(/* useDynamicRouting= */ false); 956 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 957 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 958 mCarVolumeCallbackHandler); 959 nonDynamicAudioService.init(); 960 961 expectWithMessage("Media car volume group id without dynamic routing").that( 962 nonDynamicAudioService.getUsagesForVolumeGroupId(PRIMARY_AUDIO_ZONE, 963 MEDIA_VOLUME_GROUP_ID)).asList() 964 .containsExactly(CarAudioDynamicRouting.STREAM_TYPE_USAGES[MEDIA_VOLUME_GROUP_ID]); 965 } 966 967 @Test createAudioPatch_onMediaOutputDevice_failsForConfigurationMissing()968 public void createAudioPatch_onMediaOutputDevice_failsForConfigurationMissing() { 969 mCarAudioService.init(); 970 971 doReturn(false) 972 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, false)); 973 974 IllegalStateException thrown = assertThrows(IllegalStateException.class, 975 () -> mCarAudioService 976 .createAudioPatch(PRIMARY_ZONE_FM_TUNER_ADDRESS, 977 USAGE_MEDIA, DEFAULT_GAIN)); 978 979 expectWithMessage("FM and Media Audio Patch Exception") 980 .that(thrown).hasMessageThat().contains("Audio Patch APIs not enabled"); 981 } 982 983 @Test createAudioPatch_onMediaOutputDevice_failsForMissingPermission()984 public void createAudioPatch_onMediaOutputDevice_failsForMissingPermission() { 985 mCarAudioService.init(); 986 987 mockDenyCarControlAudioSettingsPermission(); 988 989 SecurityException thrown = assertThrows(SecurityException.class, 990 () -> mCarAudioService 991 .createAudioPatch(PRIMARY_ZONE_FM_TUNER_ADDRESS, 992 USAGE_MEDIA, DEFAULT_GAIN)); 993 994 expectWithMessage("FM and Media Audio Patch Permission Exception") 995 .that(thrown).hasMessageThat().contains(PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 996 } 997 998 @Test createAudioPatch_onMediaOutputDevice_succeeds()999 public void createAudioPatch_onMediaOutputDevice_succeeds() { 1000 mCarAudioService.init(); 1001 1002 mockGrantCarControlAudioSettingsPermission(); 1003 doReturn(false) 1004 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, true)); 1005 doReturn(new AudioPatchInfo(PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE, 0)) 1006 .when(() -> AudioManagerHelper 1007 .createAudioPatch(mFmTunerInputDevice, mMediaOutputDevice, DEFAULT_GAIN)); 1008 1009 CarAudioPatchHandle audioPatch = mCarAudioService 1010 .createAudioPatch(PRIMARY_ZONE_FM_TUNER_ADDRESS, USAGE_MEDIA, DEFAULT_GAIN); 1011 1012 expectWithMessage("Audio Patch Sink Address") 1013 .that(audioPatch.getSinkAddress()).isEqualTo(MEDIA_TEST_DEVICE); 1014 expectWithMessage("Audio Patch Source Address") 1015 .that(audioPatch.getSourceAddress()).isEqualTo(PRIMARY_ZONE_FM_TUNER_ADDRESS); 1016 expectWithMessage("Audio Patch Handle") 1017 .that(audioPatch.getHandleId()).isEqualTo(0); 1018 } 1019 1020 @Test releaseAudioPatch_failsForConfigurationMissing()1021 public void releaseAudioPatch_failsForConfigurationMissing() { 1022 mCarAudioService.init(); 1023 1024 doReturn(false) 1025 .when(() -> SystemProperties.getBoolean(PROPERTY_RO_ENABLE_AUDIO_PATCH, false)); 1026 CarAudioPatchHandle carAudioPatchHandle = 1027 new CarAudioPatchHandle(0, PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE); 1028 1029 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1030 () -> mCarAudioService.releaseAudioPatch(carAudioPatchHandle)); 1031 1032 expectWithMessage("Release FM and Media Audio Patch Exception") 1033 .that(thrown).hasMessageThat().contains("Audio Patch APIs not enabled"); 1034 } 1035 1036 @Test releaseAudioPatch_failsForMissingPermission()1037 public void releaseAudioPatch_failsForMissingPermission() { 1038 mCarAudioService.init(); 1039 1040 mockDenyCarControlAudioSettingsPermission(); 1041 CarAudioPatchHandle carAudioPatchHandle = 1042 new CarAudioPatchHandle(0, PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE); 1043 1044 SecurityException thrown = assertThrows(SecurityException.class, 1045 () -> mCarAudioService.releaseAudioPatch(carAudioPatchHandle)); 1046 1047 expectWithMessage("FM and Media Audio Patch Permission Exception") 1048 .that(thrown).hasMessageThat().contains(PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 1049 } 1050 1051 @Test releaseAudioPatch_forNullSourceAddress_throwsNullPointerException()1052 public void releaseAudioPatch_forNullSourceAddress_throwsNullPointerException() { 1053 mCarAudioService.init(); 1054 mockGrantCarControlAudioSettingsPermission(); 1055 doReturn(new AudioPatchInfo(PRIMARY_ZONE_FM_TUNER_ADDRESS, MEDIA_TEST_DEVICE, 0)) 1056 .when(() -> AudioManagerHelper 1057 .createAudioPatch(mFmTunerInputDevice, mMediaOutputDevice, DEFAULT_GAIN)); 1058 1059 CarAudioPatchHandle audioPatch = mock(CarAudioPatchHandle.class); 1060 when(audioPatch.getSourceAddress()).thenReturn(null); 1061 1062 NullPointerException thrown = assertThrows(NullPointerException.class, 1063 () -> mCarAudioService.releaseAudioPatch(audioPatch)); 1064 1065 expectWithMessage("Release audio patch for null source address " 1066 + "and sink address Null Exception") 1067 .that(thrown).hasMessageThat() 1068 .contains("Source Address can not be null for patch id 0"); 1069 } 1070 1071 @Test releaseAudioPatch_failsForNullPatch()1072 public void releaseAudioPatch_failsForNullPatch() { 1073 mCarAudioService.init(); 1074 1075 assertThrows(NullPointerException.class, 1076 () -> mCarAudioService.releaseAudioPatch(null)); 1077 } 1078 1079 @Test setZoneIdForUid_withoutRoutingPermission_fails()1080 public void setZoneIdForUid_withoutRoutingPermission_fails() { 1081 mCarAudioService.init(); 1082 1083 mockDenyCarControlAudioSettingsPermission(); 1084 1085 SecurityException thrown = assertThrows(SecurityException.class, 1086 () -> mCarAudioService.setZoneIdForUid(OUT_OF_RANGE_ZONE, MEDIA_APP_UID)); 1087 1088 expectWithMessage("Set Zone for UID Permission Exception") 1089 .that(thrown).hasMessageThat() 1090 .contains(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 1091 } 1092 1093 @Test setZoneIdForUid_withoutDynamicRouting_fails()1094 public void setZoneIdForUid_withoutDynamicRouting_fails() { 1095 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1096 .thenReturn(/* useDynamicRouting= */ false); 1097 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1098 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1099 mCarVolumeCallbackHandler); 1100 nonDynamicAudioService.init(); 1101 1102 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1103 () -> nonDynamicAudioService.setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID)); 1104 1105 expectWithMessage("Set Zone for UID Dynamic Configuration Exception") 1106 .that(thrown).hasMessageThat() 1107 .contains("Dynamic routing is required"); 1108 } 1109 1110 @Test setZoneIdForUid_withInvalidZone_fails()1111 public void setZoneIdForUid_withInvalidZone_fails() { 1112 mCarAudioService.init(); 1113 1114 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 1115 () -> mCarAudioService.setZoneIdForUid(INVALID_AUDIO_ZONE, MEDIA_APP_UID)); 1116 1117 expectWithMessage("Set Zone for UID Invalid Zone Exception") 1118 .that(thrown).hasMessageThat() 1119 .contains("Invalid audio zone Id " + INVALID_AUDIO_ZONE); 1120 } 1121 1122 @Test setZoneIdForUid_withOutOfRangeZone_fails()1123 public void setZoneIdForUid_withOutOfRangeZone_fails() { 1124 mCarAudioService.init(); 1125 1126 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 1127 () -> mCarAudioService.setZoneIdForUid(OUT_OF_RANGE_ZONE, MEDIA_APP_UID)); 1128 1129 expectWithMessage("Set Zone for UID Zone Out of Range Exception") 1130 .that(thrown).hasMessageThat() 1131 .contains("Invalid audio zone Id " + OUT_OF_RANGE_ZONE); 1132 } 1133 1134 @Test setZoneIdForUid_withZoneAudioMapping_fails()1135 public void setZoneIdForUid_withZoneAudioMapping_fails() { 1136 mCarAudioService.init(); 1137 1138 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1139 () -> mCarAudioService.setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID)); 1140 1141 expectWithMessage("Set Zone for UID With Audio Zone Mapping Exception") 1142 .that(thrown).hasMessageThat() 1143 .contains("UID based routing is not supported while using occupant zone mapping"); 1144 } 1145 1146 @Test setZoneIdForUid_withValidZone_succeeds()1147 public void setZoneIdForUid_withValidZone_succeeds() throws Exception { 1148 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1149 .thenReturn(SUCCESS); 1150 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1151 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1152 mCarVolumeCallbackHandler); 1153 noZoneMappingAudioService.init(); 1154 1155 boolean results = noZoneMappingAudioService 1156 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1157 1158 expectWithMessage("Set Zone for UID Status").that(results).isTrue(); 1159 } 1160 1161 @Test setZoneIdForUid_onDifferentZones_succeeds()1162 public void setZoneIdForUid_onDifferentZones_succeeds() throws Exception { 1163 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1164 .thenReturn(SUCCESS); 1165 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1166 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1167 mCarVolumeCallbackHandler); 1168 noZoneMappingAudioService.init(); 1169 1170 noZoneMappingAudioService 1171 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1172 1173 boolean results = noZoneMappingAudioService 1174 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1175 1176 expectWithMessage("Set Zone for UID For Different Zone") 1177 .that(results).isTrue(); 1178 } 1179 1180 @Test setZoneIdForUid_onDifferentZones_withAudioFocus_succeeds()1181 public void setZoneIdForUid_onDifferentZones_withAudioFocus_succeeds() throws Exception { 1182 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1183 .thenReturn(SUCCESS); 1184 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1185 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1186 mCarVolumeCallbackHandler); 1187 noZoneMappingAudioService.init(); 1188 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(); 1189 1190 noZoneMappingAudioService 1191 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1192 1193 noZoneMappingAudioService 1194 .requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 1195 1196 boolean results = noZoneMappingAudioService 1197 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1198 1199 expectWithMessage("Set Zone for UID For Different Zone with Audio Focus") 1200 .that(results).isTrue(); 1201 } 1202 1203 @Test getZoneIdForUid_withoutMappedUid_succeeds()1204 public void getZoneIdForUid_withoutMappedUid_succeeds() throws Exception { 1205 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1206 .thenReturn(SUCCESS); 1207 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1208 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1209 mCarVolumeCallbackHandler); 1210 noZoneMappingAudioService.init(); 1211 1212 int zoneId = noZoneMappingAudioService 1213 .getZoneIdForUid(MEDIA_APP_UID); 1214 1215 expectWithMessage("Get Zone for Non Mapped UID") 1216 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1217 } 1218 1219 @Test getZoneIdForUid_succeeds()1220 public void getZoneIdForUid_succeeds() throws Exception { 1221 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1222 .thenReturn(SUCCESS); 1223 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1224 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1225 mCarVolumeCallbackHandler); 1226 noZoneMappingAudioService.init(); 1227 1228 noZoneMappingAudioService 1229 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1230 1231 int zoneId = noZoneMappingAudioService 1232 .getZoneIdForUid(MEDIA_APP_UID); 1233 1234 expectWithMessage("Get Zone for UID Zone Id") 1235 .that(zoneId).isEqualTo(TEST_REAR_LEFT_ZONE_ID); 1236 } 1237 1238 @Test getZoneIdForUid_afterSwitchingZones_succeeds()1239 public void getZoneIdForUid_afterSwitchingZones_succeeds() throws Exception { 1240 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1241 .thenReturn(SUCCESS); 1242 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1243 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1244 mCarVolumeCallbackHandler); 1245 noZoneMappingAudioService.init(); 1246 1247 noZoneMappingAudioService 1248 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1249 1250 noZoneMappingAudioService 1251 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1252 1253 int zoneId = noZoneMappingAudioService 1254 .getZoneIdForUid(MEDIA_APP_UID); 1255 1256 expectWithMessage("Get Zone for UID Zone Id") 1257 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1258 } 1259 1260 @Test clearZoneIdForUid_withoutRoutingPermission_fails()1261 public void clearZoneIdForUid_withoutRoutingPermission_fails() { 1262 mCarAudioService.init(); 1263 1264 mockDenyCarControlAudioSettingsPermission(); 1265 1266 SecurityException thrown = assertThrows(SecurityException.class, 1267 () -> mCarAudioService.clearZoneIdForUid(MEDIA_APP_UID)); 1268 1269 expectWithMessage("Clear Zone for UID Permission Exception") 1270 .that(thrown).hasMessageThat() 1271 .contains(Car.PERMISSION_CAR_CONTROL_AUDIO_SETTINGS); 1272 } 1273 1274 @Test clearZoneIdForUid_withoutDynamicRouting_fails()1275 public void clearZoneIdForUid_withoutDynamicRouting_fails() { 1276 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1277 .thenReturn(/* useDynamicRouting= */ false); 1278 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1279 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1280 mCarVolumeCallbackHandler); 1281 nonDynamicAudioService.init(); 1282 1283 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1284 () -> nonDynamicAudioService.clearZoneIdForUid(MEDIA_APP_UID)); 1285 1286 expectWithMessage("Clear Zone for UID Dynamic Configuration Exception") 1287 .that(thrown).hasMessageThat() 1288 .contains("Dynamic routing is required"); 1289 } 1290 1291 @Test clearZoneIdForUid_withZoneAudioMapping_fails()1292 public void clearZoneIdForUid_withZoneAudioMapping_fails() { 1293 mCarAudioService.init(); 1294 1295 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1296 () -> mCarAudioService.clearZoneIdForUid(MEDIA_APP_UID)); 1297 1298 expectWithMessage("Clear Zone for UID Audio Zone Mapping Exception") 1299 .that(thrown).hasMessageThat() 1300 .contains("UID based routing is not supported while using occupant zone mapping"); 1301 } 1302 1303 @Test clearZoneIdForUid_forNonMappedUid_succeeds()1304 public void clearZoneIdForUid_forNonMappedUid_succeeds() throws Exception { 1305 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1306 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1307 mCarVolumeCallbackHandler); 1308 noZoneMappingAudioService.init(); 1309 1310 boolean status = noZoneMappingAudioService 1311 .clearZoneIdForUid(MEDIA_APP_UID); 1312 1313 expectWithMessage("Clear Zone for UID Audio Zone without Mapping") 1314 .that(status).isTrue(); 1315 } 1316 1317 @Test clearZoneIdForUid_forMappedUid_succeeds()1318 public void clearZoneIdForUid_forMappedUid_succeeds() throws Exception { 1319 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1320 .thenReturn(SUCCESS); 1321 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1322 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1323 mCarVolumeCallbackHandler); 1324 noZoneMappingAudioService.init(); 1325 1326 noZoneMappingAudioService 1327 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1328 1329 boolean status = noZoneMappingAudioService.clearZoneIdForUid(MEDIA_APP_UID); 1330 1331 expectWithMessage("Clear Zone for UID Audio Zone with Mapping") 1332 .that(status).isTrue(); 1333 } 1334 1335 @Test getZoneIdForUid_afterClearedUidMapping_returnsDefaultZone()1336 public void getZoneIdForUid_afterClearedUidMapping_returnsDefaultZone() throws Exception { 1337 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1338 .thenReturn(SUCCESS); 1339 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1340 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1341 mCarVolumeCallbackHandler); 1342 noZoneMappingAudioService.init(); 1343 1344 noZoneMappingAudioService 1345 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1346 1347 noZoneMappingAudioService.clearZoneIdForUid(MEDIA_APP_UID); 1348 1349 int zoneId = noZoneMappingAudioService.getZoneIdForUid(MEDIA_APP_UID); 1350 1351 expectWithMessage("Get Zone for UID Audio Zone with Cleared Mapping") 1352 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1353 } 1354 1355 @Test getZoneIdForAudioFocusInfo_withoutMappedUid_succeeds()1356 public void getZoneIdForAudioFocusInfo_withoutMappedUid_succeeds() throws Exception { 1357 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1358 .thenReturn(SUCCESS); 1359 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1360 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1361 mCarVolumeCallbackHandler); 1362 noZoneMappingAudioService.init(); 1363 1364 int zoneId = noZoneMappingAudioService 1365 .getZoneIdForAudioFocusInfo(TEST_AUDIO_FOCUS_INFO); 1366 1367 expectWithMessage("Mapped audio focus info's zone") 1368 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1369 } 1370 1371 @Test getZoneIdForAudioFocusInfo_succeeds()1372 public void getZoneIdForAudioFocusInfo_succeeds() throws Exception { 1373 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1374 .thenReturn(SUCCESS); 1375 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1376 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1377 mCarVolumeCallbackHandler); 1378 noZoneMappingAudioService.init(); 1379 1380 noZoneMappingAudioService 1381 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1382 1383 int zoneId = noZoneMappingAudioService 1384 .getZoneIdForAudioFocusInfo(TEST_AUDIO_FOCUS_INFO); 1385 1386 expectWithMessage("Mapped audio focus info's zone") 1387 .that(zoneId).isEqualTo(TEST_REAR_LEFT_ZONE_ID); 1388 } 1389 1390 @Test getZoneIdForAudioFocusInfo_afterSwitchingZones_succeeds()1391 public void getZoneIdForAudioFocusInfo_afterSwitchingZones_succeeds() throws Exception { 1392 when(mMockAudioService.setUidDeviceAffinity(any(), anyInt(), any(), any())) 1393 .thenReturn(SUCCESS); 1394 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1395 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1396 mCarVolumeCallbackHandler); 1397 noZoneMappingAudioService.init(); 1398 noZoneMappingAudioService 1399 .setZoneIdForUid(TEST_REAR_LEFT_ZONE_ID, MEDIA_APP_UID); 1400 noZoneMappingAudioService 1401 .setZoneIdForUid(PRIMARY_AUDIO_ZONE, MEDIA_APP_UID); 1402 1403 int zoneId = noZoneMappingAudioService 1404 .getZoneIdForAudioFocusInfo(TEST_AUDIO_FOCUS_INFO); 1405 1406 expectWithMessage("Remapped audio focus info's zone") 1407 .that(zoneId).isEqualTo(PRIMARY_AUDIO_ZONE); 1408 } 1409 1410 @Test setGroupVolume_withoutPermission_fails()1411 public void setGroupVolume_withoutPermission_fails() { 1412 mCarAudioService.init(); 1413 1414 mockDenyCarControlAudioVolumePermission(); 1415 1416 SecurityException thrown = assertThrows(SecurityException.class, 1417 () -> mCarAudioService.setGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1418 TEST_GAIN_INDEX, TEST_FLAGS)); 1419 1420 expectWithMessage("Set Volume Group Permission Exception") 1421 .that(thrown).hasMessageThat() 1422 .contains(Car.PERMISSION_CAR_CONTROL_AUDIO_VOLUME); 1423 } 1424 1425 @Test setGroupVolume_withDynamicRoutingDisabled()1426 public void setGroupVolume_withDynamicRoutingDisabled() { 1427 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1428 .thenReturn(/* useDynamicRouting= */ false); 1429 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1430 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1431 mCarVolumeCallbackHandler); 1432 nonDynamicAudioService.init(); 1433 1434 nonDynamicAudioService.setGroupVolume( 1435 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, TEST_GAIN_INDEX, TEST_FLAGS); 1436 1437 verify(mAudioManager).setStreamVolume( 1438 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0], 1439 TEST_GAIN_INDEX, 1440 TEST_FLAGS); 1441 } 1442 1443 @Test setGroupVolume_verifyNoCallbacks()1444 public void setGroupVolume_verifyNoCallbacks() { 1445 mCarAudioService.init(); 1446 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1447 /* mute= */ false, TEST_FLAGS); 1448 reset(mCarVolumeCallbackHandler); 1449 1450 mCarAudioService.setGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1451 TEST_GAIN_INDEX, TEST_FLAGS); 1452 1453 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 1454 } 1455 1456 @Test setGroupVolume_afterSetVolumeGroupMute()1457 public void setGroupVolume_afterSetVolumeGroupMute() { 1458 mCarAudioService.init(); 1459 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1460 /* mute= */ true, TEST_FLAGS); 1461 reset(mCarVolumeCallbackHandler); 1462 1463 mCarAudioService.setGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1464 TEST_GAIN_INDEX, TEST_FLAGS); 1465 1466 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 1467 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 1468 } 1469 1470 @Test setGroupVolume_withVolumeGroupMutingDisabled_doesnotThrowException()1471 public void setGroupVolume_withVolumeGroupMutingDisabled_doesnotThrowException() { 1472 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)).thenReturn(false); 1473 CarAudioService nonVolumeGroupMutingAudioService = new CarAudioService(mMockContext, 1474 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1475 mCarVolumeCallbackHandler); 1476 nonVolumeGroupMutingAudioService.init(); 1477 HalAudioGainCallback callback = getHalAudioGainCallback(); 1478 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(PRIMARY_AUDIO_ZONE, 1479 MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 1480 callback.onAudioDeviceGainsChanged(List.of(Reasons.TCU_MUTE), List.of(carGain)); 1481 reset(mCarVolumeCallbackHandler); 1482 1483 nonVolumeGroupMutingAudioService.setGroupVolume( 1484 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, TEST_GAIN_INDEX, TEST_FLAGS); 1485 1486 // if an exception is thrown, the test automatically fails 1487 verify(mCarVolumeCallbackHandler).onVolumeGroupChange(eq(PRIMARY_AUDIO_ZONE), 1488 eq(TEST_PRIMARY_ZONE_GROUP_0), anyInt()); 1489 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 1490 } 1491 1492 @Test getOutputDeviceAddressForUsage_forMusicUsage()1493 public void getOutputDeviceAddressForUsage_forMusicUsage() { 1494 mCarAudioService.init(); 1495 1496 String mediaDeviceAddress = 1497 mCarAudioService.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, USAGE_MEDIA); 1498 1499 expectWithMessage("Media usage audio device address") 1500 .that(mediaDeviceAddress).isEqualTo(MEDIA_TEST_DEVICE); 1501 } 1502 1503 @Test getOutputDeviceAddressForUsage_withNonDynamicRouting_forMediaUsage_fails()1504 public void getOutputDeviceAddressForUsage_withNonDynamicRouting_forMediaUsage_fails() { 1505 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1506 .thenReturn(/* useDynamicRouting= */ false); 1507 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1508 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1509 mCarVolumeCallbackHandler); 1510 nonDynamicAudioService.init(); 1511 1512 IllegalStateException thrown = assertThrows(IllegalStateException.class, 1513 () -> nonDynamicAudioService 1514 .getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, USAGE_MEDIA)); 1515 1516 expectWithMessage("Non dynamic routing media usage audio device address exception") 1517 .that(thrown).hasMessageThat().contains("Dynamic routing is required"); 1518 } 1519 1520 @Test getOutputDeviceAddressForUsage_forNavigationUsage()1521 public void getOutputDeviceAddressForUsage_forNavigationUsage() { 1522 mCarAudioService.init(); 1523 1524 String mediaDeviceAddress = 1525 mCarAudioService.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, 1526 USAGE_ASSISTANCE_NAVIGATION_GUIDANCE); 1527 1528 expectWithMessage("Navigation usage audio device address") 1529 .that(mediaDeviceAddress).isEqualTo(NAVIGATION_TEST_DEVICE); 1530 } 1531 1532 @Test getOutputDeviceAddressForUsage_forInvalidUsage_fails()1533 public void getOutputDeviceAddressForUsage_forInvalidUsage_fails() { 1534 mCarAudioService.init(); 1535 1536 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> 1537 mCarAudioService.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, 1538 INVALID_USAGE)); 1539 1540 expectWithMessage("Invalid usage audio device address exception") 1541 .that(thrown).hasMessageThat().contains("Invalid audio attribute " + INVALID_USAGE); 1542 } 1543 1544 @Test getOutputDeviceAddressForUsage_forVirtualUsage_fails()1545 public void getOutputDeviceAddressForUsage_forVirtualUsage_fails() { 1546 mCarAudioService.init(); 1547 1548 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> 1549 mCarAudioService.getOutputDeviceAddressForUsage(PRIMARY_AUDIO_ZONE, 1550 AudioManagerHelper.getUsageVirtualSource())); 1551 1552 expectWithMessage("Invalid context audio device address exception") 1553 .that(thrown).hasMessageThat() 1554 .contains("invalid"); 1555 } 1556 1557 @Test getOutputDeviceAddressForUsage_onSecondaryZone_forMusicUsage()1558 public void getOutputDeviceAddressForUsage_onSecondaryZone_forMusicUsage() { 1559 mCarAudioService.init(); 1560 1561 String mediaDeviceAddress = mCarAudioService.getOutputDeviceAddressForUsage( 1562 TEST_REAR_LEFT_ZONE_ID, USAGE_MEDIA); 1563 1564 expectWithMessage("Media usage audio device address for secondary zone") 1565 .that(mediaDeviceAddress).isEqualTo(SECONDARY_TEST_DEVICE_CONFIG_0); 1566 } 1567 1568 @Test getSuggestedAudioContextForZone_inPrimaryZone()1569 public void getSuggestedAudioContextForZone_inPrimaryZone() { 1570 mCarAudioService.init(); 1571 int defaultAudioContext = mCarAudioService.getCarAudioContext() 1572 .getContextForAudioAttribute(CAR_DEFAULT_AUDIO_ATTRIBUTE); 1573 1574 expectWithMessage("Suggested audio context for primary zone") 1575 .that(mCarAudioService.getSuggestedAudioContextForZone(PRIMARY_AUDIO_ZONE)) 1576 .isEqualTo(defaultAudioContext); 1577 } 1578 1579 @Test getSuggestedAudioContextForZone_inSecondaryZone()1580 public void getSuggestedAudioContextForZone_inSecondaryZone() { 1581 mCarAudioService.init(); 1582 int defaultAudioContext = mCarAudioService.getCarAudioContext() 1583 .getContextForAudioAttribute(CAR_DEFAULT_AUDIO_ATTRIBUTE); 1584 1585 expectWithMessage("Suggested audio context for secondary zone") 1586 .that(mCarAudioService.getSuggestedAudioContextForZone(TEST_REAR_LEFT_ZONE_ID)) 1587 .isEqualTo(defaultAudioContext); 1588 } 1589 1590 @Test getSuggestedAudioContextForZone_inInvalidZone()1591 public void getSuggestedAudioContextForZone_inInvalidZone() { 1592 mCarAudioService.init(); 1593 1594 expectWithMessage("Suggested audio context for invalid zone") 1595 .that(mCarAudioService.getSuggestedAudioContextForZone(INVALID_AUDIO_ZONE)) 1596 .isEqualTo(CarAudioContext.getInvalidContext()); 1597 } 1598 1599 @Test isVolumeGroupMuted_noSetVolumeGroupMute()1600 public void isVolumeGroupMuted_noSetVolumeGroupMute() { 1601 mCarAudioService.init(); 1602 1603 expectWithMessage("Volume group mute for default state") 1604 .that(mCarAudioService.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 1605 TEST_PRIMARY_ZONE_GROUP_0)).isFalse(); 1606 } 1607 1608 @Test isVolumeGroupMuted_setVolumeGroupMuted_isFalse()1609 public void isVolumeGroupMuted_setVolumeGroupMuted_isFalse() { 1610 mCarAudioService.init(); 1611 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1612 /* mute= */ true, TEST_FLAGS); 1613 1614 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1615 /* mute= */ false, TEST_FLAGS); 1616 1617 expectWithMessage("Volume group muted after mute and unmute") 1618 .that(mCarAudioService.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 1619 TEST_PRIMARY_ZONE_GROUP_0)).isFalse(); 1620 } 1621 1622 @Test isVolumeGroupMuted_setVolumeGroupMuted_isTrue()1623 public void isVolumeGroupMuted_setVolumeGroupMuted_isTrue() { 1624 mCarAudioService.init(); 1625 1626 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 1627 /* mute= */ true, TEST_FLAGS); 1628 expectWithMessage("Volume group muted after mute") 1629 .that(mCarAudioService.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 1630 TEST_PRIMARY_ZONE_GROUP_0)).isTrue(); 1631 } 1632 1633 @Test isVolumeGroupMuted_withVolumeGroupMutingDisabled()1634 public void isVolumeGroupMuted_withVolumeGroupMutingDisabled() { 1635 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)) 1636 .thenReturn(false); 1637 CarAudioService nonVolumeGroupMutingAudioService = new CarAudioService(mMockContext, 1638 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1639 mCarVolumeCallbackHandler); 1640 nonVolumeGroupMutingAudioService.init(); 1641 1642 expectWithMessage("Volume group for disabled volume group muting") 1643 .that(nonVolumeGroupMutingAudioService.isVolumeGroupMuted( 1644 PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0)) 1645 .isFalse(); 1646 } 1647 1648 @Test getGroupMaxVolume_forPrimaryZone()1649 public void getGroupMaxVolume_forPrimaryZone() { 1650 mCarAudioService.init(); 1651 1652 expectWithMessage("Group max volume for primary audio zone and group") 1653 .that(mCarAudioService.getGroupMaxVolume(PRIMARY_AUDIO_ZONE, 1654 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo((MAX_GAIN - MIN_GAIN) / STEP_SIZE); 1655 } 1656 1657 @Test getGroupMinVolume_forPrimaryZone()1658 public void getGroupMinVolume_forPrimaryZone() { 1659 mCarAudioService.init(); 1660 1661 expectWithMessage("Group Min Volume for primary audio zone and group") 1662 .that(mCarAudioService.getGroupMinVolume(PRIMARY_AUDIO_ZONE, 1663 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(0); 1664 } 1665 1666 @Test getGroupCurrentVolume_forPrimaryZone()1667 public void getGroupCurrentVolume_forPrimaryZone() { 1668 mCarAudioService.init(); 1669 1670 expectWithMessage("Current group volume for primary audio zone and group") 1671 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 1672 TEST_PRIMARY_ZONE_GROUP_0)) 1673 .isEqualTo((DEFAULT_GAIN - MIN_GAIN) / STEP_SIZE); 1674 } 1675 1676 @Test getGroupMaxVolume_withNoDynamicRouting()1677 public void getGroupMaxVolume_withNoDynamicRouting() { 1678 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1679 .thenReturn(/* useDynamicRouting= */ false); 1680 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1681 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1682 mCarVolumeCallbackHandler); 1683 nonDynamicAudioService.init(); 1684 1685 nonDynamicAudioService.getGroupMaxVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 1686 1687 verify(mAudioManager).getStreamMaxVolume( 1688 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0]); 1689 } 1690 1691 @Test getGroupMinVolume_withNoDynamicRouting()1692 public void getGroupMinVolume_withNoDynamicRouting() { 1693 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1694 .thenReturn(/* useDynamicRouting= */ false); 1695 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1696 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1697 mCarVolumeCallbackHandler); 1698 nonDynamicAudioService.init(); 1699 1700 nonDynamicAudioService.getGroupMinVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 1701 1702 verify(mAudioManager).getStreamMinVolume( 1703 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0]); 1704 } 1705 1706 @Test getGroupCurrentVolume_withNoDynamicRouting()1707 public void getGroupCurrentVolume_withNoDynamicRouting() { 1708 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1709 .thenReturn(/* useDynamicRouting= */ false); 1710 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1711 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1712 mCarVolumeCallbackHandler); 1713 nonDynamicAudioService.init(); 1714 1715 nonDynamicAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 1716 1717 verify(mAudioManager).getStreamVolume( 1718 CarAudioDynamicRouting.STREAM_TYPES[TEST_PRIMARY_ZONE_GROUP_0]); 1719 } 1720 1721 @Test setBalanceTowardRight_nonNullValue()1722 public void setBalanceTowardRight_nonNullValue() { 1723 mCarAudioService.init(); 1724 1725 mCarAudioService.setBalanceTowardRight(TEST_VALUE); 1726 1727 verify(mAudioControlWrapperAidl).setBalanceTowardRight(TEST_VALUE); 1728 } 1729 1730 @Test setBalanceTowardRight_throws()1731 public void setBalanceTowardRight_throws() { 1732 mCarAudioService.init(); 1733 1734 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () 1735 -> mCarAudioService.setBalanceTowardRight(INVALID_TEST_VALUE)); 1736 1737 expectWithMessage("Out of bounds balance") 1738 .that(thrown).hasMessageThat() 1739 .contains(String.format("Balance is out of range of [%f, %f]", -1f, 1f)); 1740 } 1741 1742 @Test setFadeTowardFront_nonNullValue()1743 public void setFadeTowardFront_nonNullValue() { 1744 mCarAudioService.init(); 1745 1746 mCarAudioService.setFadeTowardFront(TEST_VALUE); 1747 1748 verify(mAudioControlWrapperAidl).setFadeTowardFront(TEST_VALUE); 1749 } 1750 1751 @Test setFadeTowardFront_throws()1752 public void setFadeTowardFront_throws() { 1753 mCarAudioService.init(); 1754 1755 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () 1756 -> mCarAudioService.setFadeTowardFront(INVALID_TEST_VALUE)); 1757 1758 expectWithMessage("Out of bounds fade") 1759 .that(thrown).hasMessageThat() 1760 .contains(String.format("Fade is out of range of [%f, %f]", -1f, 1f)); 1761 } 1762 1763 @Test isAudioFeatureEnabled_forDynamicRouting()1764 public void isAudioFeatureEnabled_forDynamicRouting() { 1765 mCarAudioService.init(); 1766 1767 expectWithMessage("Dynamic routing audio feature") 1768 .that(mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_DYNAMIC_ROUTING)) 1769 .isEqualTo(mUseDynamicRouting); 1770 } 1771 1772 @Test isAudioFeatureEnabled_forDisabledDynamicRouting()1773 public void isAudioFeatureEnabled_forDisabledDynamicRouting() { 1774 when(mMockResources.getBoolean(audioUseDynamicRouting)) 1775 .thenReturn(/* useDynamicRouting= */ false); 1776 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 1777 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1778 mCarVolumeCallbackHandler); 1779 nonDynamicAudioService.init(); 1780 1781 expectWithMessage("Disabled dynamic routing audio feature") 1782 .that(nonDynamicAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_DYNAMIC_ROUTING)) 1783 .isFalse(); 1784 } 1785 1786 @Test isAudioFeatureEnabled_forVolumeGroupMuting()1787 public void isAudioFeatureEnabled_forVolumeGroupMuting() { 1788 mCarAudioService.init(); 1789 1790 expectWithMessage("Group muting audio feature") 1791 .that(mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_MUTING)) 1792 .isEqualTo(mUseCarVolumeGroupMuting); 1793 } 1794 1795 @Test isAudioFeatureEnabled_forDisabledVolumeGroupMuting()1796 public void isAudioFeatureEnabled_forDisabledVolumeGroupMuting() { 1797 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)).thenReturn(false); 1798 CarAudioService nonVolumeGroupMutingAudioService = new CarAudioService(mMockContext, 1799 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1800 mCarVolumeCallbackHandler); 1801 nonVolumeGroupMutingAudioService.init(); 1802 1803 expectWithMessage("Disabled group muting audio feature") 1804 .that(nonVolumeGroupMutingAudioService 1805 .isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_MUTING)) 1806 .isFalse(); 1807 } 1808 1809 @Test isAudioFeatureEnabled_forVolumeGroupEvent()1810 public void isAudioFeatureEnabled_forVolumeGroupEvent() { 1811 mCarAudioService.init(); 1812 1813 expectWithMessage("Group events audio feature") 1814 .that(mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_EVENTS)) 1815 .isEqualTo(mUseCarVolumeGroupEvents); 1816 } 1817 1818 @Test isAudioFeatureEnabled_forDisabledVolumeGroupEvent()1819 public void isAudioFeatureEnabled_forDisabledVolumeGroupEvent() { 1820 when(mMockResources.getBoolean(audioUseCarVolumeGroupEvent)).thenReturn(false); 1821 CarAudioService nonVolumeGroupEventsAudioService = new CarAudioService(mMockContext, 1822 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 1823 mCarVolumeCallbackHandler); 1824 nonVolumeGroupEventsAudioService.init(); 1825 1826 expectWithMessage("Disabled group event audio feature") 1827 .that(nonVolumeGroupEventsAudioService 1828 .isAudioFeatureEnabled(AUDIO_FEATURE_VOLUME_GROUP_EVENTS)) 1829 .isFalse(); 1830 } 1831 1832 @Test isAudioFeatureEnabled_forUnrecognizableAudioFeature_throws()1833 public void isAudioFeatureEnabled_forUnrecognizableAudioFeature_throws() { 1834 mCarAudioService.init(); 1835 1836 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, 1837 () -> mCarAudioService.isAudioFeatureEnabled(INVALID_AUDIO_FEATURE)); 1838 1839 expectWithMessage("Unknown audio feature") 1840 .that(thrown).hasMessageThat() 1841 .contains("Unknown Audio Feature type: " + INVALID_AUDIO_FEATURE); 1842 } 1843 1844 @Test isAudioFeatureEnabled_forDisabledOemService()1845 public void isAudioFeatureEnabled_forDisabledOemService() { 1846 mCarAudioService.init(); 1847 1848 boolean isEnabled = 1849 mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 1850 1851 expectWithMessage("Oem service enabled with disabled oem service") 1852 .that(isEnabled).isFalse(); 1853 } 1854 1855 @Test isAudioFeatureEnabled_withEnabledFocusService()1856 public void isAudioFeatureEnabled_withEnabledFocusService() { 1857 CarOemAudioFocusProxyService service = mock(CarOemAudioFocusProxyService.class); 1858 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(true); 1859 when(mMockCarOemProxyService.getCarOemAudioFocusService()).thenReturn(service); 1860 mCarAudioService.init(); 1861 1862 boolean isEnabled = 1863 mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 1864 1865 expectWithMessage("Oem service enabled with enabled focus service") 1866 .that(isEnabled).isTrue(); 1867 } 1868 1869 @Test isAudioFeatureEnabled_withEnabledFocusServiceAndReleaseLessThanU()1870 public void isAudioFeatureEnabled_withEnabledFocusServiceAndReleaseLessThanU() { 1871 mockCarGetPlatformVersion(TIRAMISU_1); 1872 CarOemAudioFocusProxyService service = mock(CarOemAudioFocusProxyService.class); 1873 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(true); 1874 when(mMockCarOemProxyService.getCarOemAudioFocusService()).thenReturn(service); 1875 mCarAudioService.init(); 1876 1877 boolean isEnabled = 1878 mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 1879 1880 expectWithMessage("Oem service enabled with release less than U") 1881 .that(isEnabled).isFalse(); 1882 } 1883 1884 @Test isAudioFeatureEnabled_withEnabledVolumeService()1885 public void isAudioFeatureEnabled_withEnabledVolumeService() { 1886 CarOemAudioVolumeProxyService service = mock(CarOemAudioVolumeProxyService.class); 1887 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(true); 1888 when(mMockCarOemProxyService.getCarOemAudioVolumeService()).thenReturn(service); 1889 mCarAudioService.init(); 1890 1891 boolean isEnabled = 1892 mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 1893 1894 expectWithMessage("Oem service enabled with enabled volume service") 1895 .that(isEnabled).isTrue(); 1896 } 1897 1898 @Test isAudioFeatureEnabled_withEnabledDuckingService()1899 public void isAudioFeatureEnabled_withEnabledDuckingService() { 1900 CarOemAudioDuckingProxyService service = mock(CarOemAudioDuckingProxyService.class); 1901 when(mMockCarOemProxyService.isOemServiceEnabled()).thenReturn(true); 1902 when(mMockCarOemProxyService.getCarOemAudioDuckingService()).thenReturn(service); 1903 mCarAudioService.init(); 1904 1905 boolean isEnabled = 1906 mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_OEM_AUDIO_SERVICE); 1907 1908 expectWithMessage("Oem service enabled with enabled ducking service") 1909 .that(isEnabled).isTrue(); 1910 } 1911 1912 @Test isAudioFeatureEnabled_withEnabledAudioMirror()1913 public void isAudioFeatureEnabled_withEnabledAudioMirror() { 1914 mCarAudioService.init(); 1915 1916 boolean isEnabled = mCarAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_AUDIO_MIRRORING); 1917 1918 expectWithMessage("Audio mirror enabled status") 1919 .that(isEnabled).isTrue(); 1920 } 1921 1922 @Test isAudioFeatureEnabled_withDisabledAudioMirror()1923 public void isAudioFeatureEnabled_withDisabledAudioMirror() { 1924 CarAudioService carAudioService = getCarAudioServiceWithoutMirroring(); 1925 carAudioService.init(); 1926 1927 boolean isEnabled = carAudioService.isAudioFeatureEnabled(AUDIO_FEATURE_AUDIO_MIRRORING); 1928 1929 expectWithMessage("Audio mirror enabled status") 1930 .that(isEnabled).isFalse(); 1931 } 1932 1933 @Test onOccupantZoneConfigChanged_noUserAssignedToPrimaryZone()1934 public void onOccupantZoneConfigChanged_noUserAssignedToPrimaryZone() throws Exception { 1935 mCarAudioService.init(); 1936 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(UserManagerHelper.USER_NULL); 1937 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 1938 .thenReturn(UserManagerHelper.USER_NULL); 1939 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 1940 int prevUserId = mCarAudioService.getUserIdForZone(PRIMARY_AUDIO_ZONE); 1941 1942 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 1943 1944 expectWithMessage("User ID before config changed") 1945 .that(mCarAudioService.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 1946 .isEqualTo(prevUserId); 1947 } 1948 1949 @Test onOccupantZoneConfigChanged_userAssignedToPrimaryZone()1950 public void onOccupantZoneConfigChanged_userAssignedToPrimaryZone() throws Exception { 1951 mCarAudioService.init(); 1952 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 1953 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 1954 .thenReturn(TEST_REAR_LEFT_USER_ID); 1955 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 1956 1957 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 1958 1959 expectWithMessage("User ID after config changed") 1960 .that(mCarAudioService.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 1961 .isEqualTo(TEST_REAR_LEFT_USER_ID); 1962 } 1963 1964 @Test onOccupantZoneConfigChanged_afterResettingUser_returnNoUser()1965 public void onOccupantZoneConfigChanged_afterResettingUser_returnNoUser() throws Exception { 1966 mCarAudioService.init(); 1967 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 1968 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 1969 .thenReturn(TEST_REAR_LEFT_USER_ID); 1970 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 1971 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 1972 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 1973 .thenReturn(UserManagerHelper.USER_NULL); 1974 1975 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 1976 1977 expectWithMessage("User ID config changed to null") 1978 .that(mCarAudioService.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 1979 .isEqualTo(UserManagerHelper.USER_NULL); 1980 } 1981 1982 @Test onOccupantZoneConfigChanged_noOccupantZoneMapping()1983 public void onOccupantZoneConfigChanged_noOccupantZoneMapping() throws Exception { 1984 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1985 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 1986 mCarVolumeCallbackHandler); 1987 noZoneMappingAudioService.init(); 1988 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 1989 1990 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 1991 1992 verify(mMockOccupantZoneService, never()).getUserForOccupant(anyInt()); 1993 } 1994 1995 @Test onOccupantZoneConfigChanged_noOccupantZoneMapping_alreadyAssigned()1996 public void onOccupantZoneConfigChanged_noOccupantZoneMapping_alreadyAssigned() 1997 throws Exception { 1998 CarAudioService noZoneMappingAudioService = new CarAudioService(mMockContext, 1999 mTemporaryAudioConfigurationWithoutZoneMappingFile.getFile().getAbsolutePath(), 2000 mCarVolumeCallbackHandler); 2001 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2002 noZoneMappingAudioService.init(); 2003 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2004 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2005 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2006 2007 verify(mMockOccupantZoneService, never()).getUserForOccupant(anyInt()); 2008 expectWithMessage("Occupant Zone for primary zone") 2009 .that(noZoneMappingAudioService.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2010 .isEqualTo(TEST_DRIVER_USER_ID); 2011 } 2012 2013 @Test onOccupantZoneConfigChanged_multipleZones()2014 public void onOccupantZoneConfigChanged_multipleZones() throws Exception { 2015 mCarAudioService.init(); 2016 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 2017 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 2018 .thenReturn(TEST_REAR_LEFT_USER_ID, TEST_REAR_RIGHT_USER_ID); 2019 ICarOccupantZoneCallback callback = getOccupantZoneCallback(); 2020 2021 callback.onOccupantZoneConfigChanged(CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 2022 2023 expectWithMessage("User ID for primary and secondary zone after config changed") 2024 .that(mCarAudioService.getUserIdForZone(PRIMARY_AUDIO_ZONE)) 2025 .isNotEqualTo(mCarAudioService.getUserIdForZone(TEST_REAR_LEFT_ZONE_ID)); 2026 expectWithMessage("Secondary user ID config changed") 2027 .that(mCarAudioService.getUserIdForZone(TEST_REAR_LEFT_ZONE_ID)) 2028 .isEqualTo(TEST_REAR_RIGHT_USER_ID); 2029 } 2030 2031 @Test serviceDied_registersAudioGainCallback()2032 public void serviceDied_registersAudioGainCallback() { 2033 mCarAudioService.init(); 2034 ArgumentCaptor<AudioControlDeathRecipient> captor = 2035 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2036 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2037 AudioControlDeathRecipient runnable = captor.getValue(); 2038 reset(mAudioControlWrapperAidl); 2039 2040 runnable.serviceDied(); 2041 2042 verify(mAudioControlWrapperAidl).registerAudioGainCallback(any()); 2043 } 2044 2045 @Test serviceDied_registersFocusListener()2046 public void serviceDied_registersFocusListener() { 2047 mCarAudioService.init(); 2048 ArgumentCaptor<AudioControlDeathRecipient> captor = 2049 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2050 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2051 AudioControlDeathRecipient runnable = captor.getValue(); 2052 reset(mAudioControlWrapperAidl); 2053 2054 runnable.serviceDied(); 2055 2056 verify(mAudioControlWrapperAidl).registerFocusListener(any()); 2057 } 2058 2059 @Test serviceDied_setsModuleChangeCallback()2060 public void serviceDied_setsModuleChangeCallback() { 2061 mCarAudioService.init(); 2062 ArgumentCaptor<AudioControlDeathRecipient> captor = 2063 ArgumentCaptor.forClass(AudioControlDeathRecipient.class); 2064 verify(mAudioControlWrapperAidl).linkToDeath(captor.capture()); 2065 AudioControlDeathRecipient runnable = captor.getValue(); 2066 reset(mAudioControlWrapperAidl); 2067 2068 runnable.serviceDied(); 2069 2070 verify(mAudioControlWrapperAidl).setModuleChangeCallback(any()); 2071 } 2072 getOccupantZoneCallback()2073 private ICarOccupantZoneCallback getOccupantZoneCallback() { 2074 ArgumentCaptor<ICarOccupantZoneCallback> captor = 2075 ArgumentCaptor.forClass(ICarOccupantZoneCallback.class); 2076 verify(mMockOccupantZoneService).registerCallback(captor.capture()); 2077 return captor.getValue(); 2078 } 2079 2080 @Test getVolumeGroupIdForAudioContext_forPrimaryGroup()2081 public void getVolumeGroupIdForAudioContext_forPrimaryGroup() { 2082 mCarAudioService.init(); 2083 2084 expectWithMessage("Volume group ID for primary audio zone") 2085 .that(mCarAudioService.getVolumeGroupIdForAudioContext(PRIMARY_AUDIO_ZONE, 2086 CarAudioContext.MUSIC)) 2087 .isEqualTo(TEST_PRIMARY_ZONE_GROUP_0); 2088 } 2089 2090 @Test getVolumeGroupIdForAudioAttribute()2091 public void getVolumeGroupIdForAudioAttribute() { 2092 mCarAudioService.init(); 2093 2094 expectWithMessage("Volume group ID for primary audio zone") 2095 .that(mCarAudioService.getVolumeGroupIdForAudioAttribute(PRIMARY_AUDIO_ZONE, 2096 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA))) 2097 .isEqualTo(TEST_PRIMARY_ZONE_GROUP_0); 2098 } 2099 2100 @Test getVolumeGroupIdForAudioAttribute_withNullAttribute_fails()2101 public void getVolumeGroupIdForAudioAttribute_withNullAttribute_fails() { 2102 mCarAudioService.init(); 2103 2104 NullPointerException thrown = assertThrows(NullPointerException.class, () -> 2105 mCarAudioService.getVolumeGroupIdForAudioAttribute(PRIMARY_AUDIO_ZONE, 2106 /* attribute= */ null)); 2107 2108 expectWithMessage("Null audio attribute exception").that(thrown).hasMessageThat() 2109 .contains("Audio attributes"); 2110 } 2111 2112 @Test getVolumeGroupIdForAudioAttribute_withInvalidZoneId_fails()2113 public void getVolumeGroupIdForAudioAttribute_withInvalidZoneId_fails() { 2114 mCarAudioService.init(); 2115 2116 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> 2117 mCarAudioService.getVolumeGroupIdForAudioAttribute(INVALID_AUDIO_ZONE, 2118 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA))); 2119 2120 expectWithMessage("Invalid audio zone exception").that(thrown).hasMessageThat() 2121 .contains("Invalid audio zone Id"); 2122 } 2123 2124 @Test getInputDevicesForZoneId_primaryZone()2125 public void getInputDevicesForZoneId_primaryZone() { 2126 mCarAudioService.init(); 2127 2128 expectWithMessage("Get input device for primary zone id") 2129 .that(mCarAudioService.getInputDevicesForZoneId(PRIMARY_AUDIO_ZONE)) 2130 .containsExactly(new AudioDeviceAttributes(mMicrophoneInputDevice)); 2131 } 2132 2133 @Test getExternalSources_forSingleDevice()2134 public void getExternalSources_forSingleDevice() { 2135 mCarAudioService.init(); 2136 AudioDeviceInfo[] inputDevices = generateInputDeviceInfos(); 2137 2138 expectWithMessage("External input device addresses") 2139 .that(mCarAudioService.getExternalSources()) 2140 .asList().containsExactly(inputDevices[1].getAddress()); 2141 } 2142 2143 @Test setAudioEnabled_forEnabledVolumeGroupMuting()2144 public void setAudioEnabled_forEnabledVolumeGroupMuting() { 2145 mCarAudioService.init(); 2146 2147 mCarAudioService.setAudioEnabled(/* enabled= */ true); 2148 2149 verify(mAudioControlWrapperAidl).onDevicesToMuteChange(any()); 2150 } 2151 2152 @Test setAudioEnabled_forDisabledVolumeGroupMuting()2153 public void setAudioEnabled_forDisabledVolumeGroupMuting() { 2154 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)).thenReturn(false); 2155 CarAudioService nonVolumeGroupMutingAudioService = new CarAudioService(mMockContext, 2156 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 2157 mCarVolumeCallbackHandler); 2158 nonVolumeGroupMutingAudioService.init(); 2159 2160 nonVolumeGroupMutingAudioService.setAudioEnabled(/* enabled= */ true); 2161 2162 verify(mAudioControlWrapperAidl, never()).onDevicesToMuteChange(any()); 2163 } 2164 2165 @Test registerVolumeCallback_verifyCallbackHandler()2166 public void registerVolumeCallback_verifyCallbackHandler() { 2167 int uid = Binder.getCallingUid(); 2168 mCarAudioService.init(); 2169 2170 mCarAudioService.registerVolumeCallback(mVolumeCallbackBinder); 2171 2172 verify(mCarVolumeCallbackHandler).registerCallback(mVolumeCallbackBinder, uid, true); 2173 } 2174 2175 @Test unregisterVolumeCallback_verifyCallbackHandler()2176 public void unregisterVolumeCallback_verifyCallbackHandler() { 2177 int uid = Binder.getCallingUid(); 2178 mCarAudioService.init(); 2179 2180 mCarAudioService.unregisterVolumeCallback(mVolumeCallbackBinder); 2181 2182 verify(mCarVolumeCallbackHandler).unregisterCallback(mVolumeCallbackBinder, uid); 2183 } 2184 2185 @Test getMutedVolumeGroups_forInvalidZone()2186 public void getMutedVolumeGroups_forInvalidZone() { 2187 mCarAudioService.init(); 2188 2189 expectWithMessage("Muted volume groups for invalid zone") 2190 .that(mCarAudioService.getMutedVolumeGroups(INVALID_AUDIO_ZONE)) 2191 .isEmpty(); 2192 } 2193 2194 @Test getMutedVolumeGroups_whenVolumeGroupMuteNotSupported()2195 public void getMutedVolumeGroups_whenVolumeGroupMuteNotSupported() { 2196 when(mMockResources.getBoolean(audioUseCarVolumeGroupMuting)).thenReturn(false); 2197 CarAudioService nonVolumeGroupMutingAudioService = new CarAudioService(mMockContext, 2198 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 2199 mCarVolumeCallbackHandler); 2200 nonVolumeGroupMutingAudioService.init(); 2201 2202 expectWithMessage("Muted volume groups with disable mute feature") 2203 .that(nonVolumeGroupMutingAudioService.getMutedVolumeGroups(PRIMARY_AUDIO_ZONE)) 2204 .isEmpty(); 2205 } 2206 2207 @Test getMutedVolumeGroups_withMutedGroups()2208 public void getMutedVolumeGroups_withMutedGroups() { 2209 mCarAudioService.init(); 2210 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 2211 /* muted= */ true, TEST_FLAGS); 2212 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1, 2213 /* muted= */ true, TEST_FLAGS); 2214 2215 expectWithMessage("Muted volume groups") 2216 .that(mCarAudioService.getMutedVolumeGroups(PRIMARY_AUDIO_ZONE)) 2217 .containsExactly(TEST_PRIMARY_ZONE_VOLUME_INFO_0, TEST_PRIMARY_ZONE_VOLUME_INFO_1); 2218 } 2219 2220 @Test getMutedVolumeGroups_afterUnmuting()2221 public void getMutedVolumeGroups_afterUnmuting() { 2222 mCarAudioService.init(); 2223 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 2224 /* muted= */ true, TEST_FLAGS); 2225 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1, 2226 /* muted= */ true, TEST_FLAGS); 2227 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 2228 /* muted= */ false, TEST_FLAGS); 2229 2230 expectWithMessage("Muted volume groups after unmuting one group") 2231 .that(mCarAudioService.getMutedVolumeGroups(PRIMARY_AUDIO_ZONE)) 2232 .containsExactly(TEST_PRIMARY_ZONE_VOLUME_INFO_1); 2233 } 2234 2235 @Test getMutedVolumeGroups_withMutedGroupsForDifferentZone()2236 public void getMutedVolumeGroups_withMutedGroupsForDifferentZone() { 2237 mCarAudioService.init(); 2238 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 2239 /* muted= */ true, TEST_FLAGS); 2240 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1, 2241 /* muted= */ true, TEST_FLAGS); 2242 2243 expectWithMessage("Muted volume groups for secondary zone") 2244 .that(mCarAudioService.getMutedVolumeGroups(TEST_REAR_LEFT_ZONE_ID)).isEmpty(); 2245 } 2246 2247 @Test onReceive_forLegacy_noCallToOnVolumeGroupChanged()2248 public void onReceive_forLegacy_noCallToOnVolumeGroupChanged() { 2249 when(mMockResources.getBoolean(audioUseDynamicRouting)) 2250 .thenReturn(false); 2251 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 2252 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 2253 mCarVolumeCallbackHandler); 2254 nonDynamicAudioService.init(); 2255 mVolumeReceiverCaptor = ArgumentCaptor.forClass(BroadcastReceiver.class); 2256 verify(mMockContext).registerReceiver(mVolumeReceiverCaptor.capture(), any(), anyInt()); 2257 BroadcastReceiver receiver = mVolumeReceiverCaptor.getValue(); 2258 Intent intent = new Intent(VOLUME_CHANGED_ACTION); 2259 2260 receiver.onReceive(mMockContext, intent); 2261 2262 verify(mCarVolumeCallbackHandler, never()) 2263 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 2264 } 2265 2266 @Test onReceive_forLegacy_forStreamMusic()2267 public void onReceive_forLegacy_forStreamMusic() { 2268 when(mMockResources.getBoolean(audioUseDynamicRouting)) 2269 .thenReturn(false); 2270 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 2271 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 2272 mCarVolumeCallbackHandler); 2273 nonDynamicAudioService.init(); 2274 verify(mMockContext).registerReceiver(mVolumeReceiverCaptor.capture(), any(), anyInt()); 2275 BroadcastReceiver receiver = mVolumeReceiverCaptor.getValue(); 2276 Intent intent = new Intent(VOLUME_CHANGED_ACTION) 2277 .putExtra(EXTRA_VOLUME_STREAM_TYPE, STREAM_MUSIC); 2278 2279 receiver.onReceive(mMockContext, intent); 2280 2281 verify(mCarVolumeCallbackHandler).onVolumeGroupChange( 2282 eq(PRIMARY_AUDIO_ZONE), anyInt(), eq(FLAG_FROM_KEY | FLAG_SHOW_UI)); 2283 } 2284 2285 @Test onReceive_forLegacy_onMuteChanged()2286 public void onReceive_forLegacy_onMuteChanged() { 2287 when(mMockResources.getBoolean(audioUseDynamicRouting)) 2288 .thenReturn(false); 2289 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 2290 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 2291 mCarVolumeCallbackHandler); 2292 nonDynamicAudioService.init(); 2293 ArgumentCaptor<BroadcastReceiver> captor = 2294 ArgumentCaptor.forClass(BroadcastReceiver.class); 2295 verify(mMockContext).registerReceiver(captor.capture(), any(), anyInt()); 2296 BroadcastReceiver receiver = captor.getValue(); 2297 Intent intent = new Intent(); 2298 intent.setAction(MASTER_MUTE_CHANGED_ACTION); 2299 2300 receiver.onReceive(mMockContext, intent); 2301 2302 verify(mCarVolumeCallbackHandler) 2303 .onMasterMuteChanged(eq(PRIMARY_AUDIO_ZONE), eq(FLAG_FROM_KEY | FLAG_SHOW_UI)); 2304 } 2305 2306 @Test getVolumeGroupInfosForZone()2307 public void getVolumeGroupInfosForZone() { 2308 mCarAudioService.init(); 2309 int groupCount = mCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE); 2310 2311 List<CarVolumeGroupInfo> infos = 2312 mCarAudioService.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 2313 2314 for (int index = 0; index < groupCount; index++) { 2315 CarVolumeGroupInfo info = mCarAudioService 2316 .getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, index); 2317 expectWithMessage("Car volume group infos for primary zone and info %s", info) 2318 .that(infos).contains(info); 2319 } 2320 } 2321 2322 @Test getVolumeGroupInfosForZone_forDynamicRoutingDisabled()2323 public void getVolumeGroupInfosForZone_forDynamicRoutingDisabled() { 2324 when(mMockResources.getBoolean(audioUseDynamicRouting)) 2325 .thenReturn(/* useDynamicRouting= */ false); 2326 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 2327 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 2328 mCarVolumeCallbackHandler); 2329 nonDynamicAudioService.init(); 2330 2331 List<CarVolumeGroupInfo> infos = 2332 nonDynamicAudioService.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 2333 2334 expectWithMessage("Car volume group infos with dynamic routing disabled") 2335 .that(infos).isEmpty(); 2336 } 2337 2338 @Test getVolumeGroupInfosForZone_forOEMConfiguration()2339 public void getVolumeGroupInfosForZone_forOEMConfiguration() { 2340 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 2341 mTemporaryAudioConfigurationWithOEMContexts.getFile().getAbsolutePath(), 2342 mCarVolumeCallbackHandler); 2343 nonDynamicAudioService.init(); 2344 2345 List<CarVolumeGroupInfo> infos = 2346 nonDynamicAudioService.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 2347 2348 expectWithMessage("Car volume group infos size with OEM configuration") 2349 .that(infos).hasSize(1); 2350 expectWithMessage("Car volume group info name with OEM configuration") 2351 .that(infos.get(0).getName()).isEqualTo("OEM_VOLUME_GROUP"); 2352 } 2353 2354 @Test getVolumeGroupInfosForZone_size()2355 public void getVolumeGroupInfosForZone_size() { 2356 mCarAudioService.init(); 2357 int groupCount = mCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE); 2358 2359 List<CarVolumeGroupInfo> infos = 2360 mCarAudioService.getVolumeGroupInfosForZone(PRIMARY_AUDIO_ZONE); 2361 2362 expectWithMessage("Car volume group infos size for primary zone") 2363 .that(infos).hasSize(groupCount); 2364 } 2365 2366 @Test getVolumeGroupInfosForZone_forInvalidZone()2367 public void getVolumeGroupInfosForZone_forInvalidZone() { 2368 mCarAudioService.init(); 2369 2370 IllegalArgumentException thrown = 2371 assertThrows(IllegalArgumentException.class, () -> 2372 mCarAudioService.getVolumeGroupInfosForZone(INVALID_AUDIO_ZONE)); 2373 2374 expectWithMessage("Exception for volume group infos size for invalid zone") 2375 .that(thrown).hasMessageThat().contains("audio zone Id"); 2376 } 2377 2378 @Test getVolumeGroupInfo()2379 public void getVolumeGroupInfo() { 2380 CarVolumeGroupInfo testVolumeGroupInfo = new CarVolumeGroupInfo.Builder( 2381 TEST_PRIMARY_ZONE_VOLUME_INFO_0).setMuted(false).build(); 2382 mCarAudioService.init(); 2383 2384 expectWithMessage("Car volume group info for primary zone") 2385 .that(mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 2386 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(testVolumeGroupInfo); 2387 } 2388 2389 @Test getVolumeGroupInfo_forInvalidZone()2390 public void getVolumeGroupInfo_forInvalidZone() { 2391 mCarAudioService.init(); 2392 2393 IllegalArgumentException thrown = 2394 assertThrows(IllegalArgumentException.class, () -> 2395 mCarAudioService.getVolumeGroupInfo(INVALID_AUDIO_ZONE, 2396 TEST_PRIMARY_ZONE_GROUP_0)); 2397 2398 expectWithMessage("Exception for volume group info size for invalid zone") 2399 .that(thrown).hasMessageThat().contains("audio zone Id"); 2400 } 2401 2402 @Test getVolumeGroupInfo_forInvalidGroup()2403 public void getVolumeGroupInfo_forInvalidGroup() { 2404 mCarAudioService.init(); 2405 2406 IllegalArgumentException thrown = 2407 assertThrows(IllegalArgumentException.class, () -> 2408 mCarAudioService.getVolumeGroupInfo(INVALID_AUDIO_ZONE, 2409 TEST_PRIMARY_ZONE_GROUP_0)); 2410 2411 expectWithMessage("Exception for volume groups info size for invalid group id") 2412 .that(thrown).hasMessageThat().contains("audio zone Id"); 2413 } 2414 2415 @Test getVolumeGroupInfo_forGroupOverRange()2416 public void getVolumeGroupInfo_forGroupOverRange() { 2417 mCarAudioService.init(); 2418 int groupCount = mCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE); 2419 2420 IllegalArgumentException thrown = 2421 assertThrows(IllegalArgumentException.class, () -> 2422 mCarAudioService.getVolumeGroupInfo(INVALID_AUDIO_ZONE, 2423 groupCount)); 2424 2425 expectWithMessage("Exception for volume groups info size for out of range group") 2426 .that(thrown).hasMessageThat().contains("audio zone Id"); 2427 } 2428 2429 @Test registerPrimaryZoneMediaAudioRequestCallbackListener_withNullCallback_fails()2430 public void registerPrimaryZoneMediaAudioRequestCallbackListener_withNullCallback_fails() { 2431 mCarAudioService.init(); 2432 2433 NullPointerException thrown = assertThrows(NullPointerException.class, () 2434 -> mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback( 2435 /* callback= */ null)); 2436 2437 expectWithMessage("Register audio media request callback exception") 2438 .that(thrown).hasMessageThat() 2439 .contains("Media request callback"); 2440 } 2441 2442 @Test unregisterPrimaryZoneMediaAudioRequestCallback_withNullCallback_fails()2443 public void unregisterPrimaryZoneMediaAudioRequestCallback_withNullCallback_fails() { 2444 mCarAudioService.init(); 2445 2446 NullPointerException thrown = assertThrows(NullPointerException.class, () 2447 -> mCarAudioService.unregisterPrimaryZoneMediaAudioRequestCallback( 2448 /* callback= */ null)); 2449 2450 expectWithMessage("Unregister audio media request callback exception") 2451 .that(thrown).hasMessageThat() 2452 .contains("Media request callback"); 2453 } 2454 2455 @Test requestMediaAudioOnPrimaryZone_withPassengerOccupant_succeeds()2456 public void requestMediaAudioOnPrimaryZone_withPassengerOccupant_succeeds() 2457 throws Exception { 2458 mCarAudioService.init(); 2459 TestPrimaryZoneMediaAudioRequestCallback 2460 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2461 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2462 assignOccupantToAudioZones(); 2463 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2464 2465 expectWithMessage("Audio media request id") 2466 .that(mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2467 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 2468 .isNotEqualTo(INVALID_REQUEST_ID); 2469 } 2470 2471 @Test requestMediaAudioOnPrimaryZone_withDriverOccupant_fails()2472 public void requestMediaAudioOnPrimaryZone_withDriverOccupant_fails() 2473 throws Exception { 2474 mCarAudioService.init(); 2475 TestPrimaryZoneMediaAudioRequestCallback 2476 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2477 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2478 assignOccupantToAudioZones(); 2479 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2480 2481 IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () 2482 -> mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2483 TEST_DRIVER_OCCUPANT)); 2484 2485 expectWithMessage("Request media audio exception") 2486 .that(thrown).hasMessageThat().contains("already owns the primary audio zone"); 2487 } 2488 2489 @Test requestMediaAudioOnPrimaryZone_withNonAssignedOccupant_fails()2490 public void requestMediaAudioOnPrimaryZone_withNonAssignedOccupant_fails() 2491 throws Exception { 2492 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_UNASSIGNED_OCCUPANT_ZONE_ID)) 2493 .thenReturn(OUT_OF_RANGE_ZONE); 2494 mCarAudioService.init(); 2495 TestPrimaryZoneMediaAudioRequestCallback 2496 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2497 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2498 CarOccupantZoneManager.OccupantZoneInfo info = 2499 getOccupantInfo(TEST_UNASSIGNED_OCCUPANT_ZONE_ID, 2500 CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER, 2501 VehicleAreaSeat.SEAT_ROW_1_LEFT); 2502 assignOccupantToAudioZones(); 2503 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2504 2505 expectWithMessage("Invalid audio media request id") 2506 .that(mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, info)) 2507 .isEqualTo(INVALID_REQUEST_ID); 2508 } 2509 2510 @Test requestMediaAudioOnPrimaryZone_withPassengerOccupant_callsApprover()2511 public void requestMediaAudioOnPrimaryZone_withPassengerOccupant_callsApprover() 2512 throws Exception { 2513 mCarAudioService.init(); 2514 TestPrimaryZoneMediaAudioRequestCallback 2515 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2516 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2517 assignOccupantToAudioZones(); 2518 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2519 2520 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2521 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2522 2523 requestToken.waitForCallback(); 2524 expectWithMessage("Called audio media request id") 2525 .that(requestToken.mRequestId).isEqualTo(requestId); 2526 expectWithMessage("Called audio media request info") 2527 .that(requestToken.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2528 } 2529 2530 @Test requestMediaAudioOnPrimaryZone_withZoneMirroring_fails()2531 public void requestMediaAudioOnPrimaryZone_withZoneMirroring_fails() 2532 throws Exception { 2533 mCarAudioService.init(); 2534 TestPrimaryZoneMediaAudioRequestCallback 2535 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2536 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2537 assignOccupantToAudioZones(); 2538 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2539 TestAudioZonesMirrorStatusCallbackCallback mirrorCallback = 2540 getAudioZonesMirrorStatusCallback(); 2541 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 2542 mirrorCallback.waitForCallback(); 2543 2544 IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> 2545 mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2546 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)); 2547 2548 expectWithMessage("Request audio share while mirroring exception").that(thrown) 2549 .hasMessageThat().contains("Can not request audio share to primary zone"); 2550 } 2551 2552 @Test binderDied_onMediaRequestApprover_resetsApprovedRequest()2553 public void binderDied_onMediaRequestApprover_resetsApprovedRequest() 2554 throws Exception { 2555 mCarAudioService.init(); 2556 TestPrimaryZoneMediaAudioRequestCallback requestToken = 2557 new TestPrimaryZoneMediaAudioRequestCallback(); 2558 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2559 assignOccupantToAudioZones(); 2560 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2561 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2562 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2563 requestToken.waitForCallback(); 2564 requestToken.reset(); 2565 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allowed= */ true); 2566 requestToken.waitForCallback(); 2567 requestCallback.waitForCallback(); 2568 requestCallback.reset(); 2569 2570 requestToken.mDeathRecipient.binderDied(); 2571 2572 requestCallback.waitForCallback(); 2573 expectWithMessage("Stopped status due to approver's death").that(requestCallback.mStatus) 2574 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 2575 expectWithMessage("Stopped id due to approver's death") 2576 .that(requestCallback.mRequestId).isEqualTo(requestId); 2577 } 2578 2579 @Test allowMediaAudioOnPrimaryZone_withAllowedRequest()2580 public void allowMediaAudioOnPrimaryZone_withAllowedRequest() throws Exception { 2581 mCarAudioService.init(); 2582 TestPrimaryZoneMediaAudioRequestCallback 2583 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2584 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2585 assignOccupantToAudioZones(); 2586 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2587 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2588 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2589 requestToken.waitForCallback(); 2590 2591 boolean results = mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2592 /* allowed= */ true); 2593 2594 expectWithMessage("Allowed audio playback").that(results).isTrue(); 2595 } 2596 2597 @Test allowMediaAudioOnPrimaryZone_whileMirroring_fails()2598 public void allowMediaAudioOnPrimaryZone_whileMirroring_fails() throws Exception { 2599 mCarAudioService.init(); 2600 TestPrimaryZoneMediaAudioRequestCallback 2601 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2602 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2603 assignOccupantToAudioZones(); 2604 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2605 long shareId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2606 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2607 requestToken.waitForCallback(); 2608 TestAudioZonesMirrorStatusCallbackCallback mirrorCallback = 2609 getAudioZonesMirrorStatusCallback(); 2610 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 2611 mirrorCallback.waitForCallback(); 2612 requestCallback.waitForCallback(); 2613 2614 IllegalStateException thrown = 2615 assertThrows(IllegalStateException.class, () -> mCarAudioService 2616 .allowMediaAudioOnPrimaryZone(requestToken, shareId, /* allowed= */ true)); 2617 2618 expectWithMessage("Allow audio share while mirroring exception").that(thrown) 2619 .hasMessageThat().contains("Can not allow audio share to primary zone"); 2620 requestCallback.waitForCallback(); 2621 expectWithMessage("Rejected status due to mirroring").that(requestCallback.mStatus) 2622 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_REJECTED); 2623 expectWithMessage("Rejected id with rejected due to mirroring") 2624 .that(requestCallback.mRequestId).isEqualTo(shareId); 2625 } 2626 2627 @Test allowMediaAudioOnPrimaryZone_withUnallowedRequest()2628 public void allowMediaAudioOnPrimaryZone_withUnallowedRequest() throws Exception { 2629 mCarAudioService.init(); 2630 TestPrimaryZoneMediaAudioRequestCallback 2631 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2632 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2633 assignOccupantToAudioZones(); 2634 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2635 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2636 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2637 requestToken.waitForCallback(); 2638 2639 boolean results = mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2640 /* allowed= */ false); 2641 2642 expectWithMessage("Unallowed audio playback").that(results).isTrue(); 2643 } 2644 2645 @Test allowMediaAudioOnPrimaryZone_withAllowedRequest_callsRequester()2646 public void allowMediaAudioOnPrimaryZone_withAllowedRequest_callsRequester() throws Exception { 2647 mCarAudioService.init(); 2648 TestPrimaryZoneMediaAudioRequestCallback 2649 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2650 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2651 assignOccupantToAudioZones(); 2652 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2653 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2654 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2655 requestToken.waitForCallback(); 2656 2657 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2658 /* allowed= */ true); 2659 2660 requestCallback.waitForCallback(); 2661 expectWithMessage("Media request called audio media request id") 2662 .that(requestCallback.mRequestId).isEqualTo(requestId); 2663 expectWithMessage("Media request called audio media request info") 2664 .that(requestCallback.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2665 expectWithMessage("Media request called audio media request status") 2666 .that(requestCallback.mStatus) 2667 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 2668 } 2669 2670 @Test allowMediaAudioOnPrimaryZone_withAllowedRequest_callsApprover()2671 public void allowMediaAudioOnPrimaryZone_withAllowedRequest_callsApprover() throws Exception { 2672 mCarAudioService.init(); 2673 TestPrimaryZoneMediaAudioRequestCallback 2674 requestApprover = new TestPrimaryZoneMediaAudioRequestCallback(); 2675 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2676 assignOccupantToAudioZones(); 2677 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestApprover); 2678 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2679 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2680 requestApprover.waitForCallback(); 2681 requestApprover.reset(); 2682 2683 mCarAudioService.allowMediaAudioOnPrimaryZone(requestApprover, requestId, 2684 /* allowed= */ true); 2685 2686 requestApprover.waitForCallback(); 2687 expectWithMessage("Media approver called audio media request id") 2688 .that(requestApprover.mRequestId).isEqualTo(requestId); 2689 expectWithMessage("Media approver called audio media request info") 2690 .that(requestApprover.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2691 expectWithMessage("Media approver called audio media request status") 2692 .that(requestApprover.mStatus) 2693 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 2694 } 2695 2696 @Test allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsRequester()2697 public void allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsRequester() 2698 throws Exception { 2699 mCarAudioService.init(); 2700 TestPrimaryZoneMediaAudioRequestCallback 2701 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2702 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2703 assignOccupantToAudioZones(); 2704 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2705 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2706 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2707 requestToken.waitForCallback(); 2708 2709 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2710 /* allowed= */ false); 2711 2712 requestCallback.waitForCallback(); 2713 expectWithMessage("Unallowed media request called audio media request id") 2714 .that(requestCallback.mRequestId).isEqualTo(requestId); 2715 expectWithMessage("Unallowed media request called audio media request info") 2716 .that(requestCallback.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2717 expectWithMessage("Unallowed media request called audio media request status") 2718 .that(requestCallback.mStatus) 2719 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_REJECTED); 2720 } 2721 2722 @Test allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsApprover()2723 public void allowMediaAudioOnPrimaryZone_withUnallowedRequest_callsApprover() throws Exception { 2724 mCarAudioService.init(); 2725 TestPrimaryZoneMediaAudioRequestCallback 2726 requestApprover = new TestPrimaryZoneMediaAudioRequestCallback(); 2727 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2728 assignOccupantToAudioZones(); 2729 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestApprover); 2730 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2731 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2732 requestApprover.waitForCallback(); 2733 requestApprover.reset(); 2734 2735 mCarAudioService.allowMediaAudioOnPrimaryZone(requestApprover, requestId, 2736 /* allowed= */ false); 2737 2738 requestApprover.waitForCallback(); 2739 expectWithMessage("Unallowed media approver called audio media request id") 2740 .that(requestApprover.mRequestId).isEqualTo(requestId); 2741 expectWithMessage("Unallowed approver token called audio media request info") 2742 .that(requestApprover.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2743 expectWithMessage("Unallowed approver token called audio media request status") 2744 .that(requestApprover.mStatus) 2745 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_REJECTED); 2746 } 2747 2748 @Test isMediaAudioAllowedInPrimaryZone_witNullOccupant_fails()2749 public void isMediaAudioAllowedInPrimaryZone_witNullOccupant_fails() throws Exception { 2750 mCarAudioService.init(); 2751 NullPointerException thrown = assertThrows(NullPointerException.class, () 2752 -> mCarAudioService.isMediaAudioAllowedInPrimaryZone(/* occupantZoneInfo= */ null)); 2753 2754 expectWithMessage("Media status exception").that(thrown) 2755 .hasMessageThat().contains("Occupant zone info"); 2756 } 2757 2758 @Test isMediaAudioAllowedInPrimaryZone_byDefault()2759 public void isMediaAudioAllowedInPrimaryZone_byDefault() throws Exception { 2760 mCarAudioService.init(); 2761 2762 expectWithMessage("Media default status") 2763 .that(mCarAudioService.isMediaAudioAllowedInPrimaryZone( 2764 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 2765 .isFalse(); 2766 } 2767 2768 @Test isMediaAudioAllowedInPrimaryZone_afterAllowed()2769 public void isMediaAudioAllowedInPrimaryZone_afterAllowed() throws Exception { 2770 mCarAudioService.init(); 2771 TestPrimaryZoneMediaAudioRequestCallback 2772 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2773 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2774 assignOccupantToAudioZones(); 2775 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2776 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2777 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2778 requestToken.waitForCallback(); 2779 requestToken.reset(); 2780 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2781 /* allowed= */ true); 2782 requestToken.waitForCallback(); 2783 2784 expectWithMessage("Media allowed status") 2785 .that(mCarAudioService.isMediaAudioAllowedInPrimaryZone( 2786 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 2787 .isTrue(); 2788 } 2789 2790 @Test isMediaAudioAllowedInPrimaryZone_afterDisallowed()2791 public void isMediaAudioAllowedInPrimaryZone_afterDisallowed() throws Exception { 2792 mCarAudioService.init(); 2793 TestPrimaryZoneMediaAudioRequestCallback 2794 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2795 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2796 assignOccupantToAudioZones(); 2797 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2798 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2799 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2800 requestToken.waitForCallback(); 2801 requestToken.reset(); 2802 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2803 /* allowed= */ false); 2804 requestToken.waitForCallback(); 2805 2806 expectWithMessage("Media after disallowed status") 2807 .that(mCarAudioService.isMediaAudioAllowedInPrimaryZone( 2808 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 2809 .isFalse(); 2810 } 2811 2812 @Test isMediaAudioAllowedInPrimaryZone_afterUserLogout()2813 public void isMediaAudioAllowedInPrimaryZone_afterUserLogout() throws Exception { 2814 mCarAudioService.init(); 2815 TestPrimaryZoneMediaAudioRequestCallback 2816 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2817 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2818 assignOccupantToAudioZones(); 2819 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2820 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2821 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2822 requestToken.waitForCallback(); 2823 requestToken.reset(); 2824 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allowed= */ true); 2825 requestToken.waitForCallback(); 2826 requestToken.reset(); 2827 simulateLogoutPassengers(); 2828 requestToken.waitForCallback(); 2829 2830 expectWithMessage("Media allowed status after passenger logout") 2831 .that(mCarAudioService.isMediaAudioAllowedInPrimaryZone( 2832 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)).isFalse(); 2833 } 2834 2835 @Test isMediaAudioAllowedInPrimaryZone_afterUserSwitch()2836 public void isMediaAudioAllowedInPrimaryZone_afterUserSwitch() throws Exception { 2837 mCarAudioService.init(); 2838 TestPrimaryZoneMediaAudioRequestCallback 2839 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2840 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2841 assignOccupantToAudioZones(); 2842 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2843 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2844 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2845 requestToken.waitForCallback(); 2846 requestToken.reset(); 2847 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2848 /* allowed= */ true); 2849 requestToken.waitForCallback(); 2850 requestToken.reset(); 2851 simulatePassengersSwitch(); 2852 requestToken.waitForCallback(); 2853 2854 expectWithMessage("Media allowed status after passenger switch") 2855 .that(mCarAudioService.isMediaAudioAllowedInPrimaryZone( 2856 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)).isFalse(); 2857 } 2858 2859 @Test resetMediaAudioOnPrimaryZone_afterAllowed()2860 public void resetMediaAudioOnPrimaryZone_afterAllowed() throws Exception { 2861 mCarAudioService.init(); 2862 TestPrimaryZoneMediaAudioRequestCallback 2863 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2864 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2865 assignOccupantToAudioZones(); 2866 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2867 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2868 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2869 requestToken.waitForCallback(); 2870 requestToken.reset(); 2871 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2872 /* allowed= */ true); 2873 requestToken.waitForCallback(); 2874 requestToken.reset(); 2875 2876 boolean reset = mCarAudioService.resetMediaAudioOnPrimaryZone( 2877 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2878 2879 requestToken.waitForCallback(); 2880 expectWithMessage("Reset status").that(reset).isTrue(); 2881 expectWithMessage("Media reset status") 2882 .that(mCarAudioService.isMediaAudioAllowedInPrimaryZone( 2883 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 2884 .isFalse(); 2885 } 2886 2887 @Test cancelMediaAudioOnPrimaryZone_beforeAllowed()2888 public void cancelMediaAudioOnPrimaryZone_beforeAllowed() throws Exception { 2889 mCarAudioService.init(); 2890 TestPrimaryZoneMediaAudioRequestCallback 2891 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2892 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2893 assignOccupantToAudioZones(); 2894 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2895 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2896 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2897 requestToken.waitForCallback(); 2898 requestToken.reset(); 2899 2900 boolean cancel = mCarAudioService.cancelMediaAudioOnPrimaryZone(requestId); 2901 2902 requestToken.waitForCallback(); 2903 expectWithMessage("Cancel status").that(cancel).isTrue(); 2904 expectWithMessage("Canceled media token called audio media request id") 2905 .that(requestToken.mRequestId).isEqualTo(requestId); 2906 expectWithMessage("Canceled media token called audio media request info") 2907 .that(requestToken.mInfo).isEqualTo(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2908 expectWithMessage("Canceled media token called audio media request status") 2909 .that(requestToken.mStatus) 2910 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_CANCELLED); 2911 } 2912 2913 @Test cancelMediaAudioOnPrimaryZone_afterAllowed()2914 public void cancelMediaAudioOnPrimaryZone_afterAllowed() throws Exception { 2915 mCarAudioService.init(); 2916 TestPrimaryZoneMediaAudioRequestCallback 2917 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2918 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2919 assignOccupantToAudioZones(); 2920 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2921 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2922 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2923 requestToken.waitForCallback(); 2924 requestToken.reset(); 2925 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2926 /* allowed= */ true); 2927 requestToken.waitForCallback(); 2928 requestToken.reset(); 2929 2930 boolean cancel = mCarAudioService.cancelMediaAudioOnPrimaryZone(requestId); 2931 2932 requestToken.waitForCallback(); 2933 expectWithMessage("Cancel status after allowed").that(cancel).isTrue(); 2934 expectWithMessage("Media allowed status after canceled") 2935 .that(mCarAudioService.isMediaAudioAllowedInPrimaryZone( 2936 TEST_REAR_RIGHT_PASSENGER_OCCUPANT)) 2937 .isFalse(); 2938 } 2939 2940 @Test getZoneIdForAudioFocusInfo_beforeAllowedSharedAudio()2941 public void getZoneIdForAudioFocusInfo_beforeAllowedSharedAudio() throws Exception { 2942 mCarAudioService.init(); 2943 TestPrimaryZoneMediaAudioRequestCallback 2944 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2945 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2946 assignOccupantToAudioZones(); 2947 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2948 mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2949 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2950 requestToken.waitForCallback(); 2951 2952 expectWithMessage("Not yet shared media user zone") 2953 .that(mCarAudioService.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 2954 .isEqualTo(TEST_REAR_RIGHT_ZONE_ID); 2955 } 2956 2957 @Test getZoneIdForAudioFocusInfo_afterAllowedShareAudio()2958 public void getZoneIdForAudioFocusInfo_afterAllowedShareAudio() throws Exception { 2959 mCarAudioService.init(); 2960 TestPrimaryZoneMediaAudioRequestCallback 2961 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2962 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2963 assignOccupantToAudioZones(); 2964 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2965 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2966 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2967 requestToken.waitForCallback(); 2968 requestToken.reset(); 2969 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allowed= */ true); 2970 requestToken.waitForCallback(); 2971 2972 expectWithMessage("Shared media user zone") 2973 .that(mCarAudioService.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 2974 .isEqualTo(PRIMARY_AUDIO_ZONE); 2975 } 2976 2977 @Test getZoneIdForAudioFocusInfo_afterCanceled()2978 public void getZoneIdForAudioFocusInfo_afterCanceled() throws Exception { 2979 mCarAudioService.init(); 2980 TestPrimaryZoneMediaAudioRequestCallback 2981 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 2982 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 2983 assignOccupantToAudioZones(); 2984 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 2985 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 2986 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 2987 requestToken.waitForCallback(); 2988 requestToken.reset(); 2989 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 2990 /* allowed= */ true); 2991 requestToken.waitForCallback(); 2992 requestToken.reset(); 2993 mCarAudioService.cancelMediaAudioOnPrimaryZone(requestId); 2994 requestToken.waitForCallback(); 2995 2996 expectWithMessage("Canceled shared media user zone") 2997 .that(mCarAudioService.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 2998 .isEqualTo(TEST_REAR_RIGHT_ZONE_ID); 2999 } 3000 3001 @Test getZoneIdForAudioFocusInfo_afterReset()3002 public void getZoneIdForAudioFocusInfo_afterReset() throws Exception { 3003 mCarAudioService.init(); 3004 TestPrimaryZoneMediaAudioRequestCallback 3005 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3006 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3007 assignOccupantToAudioZones(); 3008 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3009 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 3010 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3011 requestToken.waitForCallback(); 3012 requestToken.reset(); 3013 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, 3014 /* allowed= */ true); 3015 requestToken.waitForCallback(); 3016 requestToken.reset(); 3017 mCarAudioService.resetMediaAudioOnPrimaryZone(TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3018 requestToken.waitForCallback(); 3019 3020 expectWithMessage("Reset shared media user zone") 3021 .that(mCarAudioService.getZoneIdForAudioFocusInfo(TEST_REAR_RIGHT_AUDIO_FOCUS_INFO)) 3022 .isEqualTo(TEST_REAR_RIGHT_ZONE_ID); 3023 } 3024 getOccupantInfo(int occupantZoneId, int occupantType, int seat)3025 private static CarOccupantZoneManager.OccupantZoneInfo getOccupantInfo(int occupantZoneId, 3026 int occupantType, int seat) { 3027 return new CarOccupantZoneManager.OccupantZoneInfo(occupantZoneId, occupantType, seat); 3028 } 3029 3030 @Test getAudioAttributesForVolumeGroup()3031 public void getAudioAttributesForVolumeGroup() { 3032 mCarAudioService.init(); 3033 CarVolumeGroupInfo info = mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 3034 TEST_PRIMARY_ZONE_GROUP_0); 3035 3036 List<AudioAttributes> audioAttributes = 3037 mCarAudioService.getAudioAttributesForVolumeGroup(info); 3038 3039 expectWithMessage("Volume group audio attributes").that(audioAttributes) 3040 .containsExactly( 3041 CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA), 3042 CarAudioContext.getAudioAttributeFromUsage(USAGE_GAME), 3043 CarAudioContext.getAudioAttributeFromUsage(USAGE_UNKNOWN), 3044 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION), 3045 CarAudioContext.getAudioAttributeFromUsage(USAGE_NOTIFICATION_EVENT), 3046 CarAudioContext.getAudioAttributeFromUsage(USAGE_ANNOUNCEMENT)); 3047 } 3048 3049 @Test getAudioAttributesForVolumeGroup_withNullInfo_fails()3050 public void getAudioAttributesForVolumeGroup_withNullInfo_fails() { 3051 mCarAudioService.init(); 3052 3053 NullPointerException thrown = 3054 assertThrows(NullPointerException.class, () -> 3055 mCarAudioService.getAudioAttributesForVolumeGroup(/* groupInfo= */ null)); 3056 3057 expectWithMessage("Volume group audio attributes with null info exception") 3058 .that(thrown).hasMessageThat().contains("Car volume group info"); 3059 } 3060 3061 @Test getAudioAttributesForVolumeGroup_withDynamicRoutingDisabled()3062 public void getAudioAttributesForVolumeGroup_withDynamicRoutingDisabled() { 3063 when(mMockResources.getBoolean(audioUseDynamicRouting)) 3064 .thenReturn(/* useDynamicRouting= */ false); 3065 CarAudioService nonDynamicAudioService = new CarAudioService(mMockContext, 3066 mTemporaryAudioConfigurationFile.getFile().getAbsolutePath(), 3067 mCarVolumeCallbackHandler); 3068 nonDynamicAudioService.init(); 3069 3070 List<AudioAttributes> audioAttributes = nonDynamicAudioService 3071 .getAudioAttributesForVolumeGroup(TEST_PRIMARY_ZONE_VOLUME_INFO_0); 3072 3073 expectWithMessage("Volume group audio attributes with dynamic routing disabled") 3074 .that(audioAttributes).isEmpty(); 3075 } 3076 3077 @Test onKeyEvent_forInvalidAudioZone()3078 public void onKeyEvent_forInvalidAudioZone() { 3079 mCarAudioService.init(); 3080 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3081 TEST_PRIMARY_ZONE_GROUP_0); 3082 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3083 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3084 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3085 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3086 .thenReturn(INVALID_AUDIO_ZONE); 3087 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_UNKNOWN); 3088 3089 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3090 3091 expectWithMessage("Volume group volume after invalid audio zone") 3092 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3093 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 3094 } 3095 3096 @Test onKeyEvent_forInvalidEvent()3097 public void onKeyEvent_forInvalidEvent() { 3098 mCarAudioService.init(); 3099 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3100 TEST_PRIMARY_ZONE_GROUP_0); 3101 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3102 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3103 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3104 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3105 .thenReturn(PRIMARY_AUDIO_ZONE); 3106 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_UNKNOWN); 3107 3108 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3109 3110 expectWithMessage("Volume group volume after unknown key event") 3111 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3112 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 3113 } 3114 3115 @Test onKeyEvent_forActionUp()3116 public void onKeyEvent_forActionUp() { 3117 mCarAudioService.init(); 3118 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3119 TEST_PRIMARY_ZONE_GROUP_0); 3120 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3121 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3122 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3123 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3124 .thenReturn(PRIMARY_AUDIO_ZONE); 3125 KeyEvent keyEvent = new KeyEvent(ACTION_UP, KEYCODE_VOLUME_UP); 3126 3127 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3128 3129 expectWithMessage("Volume group volume after volume up in primary zone in primary group " 3130 + "for action up") 3131 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3132 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 3133 } 3134 3135 @Test onKeyEvent_forActionDownFollowedByActionUp()3136 public void onKeyEvent_forActionDownFollowedByActionUp() { 3137 mCarAudioService.init(); 3138 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3139 TEST_PRIMARY_ZONE_GROUP_0); 3140 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3141 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3142 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3143 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3144 .thenReturn(PRIMARY_AUDIO_ZONE); 3145 KeyEvent actionDownKeyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 3146 KeyEvent actionUpKeyEvent = new KeyEvent(ACTION_UP, KEYCODE_VOLUME_UP); 3147 listener.onKeyEvent(actionDownKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3148 3149 listener.onKeyEvent(actionUpKeyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3150 3151 expectWithMessage("Volume group volume after volume up in primary zone in primary group " 3152 + "for action down then action up") 3153 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3154 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore + 1); 3155 } 3156 3157 @Test onKeyEvent_forVolumeUpEvent_inPrimaryZone()3158 public void onKeyEvent_forVolumeUpEvent_inPrimaryZone() { 3159 mCarAudioService.init(); 3160 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3161 TEST_PRIMARY_ZONE_GROUP_0); 3162 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3163 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3164 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3165 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3166 .thenReturn(PRIMARY_AUDIO_ZONE); 3167 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 3168 3169 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3170 3171 expectWithMessage("Volume group volume after volume up in primary zone in primary group") 3172 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3173 TEST_PRIMARY_ZONE_GROUP_0)).isGreaterThan(volumeBefore); 3174 } 3175 3176 @Test onKeyEvent_forVolumeDownEvent_inPrimaryZone()3177 public void onKeyEvent_forVolumeDownEvent_inPrimaryZone() { 3178 mCarAudioService.init(); 3179 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3180 TEST_PRIMARY_ZONE_GROUP_0); 3181 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3182 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3183 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3184 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3185 .thenReturn(PRIMARY_AUDIO_ZONE); 3186 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 3187 3188 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3189 3190 expectWithMessage("Volume group volume after volume down in primary zone in primary group") 3191 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3192 TEST_PRIMARY_ZONE_GROUP_0)).isLessThan(volumeBefore); 3193 } 3194 3195 @Test onKeyEvent_forVolumeDownEvent_inPrimaryZone_forSecondaryGroup()3196 public void onKeyEvent_forVolumeDownEvent_inPrimaryZone_forSecondaryGroup() { 3197 mCarAudioService.init(); 3198 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3199 TEST_PRIMARY_ZONE_GROUP_1); 3200 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 3201 callback.onPlaybackConfigChanged(List.of(new AudioPlaybackConfigurationBuilder() 3202 .setUsage(USAGE_ASSISTANT) 3203 .setDeviceAddress(VOICE_TEST_DEVICE) 3204 .build()) 3205 ); 3206 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3207 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3208 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3209 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3210 .thenReturn(PRIMARY_AUDIO_ZONE); 3211 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 3212 3213 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3214 3215 expectWithMessage("Assistant volume group volume after volume down") 3216 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3217 TEST_PRIMARY_ZONE_GROUP_1)).isLessThan(volumeBefore); 3218 } 3219 3220 @Test onKeyEvent_forVolumeDownEvent_inPrimaryZone_withHigherPriority()3221 public void onKeyEvent_forVolumeDownEvent_inPrimaryZone_withHigherPriority() { 3222 mCarAudioService.init(); 3223 int primaryGroupVolumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3224 TEST_PRIMARY_ZONE_GROUP_0); 3225 int voiceVolumeGroupBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3226 TEST_PRIMARY_ZONE_GROUP_2); 3227 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 3228 callback.onPlaybackConfigChanged(List.of( 3229 new AudioPlaybackConfigurationBuilder() 3230 .setUsage(USAGE_VOICE_COMMUNICATION) 3231 .setDeviceAddress(CALL_TEST_DEVICE) 3232 .build(), 3233 new AudioPlaybackConfigurationBuilder() 3234 .setUsage(USAGE_MEDIA) 3235 .setDeviceAddress(MEDIA_TEST_DEVICE) 3236 .build()) 3237 ); 3238 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3239 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3240 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3241 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3242 .thenReturn(PRIMARY_AUDIO_ZONE); 3243 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 3244 3245 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3246 3247 expectWithMessage("Media volume group volume after volume down") 3248 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3249 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(primaryGroupVolumeBefore); 3250 expectWithMessage("Call volume group volume after volume do") 3251 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3252 TEST_PRIMARY_ZONE_GROUP_2)).isLessThan(voiceVolumeGroupBefore); 3253 } 3254 3255 @Test onKeyEvent_forVolumeMuteEvent_inPrimaryZone()3256 public void onKeyEvent_forVolumeMuteEvent_inPrimaryZone() { 3257 mCarAudioService.init(); 3258 boolean muteBefore = mCarAudioService.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 3259 TEST_PRIMARY_ZONE_GROUP_0); 3260 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3261 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3262 .thenReturn(PRIMARY_OCCUPANT_ZONE); 3263 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(PRIMARY_OCCUPANT_ZONE)) 3264 .thenReturn(PRIMARY_AUDIO_ZONE); 3265 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_MUTE); 3266 3267 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3268 3269 expectWithMessage("Volume group volume after volume mute") 3270 .that(mCarAudioService.isVolumeGroupMuted(PRIMARY_AUDIO_ZONE, 3271 TEST_PRIMARY_ZONE_GROUP_0)).isNotEqualTo(muteBefore); 3272 } 3273 3274 @Test onKeyEvent_forVolumeUpEvent_inSecondaryZone()3275 public void onKeyEvent_forVolumeUpEvent_inSecondaryZone() { 3276 mCarAudioService.init(); 3277 int volumeBefore = mCarAudioService.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 3278 SECONDARY_ZONE_VOLUME_GROUP_ID); 3279 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3280 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3281 .thenReturn(TEST_DRIVER_OCCUPANT_ZONE_ID); 3282 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 3283 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 3284 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_UP); 3285 3286 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3287 3288 expectWithMessage("Secondary zone volume group after volume up") 3289 .that(mCarAudioService.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 3290 SECONDARY_ZONE_VOLUME_GROUP_ID)) 3291 .isGreaterThan(volumeBefore); 3292 } 3293 3294 @Test onKeyEvent_forVolumeDownEvent_inSecondaryZone()3295 public void onKeyEvent_forVolumeDownEvent_inSecondaryZone() { 3296 mCarAudioService.init(); 3297 int volumeBefore = mCarAudioService.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 3298 SECONDARY_ZONE_VOLUME_GROUP_ID); 3299 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3300 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3301 .thenReturn(TEST_DRIVER_OCCUPANT_ZONE_ID); 3302 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 3303 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 3304 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_DOWN); 3305 3306 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3307 3308 expectWithMessage("Secondary zone volume group after volume down") 3309 .that(mCarAudioService.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 3310 SECONDARY_ZONE_VOLUME_GROUP_ID)) 3311 .isLessThan(volumeBefore); 3312 } 3313 3314 @Test onKeyEvent_forVolumeMuteEvent_inSecondaryZone()3315 public void onKeyEvent_forVolumeMuteEvent_inSecondaryZone() { 3316 mCarAudioService.init(); 3317 boolean muteBefore = mCarAudioService.isVolumeGroupMuted(TEST_REAR_LEFT_ZONE_ID, 3318 SECONDARY_ZONE_VOLUME_GROUP_ID); 3319 CarInputService.KeyEventListener listener = getAudioKeyEventListener(); 3320 when(mMockOccupantZoneService.getOccupantZoneIdForSeat(TEST_SEAT)) 3321 .thenReturn(TEST_DRIVER_OCCUPANT_ZONE_ID); 3322 when(mMockOccupantZoneService.getAudioZoneIdForOccupant(TEST_DRIVER_OCCUPANT_ZONE_ID)) 3323 .thenReturn(TEST_REAR_LEFT_ZONE_ID); 3324 KeyEvent keyEvent = new KeyEvent(ACTION_DOWN, KEYCODE_VOLUME_MUTE); 3325 3326 listener.onKeyEvent(keyEvent, TEST_DISPLAY_TYPE, TEST_SEAT); 3327 3328 expectWithMessage("Secondary zone volume group after volume mute") 3329 .that(mCarAudioService.isVolumeGroupMuted(TEST_REAR_LEFT_ZONE_ID, 3330 SECONDARY_ZONE_VOLUME_GROUP_ID)) 3331 .isNotEqualTo(muteBefore); 3332 } 3333 3334 @Test onAudioDeviceGainsChanged_forPrimaryZone_changesVolume()3335 public void onAudioDeviceGainsChanged_forPrimaryZone_changesVolume() { 3336 mCarAudioService.init(); 3337 HalAudioGainCallback callback = getHalAudioGainCallback(); 3338 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(PRIMARY_AUDIO_ZONE, 3339 MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 3340 3341 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), List.of(carGain)); 3342 3343 expectWithMessage("New audio gains for primary zone") 3344 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3345 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 3346 } 3347 3348 @Test onAudioDeviceGainsChanged_forSecondaryZone_changesVolume()3349 public void onAudioDeviceGainsChanged_forSecondaryZone_changesVolume() { 3350 mCarAudioService.init(); 3351 HalAudioGainCallback callback = getHalAudioGainCallback(); 3352 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(TEST_REAR_LEFT_ZONE_ID, 3353 SECONDARY_TEST_DEVICE_CONFIG_0, TEST_GAIN_INDEX); 3354 3355 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), List.of(carGain)); 3356 3357 expectWithMessage("New audio gains for secondary zone") 3358 .that(mCarAudioService.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 3359 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 3360 } 3361 3362 @Test onAudioDeviceGainsChanged_forIncorrectDeviceAddress_sameVolume()3363 public void onAudioDeviceGainsChanged_forIncorrectDeviceAddress_sameVolume() { 3364 mCarAudioService.init(); 3365 HalAudioGainCallback callback = getHalAudioGainCallback(); 3366 int volumeBefore = mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3367 TEST_PRIMARY_ZONE_GROUP_0); 3368 CarAudioGainConfigInfo carGain = createCarAudioGainConfigInfo(PRIMARY_AUDIO_ZONE, 3369 SECONDARY_TEST_DEVICE_CONFIG_0, TEST_GAIN_INDEX); 3370 3371 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), List.of(carGain)); 3372 3373 expectWithMessage("Same audio gains for primary zone") 3374 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3375 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(volumeBefore); 3376 } 3377 3378 @Test onAudioDeviceGainsChanged_forMultipleZones_changesVolume()3379 public void onAudioDeviceGainsChanged_forMultipleZones_changesVolume() { 3380 mCarAudioService.init(); 3381 HalAudioGainCallback callback = getHalAudioGainCallback(); 3382 CarAudioGainConfigInfo primaryAudioZoneCarGain = createCarAudioGainConfigInfo( 3383 PRIMARY_AUDIO_ZONE, MEDIA_TEST_DEVICE, TEST_GAIN_INDEX); 3384 CarAudioGainConfigInfo secondaryAudioZoneCarGain = createCarAudioGainConfigInfo( 3385 TEST_REAR_LEFT_ZONE_ID, SECONDARY_TEST_DEVICE_CONFIG_0, TEST_GAIN_INDEX); 3386 3387 callback.onAudioDeviceGainsChanged(List.of(Reasons.THERMAL_LIMITATION), 3388 List.of(primaryAudioZoneCarGain, secondaryAudioZoneCarGain)); 3389 3390 expectWithMessage("New audio gains for primary zone") 3391 .that(mCarAudioService.getGroupVolume(PRIMARY_AUDIO_ZONE, 3392 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 3393 expectWithMessage("New audio gains for secondary zone") 3394 .that(mCarAudioService.getGroupVolume(TEST_REAR_LEFT_ZONE_ID, 3395 TEST_PRIMARY_ZONE_GROUP_0)).isEqualTo(TEST_GAIN_INDEX); 3396 } 3397 3398 @Test onAudioPortsChanged_forMediaBus_changesVolumeRanges()3399 public void onAudioPortsChanged_forMediaBus_changesVolumeRanges() { 3400 mCarAudioService.init(); 3401 HalAudioModuleChangeCallback callback = getHalModuleChangeCallback(); 3402 HalAudioDeviceInfo mediaBusDeviceInfo = createHalAudioDeviceInfo( 3403 TEST_MEDIA_PORT_ID, TEST_MEDIA_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 3404 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, MEDIA_TEST_DEVICE); 3405 CarVolumeGroupInfo volumeGroupInfoBefore = 3406 mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 3407 3408 callback.onAudioPortsChanged(List.of(mediaBusDeviceInfo)); 3409 3410 expectWithMessage("update audio port for media device") 3411 .that(mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 3412 TEST_PRIMARY_ZONE_GROUP_0)).isNotEqualTo(volumeGroupInfoBefore); 3413 } 3414 3415 @Test onAudioPortsChanged_forNavBus_changesVolumeRanges()3416 public void onAudioPortsChanged_forNavBus_changesVolumeRanges() { 3417 mCarAudioService.init(); 3418 HalAudioModuleChangeCallback callback = getHalModuleChangeCallback(); 3419 HalAudioDeviceInfo navBusDeviceInfo = createHalAudioDeviceInfo( 3420 TEST_NAV_PORT_ID, TEST_NAV_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 3421 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, NAVIGATION_TEST_DEVICE); 3422 CarVolumeGroupInfo volumeGroupInfoBefore = 3423 mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1); 3424 3425 callback.onAudioPortsChanged(List.of(navBusDeviceInfo)); 3426 3427 expectWithMessage("update audio port for nav device") 3428 .that(mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 3429 TEST_PRIMARY_ZONE_GROUP_1)).isNotEqualTo(volumeGroupInfoBefore); 3430 } 3431 3432 @Test onAudioPortsChanged_forMultipleBuses_changesVolumeRanges()3433 public void onAudioPortsChanged_forMultipleBuses_changesVolumeRanges() { 3434 mCarAudioService.init(); 3435 HalAudioModuleChangeCallback callback = getHalModuleChangeCallback(); 3436 HalAudioDeviceInfo mediaBusDeviceInfo = createHalAudioDeviceInfo( 3437 TEST_MEDIA_PORT_ID, TEST_MEDIA_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 3438 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, MEDIA_TEST_DEVICE); 3439 HalAudioDeviceInfo navBusDeviceInfo = createHalAudioDeviceInfo( 3440 TEST_NAV_PORT_ID, TEST_NAV_PORT_NAME, TEST_GAIN_MIN_VALUE, TEST_GAIN_MAX_VALUE, 3441 TEST_GAIN_DEFAULT_VALUE, TEST_GAIN_STEP_VALUE, OUT_DEVICE, NAVIGATION_TEST_DEVICE); 3442 CarVolumeGroupInfo mediaVolumeGroupInfoBefore = 3443 mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0); 3444 CarVolumeGroupInfo navVolumeGroupInfoBefore = 3445 mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_1); 3446 3447 callback.onAudioPortsChanged(List.of(mediaBusDeviceInfo, navBusDeviceInfo)); 3448 3449 expectWithMessage("update audio port for media device") 3450 .that(mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 3451 TEST_PRIMARY_ZONE_GROUP_0)).isNotEqualTo(mediaVolumeGroupInfoBefore); 3452 expectWithMessage("update audio port for nav device") 3453 .that(mCarAudioService.getVolumeGroupInfo(PRIMARY_AUDIO_ZONE, 3454 TEST_PRIMARY_ZONE_GROUP_1)).isNotEqualTo(navVolumeGroupInfoBefore); 3455 } 3456 3457 @Test getActiveAudioAttributesForZone()3458 public void getActiveAudioAttributesForZone() { 3459 mCarAudioService.init(); 3460 3461 expectWithMessage("Default active audio attributes").that( 3462 mCarAudioService.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)).isEmpty(); 3463 } 3464 3465 @Test getActiveAudioAttributesForZone_withActiveHalFocus()3466 public void getActiveAudioAttributesForZone_withActiveHalFocus() { 3467 when(mAudioManager.requestAudioFocus(any())).thenReturn( 3468 AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 3469 mCarAudioService.init(); 3470 requestHalAudioFocus(USAGE_ALARM); 3471 3472 expectWithMessage("HAL active audio attributes") 3473 .that(mCarAudioService.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)) 3474 .containsExactly(new AudioAttributes.Builder().setUsage(USAGE_ALARM).build()); 3475 } 3476 3477 @Test getActiveAudioAttributesForZone_withActivePlayback()3478 public void getActiveAudioAttributesForZone_withActivePlayback() { 3479 mCarAudioService.init(); 3480 mockActivePlayback(); 3481 3482 expectWithMessage("Playback active audio attributes") 3483 .that(mCarAudioService.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)) 3484 .containsExactly(new AudioAttributes.Builder().setUsage(USAGE_MEDIA).build()); 3485 } 3486 3487 @Test getActiveAudioAttributesForZone_withActiveHalAndPlayback()3488 public void getActiveAudioAttributesForZone_withActiveHalAndPlayback() { 3489 mCarAudioService.init(); 3490 mockActivePlayback(); 3491 when(mAudioManager.requestAudioFocus(any())).thenReturn( 3492 AudioManager.AUDIOFOCUS_REQUEST_GRANTED); 3493 requestHalAudioFocus(USAGE_VOICE_COMMUNICATION); 3494 3495 expectWithMessage("Playback active audio attributes") 3496 .that(mCarAudioService.getActiveAudioAttributesForZone(PRIMARY_AUDIO_ZONE)) 3497 .containsExactly(new AudioAttributes.Builder().setUsage(USAGE_MEDIA).build(), 3498 new AudioAttributes.Builder().setUsage(USAGE_VOICE_COMMUNICATION).build()); 3499 } 3500 3501 @Test getCallStateForZone_forPrimaryZone()3502 public void getCallStateForZone_forPrimaryZone() throws Exception { 3503 when(mMockTelephonyManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_OFFHOOK); 3504 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 3505 mCarAudioService.init(); 3506 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 3507 .thenReturn(TEST_DRIVER_USER_ID, TEST_REAR_RIGHT_USER_ID); 3508 assignOccupantToAudioZones(); 3509 3510 expectWithMessage("Primary zone call state").that( 3511 mCarAudioService.getCallStateForZone(PRIMARY_AUDIO_ZONE)) 3512 .isEqualTo(TelephonyManager.CALL_STATE_OFFHOOK); 3513 } 3514 3515 @Test getCallStateForZone_forNonPrimaryZone()3516 public void getCallStateForZone_forNonPrimaryZone() throws Exception { 3517 when(mMockTelephonyManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_OFFHOOK); 3518 when(mMockOccupantZoneService.getDriverUserId()).thenReturn(TEST_DRIVER_USER_ID); 3519 mCarAudioService.init(); 3520 when(mMockOccupantZoneService.getUserForOccupant(anyInt())) 3521 .thenReturn(TEST_REAR_LEFT_USER_ID, TEST_REAR_RIGHT_USER_ID); 3522 assignOccupantToAudioZones(); 3523 3524 expectWithMessage("Secondary zone call state").that( 3525 mCarAudioService.getCallStateForZone(TEST_REAR_LEFT_ZONE_ID)) 3526 .isEqualTo(TelephonyManager.CALL_STATE_IDLE); 3527 } 3528 3529 @Test getVolumeGroupAndContextCount()3530 public void getVolumeGroupAndContextCount() { 3531 CarAudioService useCoreAudioCarAudioService = 3532 getCarAudioServiceUsingCoreAudioRoutingAndVolume(); 3533 3534 verify(mAudioManager).registerVolumeGroupCallback(any(), any()); 3535 expectWithMessage("Primary zone car volume group count") 3536 .that(useCoreAudioCarAudioService.getVolumeGroupCount(PRIMARY_AUDIO_ZONE)) 3537 .isEqualTo(CoreAudioRoutingUtils.getVolumeGroups().size()); 3538 expectWithMessage("Number of contexts") 3539 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds().size()) 3540 .isEqualTo(CoreAudioRoutingUtils.getProductStrategies().size()); 3541 expectWithMessage("Car Audio Contexts") 3542 .that(useCoreAudioCarAudioService.getCarAudioContext().getAllContextsIds()) 3543 .containsExactly(CoreAudioRoutingUtils.NAV_STRATEGY_ID, 3544 CoreAudioRoutingUtils.MUSIC_STRATEGY_ID, 3545 CoreAudioRoutingUtils.OEM_STRATEGY_ID); 3546 } 3547 3548 @Test registerAudioZonesMirrorStatusCallback()3549 public void registerAudioZonesMirrorStatusCallback() { 3550 mCarAudioService.init(); 3551 TestAudioZonesMirrorStatusCallbackCallback callback = 3552 new TestAudioZonesMirrorStatusCallbackCallback(/* count= */ 1); 3553 3554 boolean registered = mCarAudioService.registerAudioZonesMirrorStatusCallback(callback); 3555 3556 expectWithMessage("Audio zones mirror status callback registered status") 3557 .that(registered).isTrue(); 3558 } 3559 3560 @Test registerAudioZonesMirrorStatusCallback_withoutMirroringEnabled()3561 public void registerAudioZonesMirrorStatusCallback_withoutMirroringEnabled() { 3562 CarAudioService carAudioService = getCarAudioServiceWithoutMirroring(); 3563 carAudioService.init(); 3564 TestAudioZonesMirrorStatusCallbackCallback callback = 3565 new TestAudioZonesMirrorStatusCallbackCallback(/* count= */ 1); 3566 3567 IllegalStateException thrown = 3568 assertThrows(IllegalStateException.class, () -> 3569 carAudioService.registerAudioZonesMirrorStatusCallback(callback)); 3570 3571 expectWithMessage("Disabled audio zones mirror register exception").that(thrown) 3572 .hasMessageThat().contains("Audio zones mirroring is required"); 3573 } 3574 3575 @Test registerAudioZonesMirrorStatusCallback_withNullCallback()3576 public void registerAudioZonesMirrorStatusCallback_withNullCallback() { 3577 mCarAudioService.init(); 3578 3579 NullPointerException thrown = 3580 assertThrows(NullPointerException.class, () -> 3581 mCarAudioService.registerAudioZonesMirrorStatusCallback(/* callback= */ null)); 3582 3583 expectWithMessage("Null audio zones mirror register exception").that(thrown) 3584 .hasMessageThat().contains("Audio zones mirror status callback"); 3585 } 3586 3587 @Test unregisterAudioZonesMirrorStatusCallback_withNullCallback()3588 public void unregisterAudioZonesMirrorStatusCallback_withNullCallback() { 3589 mCarAudioService.init(); 3590 3591 NullPointerException thrown = 3592 assertThrows(NullPointerException.class, () -> mCarAudioService 3593 .unregisterAudioZonesMirrorStatusCallback(/* callback= */ null)); 3594 3595 expectWithMessage("Null audio zones mirror unregister exception").that(thrown) 3596 .hasMessageThat().contains("Audio zones mirror status callback"); 3597 } 3598 3599 @Test enableMirrorForAudioZones_withNullAudioZones()3600 public void enableMirrorForAudioZones_withNullAudioZones() { 3601 mCarAudioService.init(); 3602 3603 NullPointerException thrown = 3604 assertThrows(NullPointerException.class, () -> 3605 mCarAudioService.enableMirrorForAudioZones(/* audioZones= */ null)); 3606 3607 expectWithMessage("Null mirror audio zones exception").that(thrown) 3608 .hasMessageThat().contains("Mirror audio zones"); 3609 } 3610 3611 @Test enableMirrorForAudioZones()3612 public void enableMirrorForAudioZones() throws Exception { 3613 mCarAudioService.init(); 3614 TestAudioZonesMirrorStatusCallbackCallback callback = 3615 getAudioZonesMirrorStatusCallback(); 3616 assignOccupantToAudioZones(); 3617 3618 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3619 3620 callback.waitForCallback(); 3621 expectWithMessage("Audio mirror approved status").that(callback.getLastStatus()) 3622 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 3623 expectWithMessage("Audio mirror approved zones").that(callback.getLastZoneIds()) 3624 .asList().containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID); 3625 } 3626 3627 @Test enableMirrorForAudioZones_sendsMirrorInfoToAudioHAL()3628 public void enableMirrorForAudioZones_sendsMirrorInfoToAudioHAL() throws Exception { 3629 mCarAudioService.init(); 3630 TestAudioZonesMirrorStatusCallbackCallback callback = 3631 getAudioZonesMirrorStatusCallback(); 3632 assignOccupantToAudioZones(); 3633 3634 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3635 3636 callback.waitForCallback(); 3637 String audioMirrorInfoCommand = captureAudioMirrorInfoCommand(1); 3638 List<String> commands = Arrays.asList(audioMirrorInfoCommand.split(";")); 3639 String sourceDeviceAddress = removeUpToEquals(commands.get(0)); 3640 expectWithMessage("Audio mirror source info").that(sourceDeviceAddress) 3641 .isEqualTo(MIRROR_TEST_DEVICE); 3642 String destinationsDevices = commands.get(1); 3643 List<String> deviceAddresses = Arrays.asList(removeUpToEquals(destinationsDevices) 3644 .split(",")); 3645 expectWithMessage("Audio mirror zone one info").that(deviceAddresses.get(0)) 3646 .isEqualTo(SECONDARY_TEST_DEVICE_CONFIG_0); 3647 expectWithMessage("Audio mirror zone two info").that(deviceAddresses.get(1)) 3648 .isEqualTo(TERTIARY_TEST_DEVICE_1); 3649 } 3650 3651 @Test enableMirrorForAudioZones_forPrimaryZone_fails()3652 public void enableMirrorForAudioZones_forPrimaryZone_fails() throws Exception { 3653 mCarAudioService.init(); 3654 assignOccupantToAudioZones(); 3655 int[] audioZones = new int[]{TEST_REAR_LEFT_ZONE_ID, PRIMARY_AUDIO_ZONE}; 3656 3657 IllegalArgumentException thrown = 3658 assertThrows(IllegalArgumentException.class, () -> 3659 mCarAudioService.enableMirrorForAudioZones(audioZones)); 3660 3661 expectWithMessage("Mirror audio zones with primary zone exception").that(thrown) 3662 .hasMessageThat().contains("not allowed for primary audio zone"); 3663 } 3664 3665 @Test enableMirrorForAudioZones_forNonAssignedZone_fails()3666 public void enableMirrorForAudioZones_forNonAssignedZone_fails() throws Exception { 3667 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 3668 .thenReturn(UserManagerHelper.USER_NULL); 3669 mCarAudioService.init(); 3670 getAudioZonesMirrorStatusCallback(); 3671 assignOccupantToAudioZones(); 3672 3673 IllegalStateException thrown = 3674 assertThrows(IllegalStateException.class, () -> 3675 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 3676 3677 expectWithMessage("Mirror audio zones for unoccupied audio zone exception") 3678 .that(thrown).hasMessageThat().contains("must have an active user"); 3679 } 3680 3681 @Test enableMirrorForAudioZones_forRepeatingZones_fails()3682 public void enableMirrorForAudioZones_forRepeatingZones_fails() throws Exception { 3683 mCarAudioService.init(); 3684 assignOccupantToAudioZones(); 3685 int[] audioZones = new int[]{TEST_REAR_LEFT_ZONE_ID, 3686 TEST_REAR_LEFT_ZONE_ID}; 3687 3688 IllegalArgumentException thrown = 3689 assertThrows(IllegalArgumentException.class, () -> 3690 mCarAudioService.enableMirrorForAudioZones(audioZones)); 3691 3692 expectWithMessage("Repeated mirror audio zones exception").that(thrown) 3693 .hasMessageThat().contains("must be unique"); 3694 } 3695 3696 @Test enableMirrorForAudioZones_forAlreadyMirroredZones()3697 public void enableMirrorForAudioZones_forAlreadyMirroredZones() throws Exception { 3698 mCarAudioService.init(); 3699 TestAudioZonesMirrorStatusCallbackCallback callback = 3700 getAudioZonesMirrorStatusCallback(); 3701 assignOccupantToAudioZones(); 3702 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3703 callback.waitForCallback(); 3704 callback.reset(/* count= */ 1); 3705 3706 IllegalStateException thrown = 3707 assertThrows(IllegalStateException.class, () -> 3708 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 3709 3710 expectWithMessage("Audio mirror exception for repeating request") 3711 .that(thrown).hasMessageThat().contains("is already mirroring"); 3712 3713 } 3714 3715 @Test enableMirrorForAudioZones_afterSharedInPrimaryZone()3716 public void enableMirrorForAudioZones_afterSharedInPrimaryZone() throws Exception { 3717 mCarAudioService.init(); 3718 TestPrimaryZoneMediaAudioRequestCallback 3719 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3720 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3721 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3722 assignOccupantToAudioZones(); 3723 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 3724 TEST_REAR_RIGHT_PASSENGER_OCCUPANT); 3725 requestToken.waitForCallback(); 3726 requestToken.reset(); 3727 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allowed= */ true); 3728 requestToken.waitForCallback(); 3729 requestToken.reset(); 3730 3731 IllegalStateException thrown = 3732 assertThrows(IllegalStateException.class, () -> 3733 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 3734 3735 expectWithMessage("Mirror audio zones while sharing in primary zone exception") 3736 .that(thrown).hasMessageThat().contains("currently sharing to primary zone"); 3737 } 3738 3739 @Test enableMirrorForAudioZones_forInvertedMirrorConfiguration()3740 public void enableMirrorForAudioZones_forInvertedMirrorConfiguration() throws Exception { 3741 mCarAudioService.init(); 3742 TestAudioZonesMirrorStatusCallbackCallback callback = 3743 getAudioZonesMirrorStatusCallback(); 3744 assignOccupantToAudioZones(); 3745 mCarAudioService.enableMirrorForAudioZones(new int[] {TEST_REAR_RIGHT_ZONE_ID, 3746 TEST_REAR_LEFT_ZONE_ID}); 3747 callback.waitForCallback(); 3748 callback.reset(/* count= */ 1); 3749 3750 IllegalStateException thrown = 3751 assertThrows(IllegalStateException.class, () -> 3752 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES)); 3753 3754 expectWithMessage("Audio mirror exception for inverted zone request") 3755 .that(thrown).hasMessageThat().contains("is already mirroring"); 3756 } 3757 3758 @Test enableMirrorForAudioZones_withNoMoreMirrorDevices_fails()3759 public void enableMirrorForAudioZones_withNoMoreMirrorDevices_fails() throws Exception { 3760 mCarAudioService.init(); 3761 TestAudioZonesMirrorStatusCallbackCallback callback = 3762 getAudioZonesMirrorStatusCallback(); 3763 assignOccupantToAudioZones(); 3764 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3765 callback.waitForCallback(); 3766 callback.reset(/* count= */ 1); 3767 3768 IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> 3769 mCarAudioService.enableMirrorForAudioZones( 3770 new int[] {TEST_FRONT_ZONE_ID, TEST_REAR_ROW_3_ZONE_ID})); 3771 3772 expectWithMessage("Audio mirror for out of mirror devices exception") 3773 .that(thrown).hasMessageThat().contains("available mirror output devices"); 3774 } 3775 3776 @Test canEnableAudioMirror_withOutOfMirroringDevices()3777 public void canEnableAudioMirror_withOutOfMirroringDevices() throws Exception { 3778 mCarAudioService.init(); 3779 TestAudioZonesMirrorStatusCallbackCallback callback = 3780 getAudioZonesMirrorStatusCallback(); 3781 assignOccupantToAudioZones(); 3782 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3783 callback.waitForCallback(); 3784 3785 expectWithMessage("Can audio mirror status").that(mCarAudioService 3786 .canEnableAudioMirror()) 3787 .isEqualTo(AUDIO_MIRROR_OUT_OF_OUTPUT_DEVICES); 3788 } 3789 3790 @Test canEnableAudioMirror_withAudioMirrorEnabledAndNoPendingRequests()3791 public void canEnableAudioMirror_withAudioMirrorEnabledAndNoPendingRequests() { 3792 mCarAudioService.init(); 3793 3794 expectWithMessage("Can audio mirror status before audio mirror request") 3795 .that(mCarAudioService.canEnableAudioMirror()) 3796 .isEqualTo(AUDIO_MIRROR_CAN_ENABLE); 3797 } 3798 3799 @Test canEnableAudioMirror_withMirroringDisabled()3800 public void canEnableAudioMirror_withMirroringDisabled() { 3801 CarAudioService carAudioService = getCarAudioServiceWithoutMirroring(); 3802 carAudioService.init(); 3803 3804 IllegalStateException thrown = assertThrows(IllegalStateException.class, () -> 3805 mCarAudioService.canEnableAudioMirror()); 3806 3807 expectWithMessage("Can enable audio mirror exception") 3808 .that(thrown).hasMessageThat().contains("Audio zones mirroring is required"); 3809 } 3810 3811 @Test extendAudioMirrorRequest()3812 public void extendAudioMirrorRequest() throws Exception { 3813 mCarAudioService.init(); 3814 TestAudioZonesMirrorStatusCallbackCallback callback = 3815 getAudioZonesMirrorStatusCallback(); 3816 assignOccupantToAudioZones(); 3817 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3818 callback.waitForCallback(); 3819 callback.reset(1); 3820 3821 mCarAudioService.extendAudioMirrorRequest(requestId, new int[] {TEST_FRONT_ZONE_ID}); 3822 3823 callback.waitForCallback(); 3824 expectWithMessage("Audio mirror approved status").that(callback.getLastStatus()) 3825 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_APPROVED); 3826 expectWithMessage("Audio mirror approved zones").that(callback.getLastZoneIds()) 3827 .asList().containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID, 3828 TEST_FRONT_ZONE_ID); 3829 } 3830 3831 @Test extendAudioMirrorRequest_withNullAudioZones()3832 public void extendAudioMirrorRequest_withNullAudioZones() throws Exception { 3833 mCarAudioService.init(); 3834 TestAudioZonesMirrorStatusCallbackCallback callback = 3835 getAudioZonesMirrorStatusCallback(); 3836 assignOccupantToAudioZones(); 3837 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3838 callback.waitForCallback(); 3839 callback.reset(1); 3840 3841 NullPointerException thrown = 3842 assertThrows(NullPointerException.class, () -> 3843 mCarAudioService.extendAudioMirrorRequest(requestId, 3844 /* audioZones = */ null)); 3845 3846 expectWithMessage("Null audio zones to extend for mirror request exception") 3847 .that(thrown).hasMessageThat().contains("Mirror audio zones"); 3848 } 3849 3850 @Test extendAudioMirrorRequest_withPrimaryAudioZone()3851 public void extendAudioMirrorRequest_withPrimaryAudioZone() throws Exception { 3852 mCarAudioService.init(); 3853 TestAudioZonesMirrorStatusCallbackCallback callback = 3854 getAudioZonesMirrorStatusCallback(); 3855 assignOccupantToAudioZones(); 3856 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3857 callback.waitForCallback(); 3858 callback.reset(1); 3859 3860 IllegalArgumentException thrown = 3861 assertThrows(IllegalArgumentException.class, () -> 3862 mCarAudioService.extendAudioMirrorRequest(requestId, 3863 new int[] {PRIMARY_AUDIO_ZONE})); 3864 3865 expectWithMessage("Primary audio zone to extend for mirror request exception") 3866 .that(thrown).hasMessageThat().contains( 3867 "Audio mirroring not allowed for primary audio zone"); 3868 } 3869 3870 @Test getAudioZoneConfigInfos()3871 public void getAudioZoneConfigInfos() { 3872 mCarAudioService.init(); 3873 3874 List<CarAudioZoneConfigInfo> zoneConfigInfos = 3875 mCarAudioService.getAudioZoneConfigInfos(TEST_REAR_LEFT_ZONE_ID); 3876 3877 List<String> zoneConfigNames = new ArrayList(zoneConfigInfos.size()); 3878 for (int index = 0; index < zoneConfigInfos.size(); index++) { 3879 zoneConfigNames.add(zoneConfigInfos.get(index).getName()); 3880 } 3881 expectWithMessage("Zone configurations for secondary zone").that(zoneConfigNames) 3882 .containsExactly(SECONDARY_ZONE_CONFIG_NAME_1, SECONDARY_ZONE_CONFIG_NAME_2); 3883 } 3884 3885 @Test getCurrentAudioZoneConfigInfo()3886 public void getCurrentAudioZoneConfigInfo() { 3887 mCarAudioService.init(); 3888 3889 CarAudioZoneConfigInfo currentZoneConfigInfo = 3890 mCarAudioService.getCurrentAudioZoneConfigInfo(TEST_REAR_LEFT_ZONE_ID); 3891 3892 expectWithMessage("Name of current zone configuration for secondary zone") 3893 .that(currentZoneConfigInfo.getName()).isEqualTo(SECONDARY_ZONE_CONFIG_NAME_1); 3894 } 3895 3896 @Test switchZoneToConfig()3897 public void switchZoneToConfig() throws Exception { 3898 mCarAudioService.init(); 3899 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 3900 assignOccupantToAudioZones(); 3901 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_LEFT_ZONE_ID); 3902 3903 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback); 3904 3905 callback.waitForCallback(); 3906 expectWithMessage("Updated zone configuration") 3907 .that(callback.getZoneConfig()).isEqualTo(zoneConfigSwitchTo); 3908 expectWithMessage("Zone configuration switching status") 3909 .that(callback.getSwitchStatus()).isTrue(); 3910 } 3911 3912 @Test switchZoneToConfig_forNonAssignedZone_fails()3913 public void switchZoneToConfig_forNonAssignedZone_fails() throws Exception { 3914 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 3915 .thenReturn(UserManagerHelper.USER_NULL); 3916 mCarAudioService.init(); 3917 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 3918 assignOccupantToAudioZones(); 3919 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_LEFT_ZONE_ID); 3920 3921 IllegalStateException thrown = 3922 assertThrows(IllegalStateException.class, () -> 3923 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback)); 3924 3925 expectWithMessage("Switching zone configuration for unoccupied audio zone exception") 3926 .that(thrown).hasMessageThat().contains("must have an active user"); 3927 } 3928 3929 @Test switchZoneToConfig_afterSharedInPrimaryZone_fails()3930 public void switchZoneToConfig_afterSharedInPrimaryZone_fails() throws Exception { 3931 mCarAudioService.init(); 3932 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 3933 TestPrimaryZoneMediaAudioRequestCallback 3934 requestToken = new TestPrimaryZoneMediaAudioRequestCallback(); 3935 mCarAudioService.registerPrimaryZoneMediaAudioRequestCallback(requestToken); 3936 TestMediaRequestStatusCallback requestCallback = new TestMediaRequestStatusCallback(); 3937 assignOccupantToAudioZones(); 3938 long requestId = mCarAudioService.requestMediaAudioOnPrimaryZone(requestCallback, 3939 TEST_REAR_LEFT_PASSENGER_OCCUPANT); 3940 requestToken.waitForCallback(); 3941 requestToken.reset(); 3942 mCarAudioService.allowMediaAudioOnPrimaryZone(requestToken, requestId, /* allowed= */ true); 3943 requestToken.waitForCallback(); 3944 requestToken.reset(); 3945 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_LEFT_ZONE_ID); 3946 3947 IllegalStateException thrown = 3948 assertThrows(IllegalStateException.class, () -> 3949 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback)); 3950 3951 expectWithMessage("Switching zone configuration while sharing in primary zone exception") 3952 .that(thrown).hasMessageThat().contains("currently sharing to primary zone"); 3953 } 3954 3955 @Test switchZoneToConfig_afterMirroring_fails()3956 public void switchZoneToConfig_afterMirroring_fails() throws Exception { 3957 mCarAudioService.init(); 3958 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 3959 TestAudioZonesMirrorStatusCallbackCallback mirrorCallback = 3960 getAudioZonesMirrorStatusCallback(); 3961 assignOccupantToAudioZones(); 3962 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 3963 mirrorCallback.waitForCallback(); 3964 mirrorCallback.reset(/* count= */ 1); 3965 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_LEFT_ZONE_ID); 3966 3967 IllegalStateException thrown = 3968 assertThrows(IllegalStateException.class, () -> 3969 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback)); 3970 3971 expectWithMessage("Switching zone configuration while audio mirroring").that(thrown) 3972 .hasMessageThat().contains("currently in a mirroring configuration"); 3973 } 3974 3975 @Test switchZoneToConfig_withPendingFocus_regainsFocus()3976 public void switchZoneToConfig_withPendingFocus_regainsFocus() throws Exception { 3977 mCarAudioService.init(); 3978 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 3979 assignOccupantToAudioZones(); 3980 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 3981 mCarAudioService.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 3982 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_RIGHT_ZONE_ID); 3983 3984 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback); 3985 3986 callback.waitForCallback(); 3987 expectWithMessage("Updated zone configuration with pending focus") 3988 .that(callback.getZoneConfig()).isEqualTo(zoneConfigSwitchTo); 3989 expectWithMessage("Zone configuration switching status with pending focus") 3990 .that(callback.getSwitchStatus()).isTrue(); 3991 List<Integer> focusChanges = getFocusChanges(audioFocusInfo); 3992 expectWithMessage("Media audio focus changes after switching zone") 3993 .that(focusChanges).containsExactly(AUDIOFOCUS_LOSS_TRANSIENT, AUDIOFOCUS_GAIN); 3994 } 3995 3996 @Test switchZoneToConfig_withPendingFocus_updatesDuckingInfo()3997 public void switchZoneToConfig_withPendingFocus_updatesDuckingInfo() throws Exception { 3998 mCarAudioService.init(); 3999 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 4000 assignOccupantToAudioZones(); 4001 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 4002 mCarAudioService.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 4003 ArgumentCaptor<List<CarDuckingInfo>> carDuckingInfosCaptor = 4004 ArgumentCaptor.forClass(List.class); 4005 verify(mAudioControlWrapperAidl).onDevicesToDuckChange(carDuckingInfosCaptor.capture()); 4006 verifyMediaDuckingInfoInZone(carDuckingInfosCaptor, TEST_REAR_RIGHT_ZONE_ID, 4007 " before switching zone"); 4008 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_RIGHT_ZONE_ID); 4009 4010 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback); 4011 4012 callback.waitForCallback(); 4013 expectWithMessage("Updated zone configuration with pending focus") 4014 .that(callback.getZoneConfig()).isEqualTo(zoneConfigSwitchTo); 4015 expectWithMessage("Zone configuration switching status with pending focus") 4016 .that(callback.getSwitchStatus()).isTrue(); 4017 verify(mAudioControlWrapperAidl, times(2)) 4018 .onDevicesToDuckChange(carDuckingInfosCaptor.capture()); 4019 verifyMediaDuckingInfoInZone(carDuckingInfosCaptor, TEST_REAR_RIGHT_ZONE_ID, 4020 " after switching zone"); 4021 } 4022 4023 @Test switchZoneToConfig_withCurrentZoneConfigAndPendingFocus_notLoseAndRegainFocus()4024 public void switchZoneToConfig_withCurrentZoneConfigAndPendingFocus_notLoseAndRegainFocus() 4025 throws Exception { 4026 mCarAudioService.init(); 4027 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 4028 assignOccupantToAudioZones(); 4029 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 4030 mCarAudioService.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 4031 CarAudioZoneConfigInfo currentZoneConfig = 4032 mCarAudioService.getCurrentAudioZoneConfigInfo(TEST_REAR_RIGHT_ZONE_ID); 4033 4034 mCarAudioService.switchZoneToConfig(currentZoneConfig, callback); 4035 4036 callback.waitForCallback(); 4037 expectWithMessage("Updated zone configuration with current configuration") 4038 .that(callback.getZoneConfig()).isEqualTo(currentZoneConfig); 4039 expectWithMessage("Zone configuration switching status with current configuration") 4040 .that(callback.getSwitchStatus()).isTrue(); 4041 verify(mAudioManager, never()).dispatchAudioFocusChange(eq(audioFocusInfo), anyInt(), 4042 any(AudioPolicy.class)); 4043 } 4044 4045 @Test switchZoneToConfig_withVolumeGroupEventCallbackRegistered_invokesEvent()4046 public void switchZoneToConfig_withVolumeGroupEventCallbackRegistered_invokesEvent() 4047 throws Exception { 4048 mCarAudioService.init(); 4049 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 4050 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4051 assignOccupantToAudioZones(); 4052 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_LEFT_ZONE_ID); 4053 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4054 4055 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback); 4056 4057 callback.waitForCallback(); 4058 expectWithMessage("Updated zone configuration") 4059 .that(callback.getZoneConfig()).isEqualTo(zoneConfigSwitchTo); 4060 expectWithMessage("Zone configuration switching status") 4061 .that(callback.getSwitchStatus()).isTrue(); 4062 volumeEventCallback.waitForCallback(); 4063 expectWithMessage("Volume events count after switching zone configuration") 4064 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 4065 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 4066 expectWithMessage("Volume event type after switching zone configuration") 4067 .that(groupEvent.getEventTypes()) 4068 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_ZONE_CONFIGURATION_CHANGED); 4069 expectWithMessage("Volume group infos after switching zone configuration") 4070 .that(groupEvent.getCarVolumeGroupInfos()) 4071 .containsExactly(TEST_SECONDARY_ZONE_CONFIG_1_VOLUME_INFO_0, 4072 TEST_SECONDARY_ZONE_CONFIG_1_VOLUME_INFO_1); 4073 } 4074 4075 @Test switchZoneToConfig_updatesVolumeGroupInfos()4076 public void switchZoneToConfig_updatesVolumeGroupInfos() 4077 throws Exception { 4078 mCarAudioService.init(); 4079 SwitchAudioZoneConfigCallbackImpl callback = new SwitchAudioZoneConfigCallbackImpl(); 4080 assignOccupantToAudioZones(); 4081 Log.e(TAG, "Current volume group " + mCarAudioService.getVolumeGroupInfosForZone( 4082 TEST_REAR_LEFT_ZONE_ID)); 4083 expectWithMessage("Volume group infos before switching zone configuration") 4084 .that(mCarAudioService.getVolumeGroupInfosForZone(TEST_REAR_LEFT_ZONE_ID)) 4085 .containsExactly(TEST_SECONDARY_ZONE_CONFIG_0_VOLUME_INFO); 4086 CarAudioZoneConfigInfo zoneConfigSwitchTo = getZoneConfigToSwitch(TEST_REAR_LEFT_ZONE_ID); 4087 4088 mCarAudioService.switchZoneToConfig(zoneConfigSwitchTo, callback); 4089 4090 callback.waitForCallback(); 4091 expectWithMessage("Volume group infos after switching zone configuration") 4092 .that(mCarAudioService.getVolumeGroupInfosForZone(TEST_REAR_LEFT_ZONE_ID)) 4093 .containsExactly(TEST_SECONDARY_ZONE_CONFIG_1_VOLUME_INFO_0, 4094 TEST_SECONDARY_ZONE_CONFIG_1_VOLUME_INFO_1); 4095 } 4096 4097 @Test disableAudioMirrorForZone_withInvalidZone()4098 public void disableAudioMirrorForZone_withInvalidZone() throws Exception { 4099 mCarAudioService.init(); 4100 assignOccupantToAudioZones(); 4101 4102 IllegalArgumentException thrown = 4103 assertThrows(IllegalArgumentException.class, () -> 4104 mCarAudioService.disableAudioMirrorForZone(INVALID_AUDIO_ZONE)); 4105 4106 expectWithMessage("Disable mirror for invalid audio zone exception").that(thrown) 4107 .hasMessageThat().contains("Invalid audio zone"); 4108 } 4109 4110 @Test disableAudioMirrorForZone_withMirroringDisabled()4111 public void disableAudioMirrorForZone_withMirroringDisabled() { 4112 CarAudioService carAudioService = getCarAudioServiceWithoutMirroring(); 4113 carAudioService.init(); 4114 4115 IllegalStateException thrown = 4116 assertThrows(IllegalStateException.class, () -> 4117 mCarAudioService.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID)); 4118 4119 expectWithMessage("Disable mirror for zone with audio mirroring disabled") 4120 .that(thrown).hasMessageThat().contains("Audio zones mirroring is required"); 4121 } 4122 4123 @Test disableAudioMirrorForZone_forNonMirroringZone()4124 public void disableAudioMirrorForZone_forNonMirroringZone() throws Exception { 4125 mCarAudioService.init(); 4126 TestAudioZonesMirrorStatusCallbackCallback callback = 4127 getAudioZonesMirrorStatusCallback(); 4128 assignOccupantToAudioZones(); 4129 4130 mCarAudioService.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID); 4131 4132 callback.waitForCallback(); 4133 expectWithMessage("Disable audio mirror for non-mirroring zone callback count") 4134 .that(callback.mNumberOfCalls).isEqualTo(0); 4135 } 4136 4137 @Test disableAudioMirrorForZone_forMirroringZones()4138 public void disableAudioMirrorForZone_forMirroringZones() throws Exception { 4139 mCarAudioService.init(); 4140 TestAudioZonesMirrorStatusCallbackCallback callback = 4141 getAudioZonesMirrorStatusCallback(); 4142 assignOccupantToAudioZones(); 4143 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4144 callback.waitForCallback(); 4145 callback.reset(/* count= */ 1); 4146 4147 mCarAudioService.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID); 4148 4149 callback.waitForCallback(); 4150 expectWithMessage("Callback count for disable audio mirror") 4151 .that(callback.mNumberOfCalls).isEqualTo(2); 4152 expectWithMessage("Callback status disable audio mirror for mirroring zone") 4153 .that(callback.getLastStatus()) 4154 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 4155 expectWithMessage("Callback zones disable audio mirror for mirroring zone") 4156 .that(callback.getLastZoneIds()).asList() 4157 .containsExactly(TEST_REAR_RIGHT_ZONE_ID, TEST_REAR_LEFT_ZONE_ID); 4158 } 4159 4160 @Test disableAudioMirrorForZone_forMirroringZones_forFirstMirroringConfig()4161 public void disableAudioMirrorForZone_forMirroringZones_forFirstMirroringConfig() 4162 throws Exception { 4163 mCarAudioService.init(); 4164 TestAudioZonesMirrorStatusCallbackCallback callback = 4165 getAudioZonesMirrorStatusCallback(); 4166 assignOccupantToAudioZones(); 4167 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4168 callback.waitForCallback(); 4169 callback.reset(/* count= */ 1); 4170 4171 mCarAudioService.disableAudioMirrorForZone(TEST_REAR_RIGHT_ZONE_ID); 4172 4173 callback.waitForCallback(); 4174 expectWithMessage("Callback count for disable audio mirror") 4175 .that(callback.mNumberOfCalls).isEqualTo(2); 4176 expectWithMessage("Callback status disable audio mirror for mirroring zone") 4177 .that(callback.getLastStatus()) 4178 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 4179 expectWithMessage("Callback zones disable audio mirror for mirroring zone") 4180 .that(callback.getLastZoneIds()).asList() 4181 .containsExactly(TEST_REAR_RIGHT_ZONE_ID, TEST_REAR_LEFT_ZONE_ID); 4182 String audioMirrorOffCommand = captureAudioMirrorInfoCommand(2); 4183 expectWithMessage("Audio HAL off source for mirroring zone") 4184 .that(audioMirrorOffCommand).contains(MIRROR_TEST_DEVICE); 4185 expectWithMessage("Audio HAL off signal for mirroring zone") 4186 .that(audioMirrorOffCommand).contains(MIRROR_OFF_SIGNAL); 4187 } 4188 4189 @Test disableAudioMirrorForZone_withPendingFocus()4190 public void disableAudioMirrorForZone_withPendingFocus() 4191 throws Exception { 4192 mCarAudioService.init(); 4193 TestAudioZonesMirrorStatusCallbackCallback callback = 4194 getAudioZonesMirrorStatusCallback(); 4195 assignOccupantToAudioZones(); 4196 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4197 callback.waitForCallback(); 4198 callback.reset(/* count= */ 2); 4199 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 4200 mCarAudioService.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 4201 4202 mCarAudioService.disableAudioMirrorForZone(TEST_REAR_LEFT_ZONE_ID); 4203 4204 callback.waitForCallback(); 4205 List<Integer> focusChanges = getFocusChanges(audioFocusInfo); 4206 expectWithMessage("Media audio focus changes after disable mirror for zone") 4207 .that(focusChanges).containsExactly(AUDIOFOCUS_LOSS_TRANSIENT, AUDIOFOCUS_GAIN); 4208 } 4209 4210 @Test disableAudioMirror_withoutMirroringDisabled()4211 public void disableAudioMirror_withoutMirroringDisabled() { 4212 CarAudioService carAudioService = getCarAudioServiceWithoutMirroring(); 4213 carAudioService.init(); 4214 4215 IllegalStateException thrown = 4216 assertThrows(IllegalStateException.class, () -> 4217 carAudioService.disableAudioMirror(INVALID_REQUEST_ID)); 4218 4219 expectWithMessage("Disable mirror for audio zones with audio mirroring disabled") 4220 .that(thrown).hasMessageThat().contains("Audio zones mirroring is required"); 4221 } 4222 4223 @Test disableAudioMirror_withInvalidRequestId()4224 public void disableAudioMirror_withInvalidRequestId() { 4225 mCarAudioService.init(); 4226 4227 IllegalArgumentException thrown = 4228 assertThrows(IllegalArgumentException.class, () -> 4229 mCarAudioService.disableAudioMirror(INVALID_REQUEST_ID)); 4230 4231 expectWithMessage("Disable mirror for audio zones with audio invalid request id") 4232 .that(thrown).hasMessageThat().contains("INVALID_REQUEST_ID"); 4233 } 4234 4235 @Test disableAudioMirror_forNonMirroringZone()4236 public void disableAudioMirror_forNonMirroringZone() throws Exception { 4237 mCarAudioService.init(); 4238 TestAudioZonesMirrorStatusCallbackCallback callback = 4239 getAudioZonesMirrorStatusCallback(); 4240 assignOccupantToAudioZones(); 4241 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4242 callback.waitForCallback(); 4243 callback.reset(1); 4244 mCarAudioService.disableAudioMirror(requestId); 4245 callback.waitForCallback(); 4246 callback.reset(1); 4247 4248 mCarAudioService.disableAudioMirror(requestId); 4249 4250 expectWithMessage("Disable audio mirror for non-mirroring zone callback count") 4251 .that(callback.mNumberOfCalls).isEqualTo(2); 4252 } 4253 4254 @Test disableAudioMirror_forMirroringZones()4255 public void disableAudioMirror_forMirroringZones() throws Exception { 4256 mCarAudioService.init(); 4257 TestAudioZonesMirrorStatusCallbackCallback callback = 4258 getAudioZonesMirrorStatusCallback(); 4259 assignOccupantToAudioZones(); 4260 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4261 callback.waitForCallback(); 4262 callback.reset(/* count= */ 1); 4263 4264 mCarAudioService.disableAudioMirror(requestId); 4265 4266 callback.waitForCallback(); 4267 expectWithMessage("Callback count for disable mirror in audio zones") 4268 .that(callback.mNumberOfCalls).isEqualTo(2); 4269 expectWithMessage("Callback status disable audio mirror for mirroring zones") 4270 .that(callback.getLastStatus()) 4271 .isEqualTo(CarAudioManager.AUDIO_REQUEST_STATUS_STOPPED); 4272 expectWithMessage("Callback zones disable audio mirror for mirroring zones") 4273 .that(callback.getLastZoneIds()).asList() 4274 .containsExactly(TEST_REAR_RIGHT_ZONE_ID, TEST_REAR_LEFT_ZONE_ID); 4275 String audioMirrorOffCommand = captureAudioMirrorInfoCommand(2); 4276 expectWithMessage("Audio HAL off source for mirroring zones") 4277 .that(audioMirrorOffCommand).contains(MIRROR_TEST_DEVICE); 4278 expectWithMessage("Audio HAL off signal for mirroring zones") 4279 .that(audioMirrorOffCommand).contains(MIRROR_OFF_SIGNAL); 4280 } 4281 4282 @Test disableAudioMirror_withPendingFocus()4283 public void disableAudioMirror_withPendingFocus() throws Exception { 4284 mCarAudioService.init(); 4285 TestAudioZonesMirrorStatusCallbackCallback callback = 4286 getAudioZonesMirrorStatusCallback(); 4287 assignOccupantToAudioZones(); 4288 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4289 callback.waitForCallback(); 4290 callback.reset(/* count= */ 2); 4291 AudioFocusInfo audioFocusInfo = createAudioFocusInfoForMedia(TEST_REAR_RIGHT_UID); 4292 mCarAudioService.requestAudioFocusForTest(audioFocusInfo, AUDIOFOCUS_REQUEST_GRANTED); 4293 4294 mCarAudioService.disableAudioMirror(requestId); 4295 4296 callback.waitForCallback(); 4297 List<Integer> focusChanges = getFocusChanges(audioFocusInfo); 4298 expectWithMessage("Media audio focus changes after disable audio" 4299 + "mirror for zones config").that(focusChanges) 4300 .containsExactly(AUDIOFOCUS_LOSS_TRANSIENT, AUDIOFOCUS_GAIN); 4301 } 4302 4303 @Test getMirrorAudioZonesForAudioZone_withoutMirroringEnabled()4304 public void getMirrorAudioZonesForAudioZone_withoutMirroringEnabled() 4305 throws Exception { 4306 mCarAudioService.init(); 4307 assignOccupantToAudioZones(); 4308 4309 int[] zones = mCarAudioService.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 4310 4311 expectWithMessage("Mirroring zones for non mirror zone %s", TEST_REAR_RIGHT_ZONE_ID) 4312 .that(zones).asList().isEmpty(); 4313 } 4314 4315 @Test getMirrorAudioZonesForAudioZone_withMirroringEnabled()4316 public void getMirrorAudioZonesForAudioZone_withMirroringEnabled() throws Exception { 4317 mCarAudioService.init(); 4318 TestAudioZonesMirrorStatusCallbackCallback callback = 4319 getAudioZonesMirrorStatusCallback(); 4320 assignOccupantToAudioZones(); 4321 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4322 callback.waitForCallback(); 4323 4324 int[] zones = mCarAudioService.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 4325 4326 expectWithMessage("Mirroring zones for mirror zone %s", TEST_REAR_RIGHT_ZONE_ID).that(zones) 4327 .asList().containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID); 4328 } 4329 4330 @Test getMirrorAudioZonesForAudioZone_afterDisableMirror()4331 public void getMirrorAudioZonesForAudioZone_afterDisableMirror() throws Exception { 4332 mCarAudioService.init(); 4333 TestAudioZonesMirrorStatusCallbackCallback callback = 4334 getAudioZonesMirrorStatusCallback(); 4335 assignOccupantToAudioZones(); 4336 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4337 callback.waitForCallback(); 4338 callback.reset(1); 4339 mCarAudioService.disableAudioMirror(requestId); 4340 callback.waitForCallback(); 4341 4342 int[] zones = mCarAudioService.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 4343 4344 expectWithMessage("Mirroring zones for mirror zone %s after disabling mirroring", 4345 TEST_REAR_RIGHT_ZONE_ID).that(zones).asList().isEmpty(); 4346 } 4347 4348 @Test getMirrorAudioZonesForAudioZone_afterPassengerLogout()4349 public void getMirrorAudioZonesForAudioZone_afterPassengerLogout() throws Exception { 4350 mCarAudioService.init(); 4351 TestAudioZonesMirrorStatusCallbackCallback callback = 4352 getAudioZonesMirrorStatusCallback(); 4353 assignOccupantToAudioZones(); 4354 mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4355 callback.waitForCallback(); 4356 callback.reset(1); 4357 simulateLogoutRightPassengers(); 4358 callback.waitForCallback(); 4359 4360 int[] zones = mCarAudioService.getMirrorAudioZonesForAudioZone(TEST_REAR_RIGHT_ZONE_ID); 4361 4362 expectWithMessage("Mirroring zones for mirror zone %s after logout", 4363 TEST_REAR_RIGHT_ZONE_ID).that(zones).asList().isEmpty(); 4364 } 4365 4366 @Test getMirrorAudioZonesForMirrorRequest_withMirroringEnabled()4367 public void getMirrorAudioZonesForMirrorRequest_withMirroringEnabled() throws Exception { 4368 mCarAudioService.init(); 4369 TestAudioZonesMirrorStatusCallbackCallback callback = 4370 getAudioZonesMirrorStatusCallback(); 4371 assignOccupantToAudioZones(); 4372 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4373 callback.waitForCallback(); 4374 4375 int[] zones = mCarAudioService.getMirrorAudioZonesForMirrorRequest(requestId); 4376 4377 expectWithMessage("Mirroring zones for mirror request %s", requestId).that(zones).asList() 4378 .containsExactly(TEST_REAR_LEFT_ZONE_ID, TEST_REAR_RIGHT_ZONE_ID); 4379 } 4380 4381 @Test getMirrorAudioZonesForMirrorRequest_afterDisableMirror()4382 public void getMirrorAudioZonesForMirrorRequest_afterDisableMirror() throws Exception { 4383 mCarAudioService.init(); 4384 TestAudioZonesMirrorStatusCallbackCallback callback = 4385 getAudioZonesMirrorStatusCallback(); 4386 assignOccupantToAudioZones(); 4387 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4388 callback.waitForCallback(); 4389 callback.reset(1); 4390 mCarAudioService.disableAudioMirror(requestId); 4391 callback.waitForCallback(); 4392 4393 int[] zones = mCarAudioService.getMirrorAudioZonesForMirrorRequest(TEST_REAR_RIGHT_ZONE_ID); 4394 4395 expectWithMessage("Mirroring zones for mirror request %s after disabling mirroring", 4396 requestId).that(zones).asList().isEmpty(); 4397 } 4398 4399 @Test getMirrorAudioZonesForMirrorRequest_afterPassengerLogout()4400 public void getMirrorAudioZonesForMirrorRequest_afterPassengerLogout() throws Exception { 4401 mCarAudioService.init(); 4402 TestAudioZonesMirrorStatusCallbackCallback callback = 4403 getAudioZonesMirrorStatusCallback(); 4404 assignOccupantToAudioZones(); 4405 long requestId = mCarAudioService.enableMirrorForAudioZones(TEST_MIRROR_AUDIO_ZONES); 4406 callback.waitForCallback(); 4407 callback.reset(1); 4408 simulateLogoutRightPassengers(); 4409 callback.waitForCallback(); 4410 4411 int[] zones = mCarAudioService.getMirrorAudioZonesForMirrorRequest(requestId); 4412 4413 expectWithMessage("Mirroring zones for mirror request %s after logout", 4414 TEST_REAR_RIGHT_ZONE_ID).that(zones).asList().isEmpty(); 4415 } 4416 4417 @Test onAudioVolumeGroupChanged_dispatchCallbackEvent()4418 public void onAudioVolumeGroupChanged_dispatchCallbackEvent() throws RemoteException { 4419 CarAudioService useCoreAudioCarAudioService = 4420 getCarAudioServiceUsingCoreAudioRoutingAndVolume(); 4421 int musicIndex = useCoreAudioCarAudioService.getGroupVolume( 4422 PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID); 4423 // Report a volume change 4424 when(mAudioManager.getVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 4425 .thenReturn(musicIndex + 1); 4426 when(mAudioManager.getLastAudibleVolumeForVolumeGroup(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 4427 .thenReturn(musicIndex + 1); 4428 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 4429 .thenReturn(false); 4430 4431 useCoreAudioCarAudioService.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 4432 CoreAudioRoutingUtils.MUSIC_GROUP_NAME, /* flags= */ 0); 4433 4434 verify(mCarVolumeCallbackHandler) 4435 .onVolumeGroupChange(PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, 4436 FLAG_SHOW_UI | FLAG_PLAY_SOUND); 4437 } 4438 4439 @Test onAudioVolumeGroupChanged_noDispatchCallbackEvent_whenAlreadySynced()4440 public void onAudioVolumeGroupChanged_noDispatchCallbackEvent_whenAlreadySynced() 4441 throws RemoteException { 4442 CarAudioService useCoreAudioCarAudioService = 4443 getCarAudioServiceUsingCoreAudioRoutingAndVolume(); 4444 useCoreAudioCarAudioService.setGroupVolume(PRIMARY_AUDIO_ZONE, 4445 CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, CoreAudioRoutingUtils.MUSIC_AM_INIT_INDEX, 4446 /* flags= */ 0); 4447 reset(mCarVolumeCallbackHandler); 4448 4449 useCoreAudioCarAudioService.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 4450 CoreAudioRoutingUtils.MUSIC_GROUP_NAME, /* flags= */ 0); 4451 4452 verify(mCarVolumeCallbackHandler, never()) 4453 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 4454 } 4455 4456 @Test onAudioVolumeGroupChanged_dispatchCallbackEvent_whenMuted()4457 public void onAudioVolumeGroupChanged_dispatchCallbackEvent_whenMuted() throws RemoteException { 4458 CarAudioService useCoreAudioCarAudioService = 4459 getCarAudioServiceUsingCoreAudioRoutingAndVolume(); 4460 // Report a mute change 4461 when(mAudioManager.getVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 4462 .thenReturn(CoreAudioRoutingUtils.MUSIC_MIN_INDEX); 4463 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 4464 .thenReturn(true); 4465 4466 useCoreAudioCarAudioService.onAudioVolumeGroupChanged(PRIMARY_AUDIO_ZONE, 4467 CoreAudioRoutingUtils.MUSIC_GROUP_NAME, /* flags= */ 0); 4468 4469 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 4470 CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, FLAG_SHOW_UI); 4471 } 4472 4473 @Test onVolumeGroupEvent_withVolumeEvent_triggersCallback()4474 public void onVolumeGroupEvent_withVolumeEvent_triggersCallback() throws Exception { 4475 mCarAudioService.init(); 4476 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4477 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4478 4479 mCarAudioService.onVolumeGroupEvent(List.of(TEST_CAR_VOLUME_GROUP_EVENT)); 4480 4481 expectWithMessage("Volume event callback reception status") 4482 .that(volumeEventCallback.waitForCallback()).isTrue(); 4483 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 4484 verify(mCarVolumeCallbackHandler) 4485 .onVolumeGroupChange(PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, 4486 /* flags= */ 0); 4487 expectWithMessage("Volume events count after volume event") 4488 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 4489 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 4490 expectWithMessage("Volume event type after volume event") 4491 .that(groupEvent.getEventTypes()) 4492 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_VOLUME_GAIN_INDEX_CHANGED); 4493 expectWithMessage("Volume group infos after unmute") 4494 .that(groupEvent.getCarVolumeGroupInfos()) 4495 .containsExactly(TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0); 4496 } 4497 4498 @Test onVolumeGroupEvent_withMuteEvent_triggersCallback()4499 public void onVolumeGroupEvent_withMuteEvent_triggersCallback() throws Exception { 4500 mCarAudioService.init(); 4501 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4502 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4503 4504 mCarAudioService.onVolumeGroupEvent(List.of(TEST_CAR_MUTE_GROUP_EVENT)); 4505 4506 expectWithMessage("Volume event callback reception status") 4507 .that(volumeEventCallback.waitForCallback()).isTrue(); 4508 verify(mCarVolumeCallbackHandler, never()) 4509 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 4510 verify(mCarVolumeCallbackHandler) 4511 .onGroupMuteChange(PRIMARY_AUDIO_ZONE, CoreAudioRoutingUtils.MUSIC_CAR_GROUP_ID, 4512 /* flags= */ 0); 4513 expectWithMessage("Volume events count after mute event") 4514 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 4515 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 4516 expectWithMessage("Volume event type after mute event") 4517 .that(groupEvent.getEventTypes()) 4518 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 4519 expectWithMessage("Volume group infos after mute event") 4520 .that(groupEvent.getCarVolumeGroupInfos()) 4521 .containsExactly(TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0); 4522 } 4523 4524 @Test onVolumeGroupEvent_withoutMuteOrVolumeEvent_doesNotTriggerCallback()4525 public void onVolumeGroupEvent_withoutMuteOrVolumeEvent_doesNotTriggerCallback() 4526 throws Exception { 4527 mCarAudioService.init(); 4528 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4529 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4530 4531 mCarAudioService.onVolumeGroupEvent(List.of(TEST_CAR_ZONE_RECONFIGURATION_EVENT)); 4532 4533 expectWithMessage("Volume event callback reception status") 4534 .that(volumeEventCallback.waitForCallback()).isTrue(); 4535 verify(mCarVolumeCallbackHandler, never()) 4536 .onVolumeGroupChange(anyInt(), anyInt(), anyInt()); 4537 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 4538 expectWithMessage("Volume events count after reconfiguration event") 4539 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 4540 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 4541 expectWithMessage("Volume event type after reconfiguration event") 4542 .that(groupEvent.getEventTypes()) 4543 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_ZONE_CONFIGURATION_CHANGED); 4544 expectWithMessage("Volume group infos after reconfiguration event") 4545 .that(groupEvent.getCarVolumeGroupInfos()) 4546 .containsExactly(TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0); 4547 } 4548 4549 @Test setMuted_whenUnmuted_onActivation_triggersCallback()4550 public void setMuted_whenUnmuted_onActivation_triggersCallback() throws Exception { 4551 mCarAudioService.init(); 4552 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4553 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4554 4555 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 4556 /* mute= */ true, TEST_FLAGS); 4557 4558 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 4559 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 4560 expectWithMessage("Volume event callback reception status after mute") 4561 .that(volumeEventCallback.waitForCallback()).isTrue(); 4562 expectWithMessage("Volume events count after mute") 4563 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 4564 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 4565 expectWithMessage("Volume event type after mute") 4566 .that(groupEvent.getEventTypes()) 4567 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 4568 expectWithMessage("Volume group infos after mute") 4569 .that(groupEvent.getCarVolumeGroupInfos()) 4570 .containsExactly(TEST_PRIMARY_ZONE_VOLUME_INFO_0); 4571 } 4572 4573 @Test setMuted_whenUnmuted_onDeactivation_doesNotTriggerCallback()4574 public void setMuted_whenUnmuted_onDeactivation_doesNotTriggerCallback() throws Exception { 4575 mCarAudioService.init(); 4576 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4577 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4578 4579 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 4580 /* mute= */ false, TEST_FLAGS); 4581 4582 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 4583 expectWithMessage("Volume event callback reception status") 4584 .that(volumeEventCallback.waitForCallback()).isFalse(); 4585 } 4586 4587 @Test setMuted_whenMuted_onDeactivation_triggersCallback()4588 public void setMuted_whenMuted_onDeactivation_triggersCallback() throws Exception { 4589 mCarAudioService.init(); 4590 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4591 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4592 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 4593 /* mute= */ true, TEST_FLAGS); 4594 volumeEventCallback.waitForCallback(); 4595 volumeEventCallback.reset(); 4596 reset(mCarVolumeCallbackHandler); 4597 4598 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 4599 /* mute= */ false, TEST_FLAGS); 4600 4601 verify(mCarVolumeCallbackHandler).onGroupMuteChange(PRIMARY_AUDIO_ZONE, 4602 TEST_PRIMARY_ZONE_GROUP_0, TEST_FLAGS); 4603 expectWithMessage("Volume event callback reception status after unmute") 4604 .that(volumeEventCallback.waitForCallback()).isTrue(); 4605 expectWithMessage("Volume events count after mute") 4606 .that(volumeEventCallback.getVolumeGroupEvents()).hasSize(1); 4607 CarVolumeGroupEvent groupEvent = volumeEventCallback.getVolumeGroupEvents().get(0); 4608 expectWithMessage("Volume event type after unmute") 4609 .that(groupEvent.getEventTypes()) 4610 .isEqualTo(CarVolumeGroupEvent.EVENT_TYPE_MUTE_CHANGED); 4611 expectWithMessage("Volume group infos after unmute") 4612 .that(groupEvent.getCarVolumeGroupInfos()) 4613 .containsExactly(TEST_PRIMARY_ZONE_UNMUTED_VOLUME_INFO_0); 4614 } 4615 4616 @Test setMuted_whenMuted_onActivation_doesNotTriggerCallback()4617 public void setMuted_whenMuted_onActivation_doesNotTriggerCallback() throws Exception { 4618 mCarAudioService.init(); 4619 CarVolumeEventCallbackImpl volumeEventCallback = new CarVolumeEventCallbackImpl(); 4620 mCarAudioService.registerCarVolumeEventCallback(volumeEventCallback); 4621 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 4622 /* mute= */ true, TEST_FLAGS); 4623 volumeEventCallback.waitForCallback(); 4624 volumeEventCallback.reset(); 4625 reset(mCarVolumeCallbackHandler); 4626 4627 mCarAudioService.setVolumeGroupMute(PRIMARY_AUDIO_ZONE, TEST_PRIMARY_ZONE_GROUP_0, 4628 /* mute= */ true, TEST_FLAGS); 4629 4630 verify(mCarVolumeCallbackHandler, never()).onGroupMuteChange(anyInt(), anyInt(), anyInt()); 4631 expectWithMessage("Volume event callback reception status") 4632 .that(volumeEventCallback.waitForCallback()).isFalse(); 4633 } 4634 removeUpToEquals(String command)4635 private String removeUpToEquals(String command) { 4636 return command.replaceAll("^[^=]*=", ""); 4637 } 4638 captureAudioMirrorInfoCommand(int count)4639 private String captureAudioMirrorInfoCommand(int count) { 4640 ArgumentCaptor<String> capture = ArgumentCaptor.forClass(String.class); 4641 verify(mAudioManager, times(count)).setParameters(capture.capture()); 4642 return capture.getValue(); 4643 } 4644 getAudioZonesMirrorStatusCallback()4645 private TestAudioZonesMirrorStatusCallbackCallback getAudioZonesMirrorStatusCallback() { 4646 TestAudioZonesMirrorStatusCallbackCallback callback = 4647 new TestAudioZonesMirrorStatusCallbackCallback(/* count= */ 1); 4648 mCarAudioService.registerAudioZonesMirrorStatusCallback(callback); 4649 return callback; 4650 } 4651 assignOccupantToAudioZones()4652 private void assignOccupantToAudioZones() throws RemoteException { 4653 ICarOccupantZoneCallback occupantZoneCallback = getOccupantZoneCallback(); 4654 occupantZoneCallback.onOccupantZoneConfigChanged( 4655 CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER); 4656 } 4657 simulateLogoutPassengers()4658 private void simulateLogoutPassengers() throws Exception { 4659 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 4660 .thenReturn(UserManagerHelper.USER_NULL); 4661 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 4662 .thenReturn(UserManagerHelper.USER_NULL); 4663 4664 assignOccupantToAudioZones(); 4665 } 4666 simulateLogoutRightPassengers()4667 private void simulateLogoutRightPassengers() throws Exception { 4668 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 4669 .thenReturn(UserManagerHelper.USER_NULL); 4670 4671 assignOccupantToAudioZones(); 4672 } 4673 simulatePassengersSwitch()4674 private void simulatePassengersSwitch() throws Exception { 4675 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_LEFT_OCCUPANT_ZONE_ID)) 4676 .thenReturn(TEST_REAR_RIGHT_USER_ID); 4677 when(mMockOccupantZoneService.getUserForOccupant(TEST_REAR_RIGHT_OCCUPANT_ZONE_ID)) 4678 .thenReturn(TEST_REAR_LEFT_USER_ID); 4679 4680 assignOccupantToAudioZones(); 4681 } 4682 createCarAudioGainConfigInfo(int zoneId, String devicePortAddress, int volumeIndex)4683 private CarAudioGainConfigInfo createCarAudioGainConfigInfo(int zoneId, 4684 String devicePortAddress, int volumeIndex) { 4685 AudioGainConfigInfo configInfo = new AudioGainConfigInfo(); 4686 configInfo.zoneId = zoneId; 4687 configInfo.devicePortAddress = devicePortAddress; 4688 configInfo.volumeIndex = volumeIndex; 4689 return new CarAudioGainConfigInfo(configInfo); 4690 } 4691 getHalAudioGainCallback()4692 private HalAudioGainCallback getHalAudioGainCallback() { 4693 ArgumentCaptor<HalAudioGainCallback> captor = ArgumentCaptor.forClass( 4694 HalAudioGainCallback.class); 4695 verify(mAudioControlWrapperAidl).registerAudioGainCallback(captor.capture()); 4696 return captor.getValue(); 4697 } 4698 createHalAudioDeviceInfo(int id, String name, int minVal, int maxVal, int defaultVal, int stepVal, int type, String address)4699 private HalAudioDeviceInfo createHalAudioDeviceInfo(int id, String name, int minVal, 4700 int maxVal, int defaultVal, int stepVal, int type, String address) { 4701 AudioPortDeviceExt deviceExt = new AudioPortDeviceExt(); 4702 deviceExt.device = new AudioDevice(); 4703 deviceExt.device.type = new AudioDeviceDescription(); 4704 deviceExt.device.type.type = type; 4705 deviceExt.device.type.connection = CONNECTION_BUS; 4706 deviceExt.device.address = AudioDeviceAddress.id(address); 4707 AudioPort audioPort = new AudioPort(); 4708 audioPort.id = id; 4709 audioPort.name = name; 4710 audioPort.gains = new android.media.audio.common.AudioGain[] { 4711 new android.media.audio.common.AudioGain() {{ 4712 mode = JOINT; 4713 minValue = minVal; 4714 maxValue = maxVal; 4715 defaultValue = defaultVal; 4716 stepValue = stepVal; 4717 }} 4718 }; 4719 audioPort.ext = AudioPortExt.device(deviceExt); 4720 return new HalAudioDeviceInfo(audioPort); 4721 } 4722 getHalModuleChangeCallback()4723 private HalAudioModuleChangeCallback getHalModuleChangeCallback() { 4724 ArgumentCaptor<HalAudioModuleChangeCallback> captor = ArgumentCaptor.forClass( 4725 HalAudioModuleChangeCallback.class); 4726 verify(mAudioControlWrapperAidl).setModuleChangeCallback(captor.capture()); 4727 return captor.getValue(); 4728 } 4729 getCarAudioPlaybackCallback()4730 private AudioPlaybackCallback getCarAudioPlaybackCallback() { 4731 ArgumentCaptor<AudioPlaybackCallback> captor = ArgumentCaptor.forClass( 4732 AudioPlaybackCallback.class); 4733 verify(mAudioManager).registerAudioPlaybackCallback(captor.capture(), any()); 4734 return captor.getValue(); 4735 } 4736 getAudioKeyEventListener()4737 private CarInputService.KeyEventListener getAudioKeyEventListener() { 4738 ArgumentCaptor<CarInputService.KeyEventListener> captor = 4739 ArgumentCaptor.forClass(CarInputService.KeyEventListener.class); 4740 verify(mMockCarInputService).registerKeyEventListener(captor.capture(), any()); 4741 return captor.getValue(); 4742 } 4743 requestHalAudioFocus(int usage)4744 private void requestHalAudioFocus(int usage) { 4745 ArgumentCaptor<HalFocusListener> captor = 4746 ArgumentCaptor.forClass(HalFocusListener.class); 4747 verify(mAudioControlWrapperAidl).registerFocusListener(captor.capture()); 4748 HalFocusListener halFocusListener = captor.getValue(); 4749 halFocusListener.requestAudioFocus(usage, PRIMARY_AUDIO_ZONE, 4750 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); 4751 } 4752 mockActivePlayback()4753 private void mockActivePlayback() { 4754 AudioPlaybackCallback callback = getCarAudioPlaybackCallback(); 4755 callback.onPlaybackConfigChanged(List.of(getPlaybackConfig())); 4756 } 4757 getPlaybackConfig()4758 private AudioPlaybackConfiguration getPlaybackConfig() { 4759 AudioAttributes audioAttributes = new AudioAttributes.Builder() 4760 .setUsage(USAGE_MEDIA).build(); 4761 AudioPlaybackConfiguration config = mock(AudioPlaybackConfiguration.class); 4762 when(config.getAudioAttributes()).thenReturn(audioAttributes); 4763 when(config.getAudioDeviceInfo()).thenReturn(mMediaOutputDevice); 4764 when(config.isActive()).thenReturn(true); 4765 4766 return config; 4767 } 4768 getCarAudioServiceWithoutMirroring()4769 private CarAudioService getCarAudioServiceWithoutMirroring() { 4770 AudioDeviceInfo[] outputDevices = generateOutputDeviceInfos(); 4771 when(mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)).thenReturn(outputDevices); 4772 CarAudioService carAudioService = 4773 new CarAudioService(mMockContext, mTemporaryAudioConfigurationWithoutMirroringFile 4774 .getFile().getAbsolutePath(), mCarVolumeCallbackHandler); 4775 carAudioService.init(); 4776 return carAudioService; 4777 } 4778 getCarAudioServiceUsingCoreAudioRoutingAndVolume()4779 private CarAudioService getCarAudioServiceUsingCoreAudioRoutingAndVolume() { 4780 when(mMockResources.getBoolean(audioUseCoreVolume)) 4781 .thenReturn(/* audioUseCoreVolume= */ true); 4782 when(mMockResources.getBoolean(audioUseCoreRouting)) 4783 .thenReturn(/* audioUseCoreRouting= */ true); 4784 CarAudioService useCoreAudioCarAudioService = 4785 new CarAudioService(mMockContext, 4786 mTemporaryAudioConfigurationUsingCoreAudioFile.getFile().getAbsolutePath(), 4787 mCarVolumeCallbackHandler); 4788 useCoreAudioCarAudioService.init(); 4789 return useCoreAudioCarAudioService; 4790 } 4791 mockGrantCarControlAudioSettingsPermission()4792 private void mockGrantCarControlAudioSettingsPermission() { 4793 mockContextCheckCallingOrSelfPermission(mMockContext, 4794 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS, PERMISSION_GRANTED); 4795 } 4796 mockDenyCarControlAudioSettingsPermission()4797 private void mockDenyCarControlAudioSettingsPermission() { 4798 mockContextCheckCallingOrSelfPermission(mMockContext, 4799 PERMISSION_CAR_CONTROL_AUDIO_SETTINGS, PERMISSION_DENIED); 4800 } 4801 mockDenyCarControlAudioVolumePermission()4802 private void mockDenyCarControlAudioVolumePermission() { 4803 mockContextCheckCallingOrSelfPermission(mMockContext, 4804 PERMISSION_CAR_CONTROL_AUDIO_VOLUME, PERMISSION_DENIED); 4805 } 4806 generateInputDeviceInfos()4807 private AudioDeviceInfo[] generateInputDeviceInfos() { 4808 mMicrophoneInputDevice = new AudioDeviceInfoBuilder() 4809 .setAddressName(PRIMARY_ZONE_MICROPHONE_ADDRESS) 4810 .setType(TYPE_BUILTIN_MIC) 4811 .setIsSource(true) 4812 .build(); 4813 mFmTunerInputDevice = new AudioDeviceInfoBuilder() 4814 .setAddressName(PRIMARY_ZONE_FM_TUNER_ADDRESS) 4815 .setType(TYPE_FM_TUNER) 4816 .setIsSource(true) 4817 .build(); 4818 return new AudioDeviceInfo[]{mMicrophoneInputDevice, mFmTunerInputDevice}; 4819 } 4820 generateOutputDeviceInfos()4821 private AudioDeviceInfo[] generateOutputDeviceInfos() { 4822 mMediaOutputDevice = new AudioDeviceInfoBuilder() 4823 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4824 .setAddressName(MEDIA_TEST_DEVICE) 4825 .build(); 4826 return new AudioDeviceInfo[] { 4827 mMediaOutputDevice, 4828 new AudioDeviceInfoBuilder() 4829 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4830 .setAddressName(NAVIGATION_TEST_DEVICE) 4831 .build(), 4832 new AudioDeviceInfoBuilder() 4833 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4834 .setAddressName(CALL_TEST_DEVICE) 4835 .build(), 4836 new AudioDeviceInfoBuilder() 4837 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4838 .setAddressName(SYSTEM_BUS_DEVICE) 4839 .build(), 4840 new AudioDeviceInfoBuilder() 4841 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4842 .setAddressName(NOTIFICATION_TEST_DEVICE) 4843 .build(), 4844 new AudioDeviceInfoBuilder() 4845 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4846 .setAddressName(VOICE_TEST_DEVICE) 4847 .build(), 4848 new AudioDeviceInfoBuilder() 4849 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4850 .setAddressName(RING_TEST_DEVICE) 4851 .build(), 4852 new AudioDeviceInfoBuilder() 4853 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4854 .setAddressName(ALARM_TEST_DEVICE) 4855 .build(), 4856 new AudioDeviceInfoBuilder() 4857 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4858 .setAddressName(SECONDARY_TEST_DEVICE_CONFIG_0) 4859 .build(), 4860 new AudioDeviceInfoBuilder() 4861 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4862 .setAddressName(SECONDARY_TEST_DEVICE_CONFIG_1_0) 4863 .build(), 4864 new AudioDeviceInfoBuilder() 4865 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4866 .setAddressName(SECONDARY_TEST_DEVICE_CONFIG_1_1) 4867 .build(), 4868 new AudioDeviceInfoBuilder() 4869 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4870 .setAddressName(TERTIARY_TEST_DEVICE_1) 4871 .build(), 4872 new AudioDeviceInfoBuilder() 4873 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4874 .setAddressName(TERTIARY_TEST_DEVICE_2) 4875 .build(), 4876 new AudioDeviceInfoBuilder() 4877 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4878 .setAddressName(QUATERNARY_TEST_DEVICE_1) 4879 .build(), 4880 new AudioDeviceInfoBuilder() 4881 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4882 .setAddressName(OEM_TEST_DEVICE) 4883 .build(), 4884 new AudioDeviceInfoBuilder() 4885 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4886 .setAddressName(MIRROR_TEST_DEVICE).build(), 4887 new AudioDeviceInfoBuilder() 4888 .setAudioGains(new AudioGain[] {new GainBuilder().build()}) 4889 .setAddressName(TEST_REAR_ROW_3_DEVICE).build(), 4890 }; 4891 } 4892 mockCoreAudioRoutingAndVolume()4893 private void mockCoreAudioRoutingAndVolume() { 4894 doReturn(CoreAudioRoutingUtils.getProductStrategies()) 4895 .when(() -> AudioManager.getAudioProductStrategies()); 4896 doReturn(CoreAudioRoutingUtils.getVolumeGroups()) 4897 .when(() -> AudioManager.getAudioVolumeGroups()); 4898 4899 when(mAudioManager.getVolumeGroupIdForAttributes(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES)) 4900 .thenReturn(CoreAudioRoutingUtils.MUSIC_GROUP_ID); 4901 when(mAudioManager.getMinVolumeIndexForAttributes( 4902 eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 4903 .thenReturn(CoreAudioRoutingUtils.MUSIC_MIN_INDEX); 4904 when(mAudioManager.getMaxVolumeIndexForAttributes( 4905 eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 4906 .thenReturn(CoreAudioRoutingUtils.MUSIC_MAX_INDEX); 4907 when(mAudioManager.getVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES))) 4908 .thenReturn(CoreAudioRoutingUtils.MUSIC_AM_INIT_INDEX); 4909 when(mAudioManager.getLastAudibleVolumeForVolumeGroup(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 4910 .thenReturn(CoreAudioRoutingUtils.MUSIC_AM_INIT_INDEX); 4911 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.MUSIC_GROUP_ID)) 4912 .thenReturn(false); 4913 4914 when(mAudioManager.getVolumeGroupIdForAttributes(CoreAudioRoutingUtils.NAV_ATTRIBUTES)) 4915 .thenReturn(CoreAudioRoutingUtils.NAV_GROUP_ID); 4916 when(mAudioManager.getMinVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.NAV_ATTRIBUTES))) 4917 .thenReturn(CoreAudioRoutingUtils.NAV_MIN_INDEX); 4918 when(mAudioManager.getMaxVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.NAV_ATTRIBUTES))) 4919 .thenReturn(CoreAudioRoutingUtils.NAV_MAX_INDEX); 4920 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.NAV_GROUP_ID)) 4921 .thenReturn(false); 4922 4923 when(mAudioManager.getVolumeGroupIdForAttributes(CoreAudioRoutingUtils.OEM_ATTRIBUTES)) 4924 .thenReturn(CoreAudioRoutingUtils.OEM_GROUP_ID); 4925 when(mAudioManager.getMinVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.OEM_ATTRIBUTES))) 4926 .thenReturn(CoreAudioRoutingUtils.OEM_MIN_INDEX); 4927 when(mAudioManager.getMaxVolumeIndexForAttributes(eq(CoreAudioRoutingUtils.OEM_ATTRIBUTES))) 4928 .thenReturn(CoreAudioRoutingUtils.OEM_MAX_INDEX); 4929 when(mAudioManager.isVolumeGroupMuted(CoreAudioRoutingUtils.OEM_GROUP_ID)) 4930 .thenReturn(false); 4931 4932 doReturn(CoreAudioRoutingUtils.MUSIC_GROUP_ID) 4933 .when(() -> CoreAudioHelper.getVolumeGroupIdForAudioAttributes( 4934 CoreAudioRoutingUtils.MUSIC_ATTRIBUTES)); 4935 doReturn(CoreAudioRoutingUtils.MUSIC_ATTRIBUTES) 4936 .when(() -> CoreAudioHelper.selectAttributesForVolumeGroupName( 4937 CoreAudioRoutingUtils.MUSIC_GROUP_NAME)); 4938 4939 doReturn(CoreAudioRoutingUtils.NAV_GROUP_ID) 4940 .when(() -> CoreAudioHelper.getVolumeGroupIdForAudioAttributes( 4941 CoreAudioRoutingUtils.NAV_ATTRIBUTES)); 4942 doReturn(CoreAudioRoutingUtils.NAV_ATTRIBUTES) 4943 .when(() -> CoreAudioHelper.selectAttributesForVolumeGroupName( 4944 CoreAudioRoutingUtils.NAV_GROUP_NAME)); 4945 4946 doReturn(CoreAudioRoutingUtils.OEM_GROUP_ID) 4947 .when(() -> CoreAudioHelper.getVolumeGroupIdForAudioAttributes( 4948 CoreAudioRoutingUtils.OEM_ATTRIBUTES)); 4949 doReturn(CoreAudioRoutingUtils.OEM_ATTRIBUTES) 4950 .when(() -> CoreAudioHelper.selectAttributesForVolumeGroupName( 4951 CoreAudioRoutingUtils.OEM_GROUP_NAME)); 4952 } 4953 createAudioFocusInfoForMedia()4954 private static AudioFocusInfo createAudioFocusInfoForMedia() { 4955 return createAudioFocusInfoForMedia(MEDIA_APP_UID); 4956 } 4957 createAudioFocusInfoForMedia(int uid)4958 private static AudioFocusInfo createAudioFocusInfoForMedia(int uid) { 4959 AudioAttributes.Builder builder = new AudioAttributes.Builder(); 4960 builder.setUsage(USAGE_MEDIA); 4961 4962 return new AudioFocusInfo(builder.build(), uid, MEDIA_CLIENT_ID, 4963 MEDIA_PACKAGE_NAME, AUDIOFOCUS_GAIN, AUDIOFOCUS_LOSS, MEDIA_EMPTY_FLAG, SDK_INT); 4964 } 4965 getFocusChanges(AudioFocusInfo info)4966 private List<Integer> getFocusChanges(AudioFocusInfo info) { 4967 ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class); 4968 verify(mAudioManager, atLeastOnce()).dispatchAudioFocusChange(eq(info), captor.capture(), 4969 any()); 4970 return captor.getAllValues(); 4971 } 4972 verifyMediaDuckingInfoInZone(ArgumentCaptor<List<CarDuckingInfo>> carDuckingInfosCaptor, int zoneId, String message)4973 private void verifyMediaDuckingInfoInZone(ArgumentCaptor<List<CarDuckingInfo>> 4974 carDuckingInfosCaptor, int zoneId, String message) { 4975 expectWithMessage("Zone size of notified ducking info " + message) 4976 .that(carDuckingInfosCaptor.getValue().size()).isEqualTo(1); 4977 CarDuckingInfo duckingInfo = carDuckingInfosCaptor.getValue().get(0); 4978 expectWithMessage("Ducking info zone id " + message) 4979 .that(duckingInfo.mZoneId).isEqualTo(zoneId); 4980 expectWithMessage("Audio attributes holding focus " + message) 4981 .that(CarHalAudioUtils.metadataToAudioAttributes(duckingInfo 4982 .mPlaybackMetaDataHoldingFocus)) 4983 .containsExactly(CarAudioContext.getAudioAttributeFromUsage(USAGE_MEDIA)); 4984 } 4985 getZoneConfigToSwitch(int zoneId)4986 private CarAudioZoneConfigInfo getZoneConfigToSwitch(int zoneId) { 4987 CarAudioZoneConfigInfo currentZoneConfigInfo = 4988 mCarAudioService.getCurrentAudioZoneConfigInfo(zoneId); 4989 List<CarAudioZoneConfigInfo> zoneConfigInfos = 4990 mCarAudioService.getAudioZoneConfigInfos(zoneId); 4991 4992 for (int index = 0; index < zoneConfigInfos.size(); index++) { 4993 if (!currentZoneConfigInfo.equals(zoneConfigInfos.get(index))) { 4994 return zoneConfigInfos.get(index); 4995 } 4996 } 4997 return null; 4998 } 4999 5000 private static final class TestPrimaryZoneMediaAudioRequestCallback extends 5001 IPrimaryZoneMediaAudioRequestCallback.Stub { 5002 private long mRequestId = INVALID_REQUEST_ID; 5003 private CarOccupantZoneManager.OccupantZoneInfo mInfo; 5004 private CountDownLatch mStatusLatch = new CountDownLatch(1); 5005 private int mStatus; 5006 private DeathRecipient mDeathRecipient; 5007 5008 @Override linkToDeath(@onNull DeathRecipient recipient, int flags)5009 public void linkToDeath(@NonNull DeathRecipient recipient, int flags) { 5010 mDeathRecipient = recipient; 5011 super.linkToDeath(recipient, flags); 5012 } 5013 5014 @Override onRequestMediaOnPrimaryZone(CarOccupantZoneManager.OccupantZoneInfo info, long requestId)5015 public void onRequestMediaOnPrimaryZone(CarOccupantZoneManager.OccupantZoneInfo info, 5016 long requestId) { 5017 mInfo = info; 5018 mRequestId = requestId; 5019 mStatusLatch.countDown(); 5020 } 5021 5022 @Override onMediaAudioRequestStatusChanged( @onNull CarOccupantZoneManager.OccupantZoneInfo info, long requestId, int status)5023 public void onMediaAudioRequestStatusChanged( 5024 @NonNull CarOccupantZoneManager.OccupantZoneInfo info, 5025 long requestId, int status) { 5026 mInfo = info; 5027 mRequestId = requestId; 5028 mStatus = status; 5029 mStatusLatch.countDown(); 5030 } 5031 waitForCallback()5032 private void waitForCallback() throws Exception { 5033 mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 5034 } 5035 reset()5036 public void reset() { 5037 mInfo = null; 5038 mRequestId = INVALID_REQUEST_ID; 5039 mStatus = INVALID_STATUS; 5040 mStatusLatch = new CountDownLatch(1); 5041 } 5042 } 5043 5044 private static final class TestMediaRequestStatusCallback extends 5045 IMediaAudioRequestStatusCallback.Stub { 5046 private long mRequestId = INVALID_REQUEST_ID; 5047 private CarOccupantZoneManager.OccupantZoneInfo mInfo; 5048 private int mStatus; 5049 private CountDownLatch mStatusLatch = new CountDownLatch(1); 5050 5051 @Override onMediaAudioRequestStatusChanged( @onNull CarOccupantZoneManager.OccupantZoneInfo info, long requestId, @CarAudioManager.MediaAudioRequestStatus int status)5052 public void onMediaAudioRequestStatusChanged( 5053 @NonNull CarOccupantZoneManager.OccupantZoneInfo info, 5054 long requestId, @CarAudioManager.MediaAudioRequestStatus int status) 5055 throws RemoteException { 5056 mInfo = info; 5057 mRequestId = requestId; 5058 mStatus = status; 5059 mStatusLatch.countDown(); 5060 } 5061 waitForCallback()5062 private void waitForCallback() throws Exception { 5063 mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 5064 } 5065 reset()5066 private void reset() { 5067 mInfo = null; 5068 mRequestId = INVALID_REQUEST_ID; 5069 mStatus = INVALID_STATUS; 5070 mStatusLatch = new CountDownLatch(1); 5071 } 5072 } 5073 5074 private static final class TestAudioZonesMirrorStatusCallbackCallback extends 5075 IAudioZonesMirrorStatusCallback.Stub { 5076 5077 private static final long TEST_CALLBACK_TIMEOUT_MS = 300; 5078 5079 private List<int[]> mZoneIds = new ArrayList<>(); 5080 private List<Integer> mStatus = new ArrayList<>(); 5081 private int mNumberOfCalls = 0; 5082 private CountDownLatch mStatusLatch; 5083 TestAudioZonesMirrorStatusCallbackCallback(int count)5084 private TestAudioZonesMirrorStatusCallbackCallback(int count) { 5085 mStatusLatch = new CountDownLatch(count); 5086 } 5087 5088 @Override onAudioZonesMirrorStatusChanged(int[] zoneIds, int status)5089 public void onAudioZonesMirrorStatusChanged(int[] zoneIds, int status) { 5090 mZoneIds.add(zoneIds); 5091 mStatus.add(status); 5092 mNumberOfCalls++; 5093 mStatusLatch.countDown(); 5094 } 5095 waitForCallback()5096 private void waitForCallback() throws Exception { 5097 mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 5098 } 5099 reset(int count)5100 public void reset(int count) { 5101 mStatusLatch = new CountDownLatch(count); 5102 } 5103 getLastZoneIds()5104 private int[] getLastZoneIds() { 5105 return mZoneIds.get(mZoneIds.size() - 1); 5106 } 5107 getZoneIds(int index)5108 private int[] getZoneIds(int index) { 5109 return mZoneIds.get(index); 5110 } 5111 getLastStatus()5112 public int getLastStatus() { 5113 return mStatus.get(mStatus.size() - 1); 5114 } 5115 getStatus(int index)5116 public int getStatus(int index) { 5117 return mStatus.get(index); 5118 } 5119 } 5120 5121 private static final class SwitchAudioZoneConfigCallbackImpl extends 5122 ISwitchAudioZoneConfigCallback.Stub { 5123 private CountDownLatch mStatusLatch = new CountDownLatch(1); 5124 private CarAudioZoneConfigInfo mZoneConfig; 5125 private boolean mIsSuccessful; 5126 5127 @Override onAudioZoneConfigSwitched(CarAudioZoneConfigInfo zoneConfig, boolean isSuccessful)5128 public void onAudioZoneConfigSwitched(CarAudioZoneConfigInfo zoneConfig, 5129 boolean isSuccessful) { 5130 mZoneConfig = zoneConfig; 5131 mIsSuccessful = isSuccessful; 5132 mStatusLatch.countDown(); 5133 } 5134 waitForCallback()5135 private void waitForCallback() throws Exception { 5136 mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 5137 } 5138 getZoneConfig()5139 CarAudioZoneConfigInfo getZoneConfig() { 5140 return mZoneConfig; 5141 } 5142 getSwitchStatus()5143 boolean getSwitchStatus() { 5144 return mIsSuccessful; 5145 } 5146 } 5147 5148 private static final class CarVolumeEventCallbackImpl extends ICarVolumeEventCallback.Stub { 5149 private CountDownLatch mStatusLatch = new CountDownLatch(1); 5150 private List<CarVolumeGroupEvent> mVolumeGroupEvents; 5151 5152 @Override onVolumeGroupEvent(List<CarVolumeGroupEvent> volumeGroupEvents)5153 public void onVolumeGroupEvent(List<CarVolumeGroupEvent> volumeGroupEvents) { 5154 mVolumeGroupEvents = volumeGroupEvents; 5155 mStatusLatch.countDown(); 5156 } 5157 5158 @Override onMasterMuteChanged(int zoneId, int flags)5159 public void onMasterMuteChanged(int zoneId, int flags) { 5160 mStatusLatch.countDown(); 5161 } 5162 waitForCallback()5163 private boolean waitForCallback() throws Exception { 5164 return mStatusLatch.await(TEST_CALLBACK_TIMEOUT_MS, TimeUnit.MILLISECONDS); 5165 } 5166 getVolumeGroupEvents()5167 List<CarVolumeGroupEvent> getVolumeGroupEvents() { 5168 return mVolumeGroupEvents; 5169 } 5170 reset()5171 public void reset() { 5172 mStatusLatch = new CountDownLatch(1); 5173 } 5174 } 5175 } 5176