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