CarAudioExtFocusTest.java revision 32b6382264510577126f9723337a7f48332b2ae3
1/* 2 * Copyright (C) 2016 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 */ 16package com.android.car.test; 17 18import android.car.Car; 19import android.car.media.CarAudioManager; 20import android.car.test.VehicleHalEmulator.VehicleHalPropertyHandler; 21import android.content.Context; 22import android.media.AudioAttributes; 23import android.media.AudioManager; 24import android.os.SystemClock; 25import android.test.suitebuilder.annotation.MediumTest; 26import android.util.Log; 27 28import com.android.car.vehiclenetwork.VehicleNetworkConsts; 29import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioContextFlag; 30import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioExtFocusFlag; 31import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusIndex; 32import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusRequest; 33import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusState; 34import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioStream; 35import com.android.car.vehiclenetwork.VehiclePropConfigUtil; 36import com.android.car.vehiclenetwork.VehiclePropValueUtil; 37import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePermissionModel; 38import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess; 39import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode; 40import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType; 41import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue; 42 43import java.util.Arrays; 44import java.util.LinkedList; 45import java.util.concurrent.Semaphore; 46import java.util.concurrent.TimeUnit; 47 48@MediumTest 49public class CarAudioExtFocusTest extends MockedCarTestBase { 50 private static final String TAG = CarAudioExtFocusTest.class.getSimpleName(); 51 52 private static final long TIMEOUT_MS = 3000; 53 54 private final VehicleHalPropertyHandler mAudioRoutingPolicyPropertyHandler = 55 new VehicleHalPropertyHandler() { 56 @Override 57 public void onPropertySet(VehiclePropValue value) { 58 //TODO 59 } 60 61 @Override 62 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 63 fail("cannot get"); 64 return null; 65 } 66 67 @Override 68 public void onPropertySubscribe(int property, float sampleRate, int zones) { 69 fail("cannot subscribe"); 70 } 71 72 @Override 73 public void onPropertyUnsubscribe(int property) { 74 fail("cannot unsubscribe"); 75 } 76 }; 77 78 private final FocusPropertyHandler mAudioFocusPropertyHandler = 79 new FocusPropertyHandler(this); 80 81 private final ExtRoutingHintPropertyHandler mExtRoutingHintPropertyHandler = 82 new ExtRoutingHintPropertyHandler(); 83 84 private static final String EXT_ROUTING_CONFIG = 85 "0:RADIO_AM_FM:0,1:RADIO_SATELLITE:0,33:CD_DVD:0," + 86 "64:com.google.test.SOMETHING_SPECIAL," + 87 "4:EXT_NAV_GUIDANCE:1," + 88 "5:AUX_IN0:0"; 89 90 private final Semaphore mWaitSemaphore = new Semaphore(0); 91 private final LinkedList<VehiclePropValue> mEvents = new LinkedList<VehiclePropValue>(); 92 private AudioManager mAudioManager; 93 private CarAudioManager mCarAudioManager; 94 95 @Override 96 protected void setUp() throws Exception { 97 super.setUp(); 98 // AudioManager should be created in main thread to get focus event. :( 99 runOnMainSync(new Runnable() { 100 @Override 101 public void run() { 102 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 103 } 104 }); 105 106 getVehicleHalEmulator().addProperty( 107 VehiclePropConfigUtil.getBuilder( 108 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY, 109 VehiclePropAccess.VEHICLE_PROP_ACCESS_WRITE, 110 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 111 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2, 112 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 113 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 114 mAudioRoutingPolicyPropertyHandler); 115 getVehicleHalEmulator().addProperty( 116 VehiclePropConfigUtil.getBuilder( 117 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, 118 VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE, 119 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 120 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4, 121 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 122 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 123 mAudioFocusPropertyHandler); 124 getVehicleHalEmulator().addStaticProperty( 125 VehiclePropConfigUtil.createStaticStringProperty( 126 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_HW_VARIANT), 127 VehiclePropValueUtil.createIntValue( 128 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_HW_VARIANT, -1, 0)); 129 getVehicleHalEmulator().addProperty( 130 VehiclePropConfigUtil.getBuilder( 131 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_EXT_ROUTING_HINT, 132 VehiclePropAccess.VEHICLE_PROP_ACCESS_WRITE, 133 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 134 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4, 135 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 136 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/). 137 setConfigString(EXT_ROUTING_CONFIG).build(), 138 mExtRoutingHintPropertyHandler); 139 getVehicleHalEmulator().start(); 140 mCarAudioManager = (CarAudioManager) getCar().getCarManager(Car.AUDIO_SERVICE); 141 assertNotNull(mCarAudioManager); 142 } 143 144 public void testExtRoutings() throws Exception { 145 String[] radioTypes = mCarAudioManager.getSupportedRadioTypes(); 146 assertNotNull(radioTypes); 147 checkStringArrayContents(new String[] {"RADIO_AM_FM", "RADIO_SATELLITE"}, radioTypes); 148 149 String[] nonRadioTypes = mCarAudioManager.getSupportedExternalSourceTypes(); 150 assertNotNull(nonRadioTypes); 151 checkStringArrayContents(new String[] {"CD_DVD", "com.google.test.SOMETHING_SPECIAL", 152 "EXT_NAV_GUIDANCE", "AUX_IN0"}, nonRadioTypes); 153 } 154 155 private void checkStringArrayContents(String[] expected, String[] actual) throws Exception { 156 Arrays.sort(expected); 157 Arrays.sort(actual); 158 assertEquals(expected.length, actual.length); 159 for (int i = 0; i < expected.length; i++) { 160 assertEquals(expected[i], actual[i]); 161 } 162 } 163 164 public void testRadioAttributeCreation() throws Exception { 165 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForRadio( 166 CarAudioManager.CAR_RADIO_TYPE_AM_FM); 167 assertNotNull(attrb); 168 169 attrb = mCarAudioManager.getAudioAttributesForRadio( 170 CarAudioManager.CAR_RADIO_TYPE_SATELLITE); 171 assertNotNull(attrb); 172 173 try { 174 attrb = mCarAudioManager.getAudioAttributesForRadio( 175 CarAudioManager.CAR_RADIO_TYPE_AM_FM_HD); 176 fail(); 177 } catch (IllegalArgumentException e) { 178 // expected 179 } 180 } 181 182 public void testExtSourceAttributeCreation() throws Exception { 183 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource( 184 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_CD_DVD); 185 assertNotNull(attrb); 186 187 attrb = mCarAudioManager.getAudioAttributesForExternalSource( 188 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE); 189 assertNotNull(attrb); 190 191 attrb = mCarAudioManager.getAudioAttributesForExternalSource( 192 "com.google.test.SOMETHING_SPECIAL"); 193 assertNotNull(attrb); 194 195 try { 196 attrb = mCarAudioManager.getAudioAttributesForExternalSource( 197 CarAudioManager.CAR_RADIO_TYPE_AM_FM_HD); 198 fail(); 199 } catch (IllegalArgumentException e) { 200 // expected 201 } 202 } 203 204 public void testRadioAmFmGainFocus() throws Exception { 205 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForRadio( 206 CarAudioManager.CAR_RADIO_TYPE_AM_FM); 207 assertNotNull(attrb); 208 checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {1, 0, 0, 0}, 209 0, VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 210 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG); 211 } 212 213 public void testRadioSatelliteGainFocus() throws Exception { 214 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForRadio( 215 CarAudioManager.CAR_RADIO_TYPE_SATELLITE); 216 assertNotNull(attrb); 217 checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {2, 0, 0, 0}, 218 0, VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 219 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG); 220 } 221 222 public void testCdGainFocus() throws Exception { 223 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource( 224 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_CD_DVD); 225 assertNotNull(attrb); 226 checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0, 2, 0, 0}, 227 0, VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 228 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_CD_ROM_FLAG); 229 } 230 231 public void testAuxInFocus() throws Exception { 232 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource( 233 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_AUX_IN0); 234 assertNotNull(attrb); 235 checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0x1<<5, 0, 0, 0}, 236 0, VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 237 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_AUX_AUDIO_FLAG); 238 } 239 240 public void testExtNavInFocus() throws Exception { 241 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource( 242 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE); 243 assertNotNull(attrb); 244 checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0x1<<4, 0, 0, 0}, 245 0, VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 246 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_EXT_SOURCE_FLAG); 247 } 248 249 public void testCustomInFocus() throws Exception { 250 AudioAttributes attrb = mCarAudioManager.getAudioAttributesForExternalSource( 251 "com.google.test.SOMETHING_SPECIAL"); 252 assertNotNull(attrb); 253 checkSingleRequestRelease(attrb, AudioManager.AUDIOFOCUS_GAIN, new int[] {0, 0, 1, 0}, 254 0, VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 255 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_EXT_SOURCE_FLAG); 256 } 257 258 public void testMediaNavFocus() throws Exception { 259 //music start 260 AudioFocusListener listenerMusic = new AudioFocusListener(); 261 int res = mAudioManager.requestAudioFocus(listenerMusic, 262 AudioManager.STREAM_MUSIC, 263 AudioManager.AUDIOFOCUS_GAIN); 264 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 265 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 266 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 267 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 268 assertEquals(0, request[2]); 269 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 270 assertArrayEquals(new int[] {0, 0, 0, 0}, 271 mExtRoutingHintPropertyHandler.getLastHint()); 272 mAudioFocusPropertyHandler.sendAudioFocusState( 273 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 274 request[1], 275 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 276 277 // nav guidance start 278 AudioFocusListener listenerNav = new AudioFocusListener(); 279 AudioAttributes navAttrib = (new AudioAttributes.Builder()). 280 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION). 281 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 282 build(); 283 res = mAudioManager.requestAudioFocus(listenerNav, navAttrib, 284 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 285 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 286 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 287 assertEquals(0x3, request[1]); 288 assertEquals(0, request[2]); 289 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG | 290 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 291 assertArrayEquals(new int[] {0, 0, 0, 0}, 292 mExtRoutingHintPropertyHandler.getLastHint()); 293 mAudioFocusPropertyHandler.sendAudioFocusState( 294 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, request[1], 295 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 296 297 // nav guidance done 298 mAudioManager.abandonAudioFocus(listenerNav); 299 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 300 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 301 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 302 assertEquals(0, request[2]); 303 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 304 assertArrayEquals(new int[] {0, 0, 0, 0}, 305 mExtRoutingHintPropertyHandler.getLastHint()); 306 mAudioFocusPropertyHandler.sendAudioFocusState( 307 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, request[1], 308 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 309 310 // music done 311 mAudioManager.abandonAudioFocus(listenerMusic); 312 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 313 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 314 assertEquals(0, request[1]); 315 assertEquals(0, request[2]); 316 assertEquals(0, request[3]); 317 assertArrayEquals(new int[] {0, 0, 0, 0}, 318 mExtRoutingHintPropertyHandler.getLastHint()); 319 mAudioFocusPropertyHandler.sendAudioFocusState( 320 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, request[1], 321 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 322 } 323 324 public void testMediaExternalMediaNavFocus() throws Exception { 325 // android music 326 AudioFocusListener listenerMusic = new AudioFocusListener(); 327 int res = mAudioManager.requestAudioFocus(listenerMusic, 328 AudioManager.STREAM_MUSIC, 329 AudioManager.AUDIOFOCUS_GAIN); 330 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 331 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 332 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 333 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 334 assertEquals(0, request[2]); 335 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 336 assertArrayEquals(new int[] {0, 0, 0, 0}, 337 mExtRoutingHintPropertyHandler.getLastHint()); 338 mAudioFocusPropertyHandler.sendAudioFocusState( 339 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 340 request[1], 341 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 342 343 // car plays external media (=outside Android) 344 mAudioFocusPropertyHandler.sendAudioFocusState( 345 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 346 0, 347 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG); 348 int focusChange = listenerMusic.waitAndGetFocusChange(TIMEOUT_MS); 349 assertEquals(AudioManager.AUDIOFOCUS_LOSS, focusChange); 350 351 // nav guidance start 352 AudioFocusListener listenerNav = new AudioFocusListener(); 353 AudioAttributes navAttrib = (new AudioAttributes.Builder()). 354 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION). 355 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 356 build(); 357 res = mAudioManager.requestAudioFocus(listenerNav, navAttrib, 358 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 359 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 360 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK, 361 request[0]); 362 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, request[1]); 363 assertEquals(0, request[2]); 364 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 365 assertArrayEquals(new int[] {0, 0, 0, 0}, 366 mExtRoutingHintPropertyHandler.getLastHint()); 367 mAudioFocusPropertyHandler.sendAudioFocusState( 368 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT, 369 0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, 370 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG); 371 372 // nav guidance ends 373 mAudioManager.abandonAudioFocus(listenerNav); 374 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 375 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 376 assertEquals(0, request[1]); 377 assertEquals(0, request[2]); 378 assertEquals(0, request[3]); 379 assertArrayEquals(new int[] {0, 0, 0, 0}, 380 mExtRoutingHintPropertyHandler.getLastHint()); 381 mAudioFocusPropertyHandler.sendAudioFocusState( 382 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 383 0, 384 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG); 385 386 // now ends external play 387 mAudioFocusPropertyHandler.sendAudioFocusState( 388 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 389 0, 390 0); 391 mAudioManager.abandonAudioFocus(listenerMusic); 392 //TODO how to check this? 393 } 394 395 public void testExternalRadioExternalNav() throws Exception { 396 // android radio 397 AudioFocusListener listenerRadio = new AudioFocusListener(); 398 CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager( 399 Car.AUDIO_SERVICE); 400 assertNotNull(carAudioManager); 401 AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage( 402 CarAudioManager.CAR_AUDIO_USAGE_RADIO); 403 int res = mAudioManager.requestAudioFocus(listenerRadio, 404 radioAttributes, AudioManager.AUDIOFOCUS_GAIN, 0); 405 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 406 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 407 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 408 assertEquals(0, request[1]); 409 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 410 request[2]); 411 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG, request[3]); 412 assertArrayEquals(new int[] {1, 0, 0, 0}, 413 mExtRoutingHintPropertyHandler.getLastHint()); 414 mAudioFocusPropertyHandler.sendAudioFocusState( 415 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 416 0, 417 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 418 419 //external nav 420 AudioFocusListener listenerNav = new AudioFocusListener(); 421 AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource( 422 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE); 423 res = mAudioManager.requestAudioFocus(listenerNav, 424 extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 425 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 426 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 427 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 428 request[0]); 429 assertEquals(0, request[1]); 430 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 431 request[2]); 432 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG | 433 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_EXT_SOURCE_FLAG, request[3]); 434 assertArrayEquals(new int[] {1 | 1<<4, 0, 0, 0}, 435 mExtRoutingHintPropertyHandler.getLastHint()); 436 mAudioFocusPropertyHandler.sendAudioFocusState( 437 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 438 0, 439 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 440 441 mAudioManager.abandonAudioFocus(listenerNav); 442 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 443 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 444 assertEquals(0, request[1]); 445 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 446 request[2]); 447 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG, request[3]); 448 assertArrayEquals(new int[] {1, 0, 0, 0}, 449 mExtRoutingHintPropertyHandler.getLastHint()); 450 mAudioFocusPropertyHandler.sendAudioFocusState( 451 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 452 0, 453 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 454 455 mAudioManager.abandonAudioFocus(listenerRadio); 456 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 457 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 458 assertEquals(0, request[1]); 459 assertEquals(0, request[2]); 460 assertEquals(0, request[3]); 461 assertArrayEquals(new int[] {0, 0, 0, 0}, 462 mExtRoutingHintPropertyHandler.getLastHint()); 463 mAudioFocusPropertyHandler.sendAudioFocusState( 464 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 465 0, 466 0); 467 } 468 469 public void testMediaExternalNav() throws Exception { 470 // android music 471 AudioFocusListener listenerMusic = new AudioFocusListener(); 472 int res = mAudioManager.requestAudioFocus(listenerMusic, 473 AudioManager.STREAM_MUSIC, 474 AudioManager.AUDIOFOCUS_GAIN); 475 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 476 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 477 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 478 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 479 assertEquals(0, request[2]); 480 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 481 assertArrayEquals(new int[] {0, 0, 0, 0}, 482 mExtRoutingHintPropertyHandler.getLastHint()); 483 mAudioFocusPropertyHandler.sendAudioFocusState( 484 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 485 request[1], 486 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 487 488 //external nav 489 AudioFocusListener listenerNav = new AudioFocusListener(); 490 AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource( 491 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE); 492 res = mAudioManager.requestAudioFocus(listenerNav, 493 extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 494 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 495 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 496 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 497 request[0]); 498 assertEquals(0x1, request[1]); 499 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 500 request[2]); 501 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG | 502 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_EXT_SOURCE_FLAG, request[3]); 503 assertArrayEquals(new int[] {1<<4, 0, 0, 0}, 504 mExtRoutingHintPropertyHandler.getLastHint()); 505 mAudioFocusPropertyHandler.sendAudioFocusState( 506 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 507 0x1, 508 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 509 510 mAudioManager.abandonAudioFocus(listenerNav); 511 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 512 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 513 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 514 assertEquals(0, request[2]); 515 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 516 assertArrayEquals(new int[] {0, 0, 0, 0}, 517 mExtRoutingHintPropertyHandler.getLastHint()); 518 mAudioFocusPropertyHandler.sendAudioFocusState( 519 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 520 request[1], 521 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 522 523 mAudioManager.abandonAudioFocus(listenerMusic); 524 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 525 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 526 assertEquals(0, request[1]); 527 assertEquals(0, request[2]); 528 assertEquals(0, request[3]); 529 assertArrayEquals(new int[] {0, 0, 0, 0}, 530 mExtRoutingHintPropertyHandler.getLastHint()); 531 mAudioFocusPropertyHandler.sendAudioFocusState( 532 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 533 0, 534 0); 535 } 536 537 /** 538 * Test internal nav - external nav case. 539 * External nav takes the same physical stream as internal nav. So internal nav 540 * will be lost while external nav is played. This should not happen in real case when 541 * AppFocus is used, but this test is to make sure that audio focus works as expected. 542 */ 543 public void testNavExternalNav() throws Exception { 544 // android nav 545 AudioFocusListener listenerIntNav = new AudioFocusListener(); 546 AudioAttributes intNavAttributes = mCarAudioManager.getAudioAttributesForCarUsage( 547 CarAudioManager.CAR_AUDIO_USAGE_NAVIGATION_GUIDANCE); 548 int res = mAudioManager.requestAudioFocus(listenerIntNav, intNavAttributes, 549 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 550 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 551 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 552 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK, 553 request[0]); 554 assertEquals(0x2, request[1]); 555 assertEquals(0, request[2]); 556 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 557 assertArrayEquals(new int[] {0, 0, 0, 0}, 558 mExtRoutingHintPropertyHandler.getLastHint()); 559 mAudioFocusPropertyHandler.sendAudioFocusState( 560 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 561 request[1], 562 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 563 564 //external nav 565 AudioFocusListener listenerExtNav = new AudioFocusListener(); 566 AudioAttributes extNavAttributes = mCarAudioManager.getAudioAttributesForExternalSource( 567 CarAudioManager.CAR_EXTERNAL_SOURCE_TYPE_EXT_NAV_GUIDANCE); 568 res = mAudioManager.requestAudioFocus(listenerExtNav, 569 extNavAttributes, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 570 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 571 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 572 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 573 request[0]); 574 assertEquals(0, request[1]); 575 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 576 request[2]); 577 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_EXT_SOURCE_FLAG, request[3]); 578 assertArrayEquals(new int[] {1<<4, 0, 0, 0}, 579 mExtRoutingHintPropertyHandler.getLastHint()); 580 mAudioFocusPropertyHandler.sendAudioFocusState( 581 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 582 0x1, 583 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 584 585 mAudioManager.abandonAudioFocus(listenerExtNav); 586 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 587 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK, 588 request[0]); 589 assertEquals(0x2, request[1]); 590 assertEquals(0, request[2]); 591 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 592 assertArrayEquals(new int[] {0, 0, 0, 0}, 593 mExtRoutingHintPropertyHandler.getLastHint()); 594 mAudioFocusPropertyHandler.sendAudioFocusState( 595 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 596 request[1], 597 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 598 599 mAudioManager.abandonAudioFocus(listenerIntNav); 600 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 601 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 602 assertEquals(0, request[1]); 603 assertEquals(0, request[2]); 604 assertEquals(0, request[3]); 605 assertArrayEquals(new int[] {0, 0, 0, 0}, 606 mExtRoutingHintPropertyHandler.getLastHint()); 607 mAudioFocusPropertyHandler.sendAudioFocusState( 608 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 609 0, 610 0); 611 } 612 613 public void testMediaExternalRadioNavMediaFocus() throws Exception { 614 // android music 615 AudioFocusListener listenerMusic = new AudioFocusListener(); 616 int res = mAudioManager.requestAudioFocus(listenerMusic, 617 AudioManager.STREAM_MUSIC, 618 AudioManager.AUDIOFOCUS_GAIN); 619 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 620 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 621 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 622 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 623 assertEquals(0, request[2]); 624 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 625 assertArrayEquals(new int[] {0, 0, 0, 0}, 626 mExtRoutingHintPropertyHandler.getLastHint()); 627 mAudioFocusPropertyHandler.sendAudioFocusState( 628 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 629 request[1], 630 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 631 632 // android radio 633 AudioFocusListener listenerRadio = new AudioFocusListener(); 634 CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager( 635 Car.AUDIO_SERVICE); 636 assertNotNull(carAudioManager); 637 AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage( 638 CarAudioManager.CAR_AUDIO_USAGE_RADIO); 639 res = mAudioManager.requestAudioFocus(listenerRadio, 640 radioAttributes, AudioManager.AUDIOFOCUS_GAIN, 0); 641 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 642 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 643 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 644 assertEquals(0, request[1]); 645 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 646 request[2]); 647 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG, request[3]); 648 assertArrayEquals(new int[] {1, 0, 0, 0}, 649 mExtRoutingHintPropertyHandler.getLastHint()); 650 mAudioFocusPropertyHandler.sendAudioFocusState( 651 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 652 0, 653 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 654 655 // nav guidance start 656 AudioFocusListener listenerNav = new AudioFocusListener(); 657 AudioAttributes navAttrib = (new AudioAttributes.Builder()). 658 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION). 659 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 660 build(); 661 res = mAudioManager.requestAudioFocus(listenerNav, navAttrib, 662 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 663 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 664 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 665 request[0]); 666 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, request[1]); 667 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 668 request[2]); 669 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG | 670 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG, request[3]); 671 assertArrayEquals(new int[] {1, 0, 0, 0}, 672 mExtRoutingHintPropertyHandler.getLastHint()); 673 mAudioFocusPropertyHandler.sendAudioFocusState( 674 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 675 0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, 676 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 677 678 // nav guidance ends 679 mAudioManager.abandonAudioFocus(listenerNav); 680 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 681 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 682 request[0]); 683 assertEquals(0, request[1]); 684 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 685 request[2]); 686 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG, request[3]); 687 assertArrayEquals(new int[] {1, 0, 0, 0}, 688 mExtRoutingHintPropertyHandler.getLastHint()); 689 mAudioFocusPropertyHandler.sendAudioFocusState( 690 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 691 0, 692 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 693 694 // ends radio. music will get the focus GAIN. 695 // Music app is supposed to stop and release focus when it has lost focus, but here just 696 // check if focus is working. 697 mAudioManager.abandonAudioFocus(listenerRadio); 698 listenerMusic.waitForFocus(TIMEOUT_MS, AudioManager.AUDIOFOCUS_GAIN); 699 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 700 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 701 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 702 assertEquals(0, request[2]); 703 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 704 assertArrayEquals(new int[] {0, 0, 0, 0}, 705 mExtRoutingHintPropertyHandler.getLastHint()); 706 mAudioFocusPropertyHandler.sendAudioFocusState( 707 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 708 0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, 709 0); 710 711 // now music release focus. 712 mAudioManager.abandonAudioFocus(listenerMusic); 713 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 714 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 715 assertEquals(0, request[1]); 716 assertEquals(0, request[2]); 717 assertEquals(0, request[3]); 718 assertArrayEquals(new int[] {0, 0, 0, 0}, 719 mExtRoutingHintPropertyHandler.getLastHint()); 720 mAudioFocusPropertyHandler.sendAudioFocusState( 721 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 722 0, 723 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 724 } 725 726 private void checkSingleRequestRelease(AudioAttributes attrb, int androidFocusToRequest, 727 int[] expectedExtRouting, int expectedStreams, 728 int expectedExtState, int expectedContexts) throws Exception { 729 AudioFocusListener lister = new AudioFocusListener(); 730 int res = mCarAudioManager.requestAudioFocus(lister, attrb, androidFocusToRequest, 0); 731 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 732 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 733 int expectedFocusRequest = VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE; 734 int response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 735 switch (androidFocusToRequest) { 736 case AudioManager.AUDIOFOCUS_GAIN: 737 expectedFocusRequest = VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN; 738 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN; 739 break; 740 case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT: 741 expectedFocusRequest = 742 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT; 743 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT; 744 break; 745 case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK: 746 expectedFocusRequest = 747 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK; 748 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT; 749 break; 750 } 751 assertEquals(expectedFocusRequest, request[0]); 752 assertEquals(expectedStreams, request[1]); 753 assertEquals(expectedExtState, request[2]); 754 assertEquals(expectedContexts, request[3]); 755 assertArrayEquals(expectedExtRouting, mExtRoutingHintPropertyHandler.getLastHint()); 756 mAudioFocusPropertyHandler.sendAudioFocusState( 757 response, 758 request[1], 759 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 760 mAudioManager.abandonAudioFocus(lister); 761 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 762 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 763 assertEquals(0, request[1]); 764 assertEquals(0, request[2]); 765 assertEquals(0, request[3]); 766 assertArrayEquals(new int[] {0, 0, 0, 0}, 767 mExtRoutingHintPropertyHandler.getLastHint()); 768 mAudioFocusPropertyHandler.sendAudioFocusState( 769 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 770 request[1], 771 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 772 } 773 774 public void testRadioMute() throws Exception { 775 testMediaMute(CarAudioManager.CAR_AUDIO_USAGE_RADIO, 776 0, 777 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 778 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_RADIO_FLAG); 779 } 780 781 public void testMusicMute() throws Exception { 782 testMediaMute(CarAudioManager.CAR_AUDIO_USAGE_MUSIC, 783 0x1, 784 0, 785 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG); 786 } 787 788 private void testMediaMute(int mediaUsage, int primaryStream, int extFocusFlag, 789 int mediaContext) throws Exception { 790 // android radio 791 AudioFocusListener listenerMedia = new AudioFocusListener(); 792 CarAudioManager carAudioManager = (CarAudioManager) getCar().getCarManager( 793 Car.AUDIO_SERVICE); 794 assertNotNull(carAudioManager); 795 AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage(mediaUsage); 796 Log.i(TAG, "request media Focus"); 797 int res = mAudioManager.requestAudioFocus(listenerMedia, 798 radioAttributes, AudioManager.AUDIOFOCUS_GAIN, 0); 799 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 800 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 801 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 802 assertEquals(primaryStream, request[1]); 803 assertEquals(extFocusFlag, request[2]); 804 assertEquals(mediaContext, request[3]); 805 if (mediaUsage == CarAudioManager.CAR_AUDIO_USAGE_RADIO) { 806 assertArrayEquals(new int[] {1, 0, 0, 0}, 807 mExtRoutingHintPropertyHandler.getLastHint()); 808 } else { 809 assertArrayEquals(new int[] {0, 0, 0, 0}, 810 mExtRoutingHintPropertyHandler.getLastHint()); 811 } 812 mAudioFocusPropertyHandler.sendAudioFocusState( 813 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 814 primaryStream, 815 extFocusFlag); 816 // now mute it. 817 assertFalse(carAudioManager.isMediaMuted()); 818 Log.i(TAG, "mute media"); 819 assertTrue(carAudioManager.setMediaMute(true)); 820 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 821 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT, 822 request[0]); 823 assertEquals(0, request[1]); 824 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG, 825 request[2]); 826 assertEquals(0, request[3]); 827 assertArrayEquals(new int[] {0, 0, 0, 0}, 828 mExtRoutingHintPropertyHandler.getLastHint()); 829 mAudioFocusPropertyHandler.sendAudioFocusState( 830 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 831 0, 832 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG); 833 assertTrue(carAudioManager.isMediaMuted()); 834 // nav guidance on top of it 835 AudioFocusListener listenerNav = new AudioFocusListener(); 836 AudioAttributes navAttrib = (new AudioAttributes.Builder()). 837 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION). 838 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 839 build(); 840 Log.i(TAG, "request nav Focus"); 841 res = mAudioManager.requestAudioFocus(listenerNav, navAttrib, 842 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 843 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 844 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK, 845 request[0]); 846 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, request[1]); 847 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG, 848 request[2]); 849 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 850 assertArrayEquals(new int[] {0, 0, 0, 0}, 851 mExtRoutingHintPropertyHandler.getLastHint()); 852 assertTrue(carAudioManager.isMediaMuted()); 853 mAudioFocusPropertyHandler.sendAudioFocusState( 854 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 855 0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, 856 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG); 857 assertTrue(carAudioManager.isMediaMuted()); 858 // nav guidance ends 859 mAudioManager.abandonAudioFocus(listenerNav); 860 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 861 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT, 862 request[0]); 863 assertEquals(0, request[1]); 864 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG, 865 request[2]); 866 assertEquals(0, request[3]); 867 assertArrayEquals(new int[] {0, 0, 0, 0}, 868 mExtRoutingHintPropertyHandler.getLastHint()); 869 assertTrue(carAudioManager.isMediaMuted()); 870 mAudioFocusPropertyHandler.sendAudioFocusState( 871 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 872 0, 873 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_MUTE_MEDIA_FLAG); 874 // now unmute it. media should resume. 875 assertTrue(carAudioManager.isMediaMuted()); 876 assertFalse(carAudioManager.setMediaMute(false)); 877 assertFalse(carAudioManager.isMediaMuted()); 878 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 879 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 880 assertEquals(primaryStream, request[1]); 881 assertEquals(extFocusFlag, 882 request[2]); 883 assertEquals(mediaContext, request[3]); 884 if (mediaUsage == CarAudioManager.CAR_AUDIO_USAGE_RADIO) { 885 assertArrayEquals(new int[] {1, 0, 0, 0}, 886 mExtRoutingHintPropertyHandler.getLastHint()); 887 } else { 888 assertArrayEquals(new int[] {0, 0, 0, 0}, 889 mExtRoutingHintPropertyHandler.getLastHint()); 890 } 891 assertFalse(carAudioManager.isMediaMuted()); 892 mAudioFocusPropertyHandler.sendAudioFocusState( 893 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 894 primaryStream, 895 extFocusFlag); 896 assertFalse(carAudioManager.isMediaMuted()); 897 // release focus 898 mAudioManager.abandonAudioFocus(listenerMedia); 899 } 900 901 protected static class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener { 902 private final Semaphore mFocusChangeWait = new Semaphore(0); 903 private int mLastFocusChange; 904 905 public int waitAndGetFocusChange(long timeoutMs) throws Exception { 906 if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 907 fail("timeout waiting for focus change"); 908 } 909 return mLastFocusChange; 910 } 911 912 public void waitForFocus(long timeoutMs, int expectedFocus) throws Exception { 913 while (mLastFocusChange != expectedFocus) { 914 if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 915 fail("timeout waiting for focus change"); 916 } 917 } 918 } 919 920 @Override 921 public void onAudioFocusChange(int focusChange) { 922 mLastFocusChange = focusChange; 923 mFocusChangeWait.release(); 924 } 925 } 926 927 protected static class FocusPropertyHandler implements VehicleHalPropertyHandler { 928 929 private int mState = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 930 private int mStreams = 0; 931 private int mExtFocus = 0; 932 private int mRequest; 933 private int mRequestedStreams; 934 private int mRequestedExtFocus; 935 private int mRequestedAudioContexts; 936 private final MockedCarTestBase mCarTest; 937 938 private final Semaphore mSetWaitSemaphore = new Semaphore(0); 939 940 public FocusPropertyHandler(MockedCarTestBase carTest) { 941 mCarTest = carTest; 942 } 943 944 public void sendAudioFocusState(int state, int streams, int extFocus) { 945 synchronized (this) { 946 mState = state; 947 mStreams = streams; 948 mExtFocus = extFocus; 949 } 950 int[] values = { state, streams, extFocus, 0 }; 951 mCarTest.getVehicleHalEmulator().injectEvent(VehiclePropValueUtil.createIntVectorValue( 952 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 953 SystemClock.elapsedRealtimeNanos())); 954 } 955 956 public int[] waitForAudioFocusRequest(long timeoutMs) throws Exception { 957 if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 958 fail("timeout"); 959 } 960 synchronized (this) { 961 return new int[] { mRequest, mRequestedStreams, mRequestedExtFocus, 962 mRequestedAudioContexts }; 963 } 964 } 965 966 @Override 967 public void onPropertySet(VehiclePropValue value) { 968 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, value.getProp()); 969 synchronized (this) { 970 mRequest = value.getInt32Values( 971 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_FOCUS); 972 mRequestedStreams = value.getInt32Values( 973 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_STREAMS); 974 mRequestedExtFocus = value.getInt32Values( 975 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE); 976 mRequestedAudioContexts = value.getInt32Values( 977 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_AUDIO_CONTEXTS); 978 } 979 mSetWaitSemaphore.release(); 980 } 981 982 @Override 983 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 984 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, value.getProp()); 985 int state, streams, extFocus; 986 synchronized (this) { 987 state = mState; 988 streams = mStreams; 989 extFocus = mExtFocus; 990 } 991 int[] values = { state, streams, extFocus, 0 }; 992 return VehiclePropValueUtil.createIntVectorValue( 993 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 994 SystemClock.elapsedRealtimeNanos()); 995 } 996 997 @Override 998 public void onPropertySubscribe(int property, float sampleRate, int zones) { 999 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, property); 1000 } 1001 1002 @Override 1003 public void onPropertyUnsubscribe(int property) { 1004 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, property); 1005 } 1006 } 1007 1008 private static class ExtRoutingHintPropertyHandler implements VehicleHalPropertyHandler { 1009 private int[] mLastHint = {0, 0, 0, 0}; 1010 1011 public int[] getLastHint() { 1012 int[] lastHint = new int[mLastHint.length]; 1013 synchronized (this) { 1014 System.arraycopy(mLastHint, 0, lastHint, 0, mLastHint.length); 1015 } 1016 return lastHint; 1017 } 1018 1019 @Override 1020 public void onPropertySet(VehiclePropValue value) { 1021 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_EXT_ROUTING_HINT, 1022 value.getProp()); 1023 assertEquals(mLastHint.length, value.getInt32ValuesCount()); 1024 synchronized (this) { 1025 for (int i = 0; i < mLastHint.length; i++) { 1026 mLastHint[i] = value.getInt32Values(i); 1027 } 1028 } 1029 } 1030 1031 @Override 1032 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 1033 fail("write only"); 1034 return null; 1035 } 1036 1037 @Override 1038 public void onPropertySubscribe(int property, float sampleRate, int zones) { 1039 fail("cannot subsctibe"); 1040 } 1041 1042 @Override 1043 public void onPropertyUnsubscribe(int property) { 1044 fail("cannot subsctibe"); 1045 } 1046 } 1047} 1048