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