1/* 2 * Copyright (C) 2015 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.test.VehicleHalEmulator.VehicleHalPropertyHandler; 19import android.content.Context; 20import android.media.AudioAttributes; 21import android.media.AudioManager; 22import android.os.SystemClock; 23import android.support.car.Car; 24import android.support.car.media.CarAudioManager; 25import android.test.suitebuilder.annotation.MediumTest; 26 27import com.android.car.vehiclenetwork.VehicleNetworkConsts; 28import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioContextFlag; 29import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioExtFocusFlag; 30import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusIndex; 31import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusRequest; 32import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioFocusState; 33import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleAudioStream; 34import com.android.car.vehiclenetwork.VehiclePropConfigUtil; 35import com.android.car.vehiclenetwork.VehiclePropValueUtil; 36import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePermissionModel; 37import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropAccess; 38import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehiclePropChangeMode; 39import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType; 40import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue; 41 42import java.util.LinkedList; 43import java.util.concurrent.Semaphore; 44import java.util.concurrent.TimeUnit; 45 46@MediumTest 47public class CarAudioFocusTest extends MockedCarTestBase { 48 49 private static final long TIMEOUT_MS = 3000; 50 51 private final VehicleHalPropertyHandler mAudioRoutingPolicyPropertyHandler = 52 new VehicleHalPropertyHandler() { 53 @Override 54 public void onPropertySet(VehiclePropValue value) { 55 //TODO 56 } 57 58 @Override 59 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 60 fail("cannot get"); 61 return null; 62 } 63 64 @Override 65 public void onPropertySubscribe(int property, float sampleRate, int zones) { 66 fail("cannot subscribe"); 67 } 68 69 @Override 70 public void onPropertyUnsubscribe(int property) { 71 fail("cannot unsubscribe"); 72 } 73 }; 74 75 private final FocusPropertyHandler mAudioFocusPropertyHandler = 76 new FocusPropertyHandler(); 77 78 private final VehicleHalPropertyHandler mAppContextPropertyHandler = 79 new VehicleHalPropertyHandler() { 80 81 @Override 82 public void onPropertySet(VehiclePropValue value) { 83 // TODO Auto-generated method stub 84 85 } 86 87 @Override 88 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 89 // TODO Auto-generated method stub 90 return null; 91 } 92 93 @Override 94 public void onPropertySubscribe(int property, float sampleRate, int zones) { 95 // TODO Auto-generated method stub 96 97 } 98 99 @Override 100 public void onPropertyUnsubscribe(int property) { 101 // TODO Auto-generated method stub 102 103 } 104 }; 105 106 private final Semaphore mWaitSemaphore = new Semaphore(0); 107 private final LinkedList<VehiclePropValue> mEvents = new LinkedList<VehiclePropValue>(); 108 private AudioManager mAudioManager; 109 110 @Override 111 protected void setUp() throws Exception { 112 super.setUp(); 113 // AudioManager should be created in main thread to get focus event. :( 114 runOnMainSync(new Runnable() { 115 @Override 116 public void run() { 117 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 118 } 119 }); 120 121 getVehicleHalEmulator().addProperty( 122 VehiclePropConfigUtil.getBuilder( 123 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_ROUTING_POLICY, 124 VehiclePropAccess.VEHICLE_PROP_ACCESS_WRITE, 125 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 126 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2, 127 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 128 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 129 mAudioRoutingPolicyPropertyHandler); 130 getVehicleHalEmulator().addProperty( 131 VehiclePropConfigUtil.getBuilder( 132 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, 133 VehiclePropAccess.VEHICLE_PROP_ACCESS_READ_WRITE, 134 VehiclePropChangeMode.VEHICLE_PROP_CHANGE_MODE_ON_CHANGE, 135 VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4, 136 VehiclePermissionModel.VEHICLE_PERMISSION_SYSTEM_APP_ONLY, 137 0 /*configFlags*/, 0 /*sampleRateMax*/, 0 /*sampleRateMin*/).build(), 138 mAudioFocusPropertyHandler); 139 getVehicleHalEmulator().addStaticProperty( 140 VehiclePropConfigUtil.createStaticStringProperty( 141 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_HW_VARIANT), 142 VehiclePropValueUtil.createIntValue( 143 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_HW_VARIANT, 1, 0)); 144 getVehicleHalEmulator().start(); 145 } 146 147 public void testMediaGainFocus() throws Exception { 148 //TODO update this to check config 149 checkSingleRequestRelease( 150 AudioManager.STREAM_MUSIC, 151 AudioManager.AUDIOFOCUS_GAIN, 152 VehicleAudioStream.VEHICLE_AUDIO_STREAM0, 153 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG); 154 } 155 156 public void testMediaGainTransientFocus() throws Exception { 157 checkSingleRequestRelease( 158 AudioManager.STREAM_MUSIC, 159 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, 160 VehicleAudioStream.VEHICLE_AUDIO_STREAM0, 161 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG); 162 } 163 164 public void testMediaGainTransientMayDuckFocus() throws Exception { 165 checkSingleRequestRelease( 166 AudioManager.STREAM_MUSIC, 167 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 168 VehicleAudioStream.VEHICLE_AUDIO_STREAM0, 169 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG); 170 } 171 172 public void testAlarmGainTransientFocus() throws Exception { 173 checkSingleRequestRelease( 174 AudioManager.STREAM_ALARM, 175 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT, 176 VehicleAudioStream.VEHICLE_AUDIO_STREAM1, 177 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_ALARM_FLAG); 178 } 179 180 public void testAlarmGainTransientMayDuckFocus() throws Exception { 181 checkSingleRequestRelease( 182 AudioManager.STREAM_ALARM, 183 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 184 VehicleAudioStream.VEHICLE_AUDIO_STREAM1, 185 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_ALARM_FLAG); 186 } 187 188 public void testMediaNavFocus() throws Exception { 189 //music start 190 AudioFocusListener listenerMusic = new AudioFocusListener(); 191 int res = mAudioManager.requestAudioFocus(listenerMusic, 192 AudioManager.STREAM_MUSIC, 193 AudioManager.AUDIOFOCUS_GAIN); 194 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 195 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 196 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 197 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 198 assertEquals(0, request[2]); 199 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 200 mAudioFocusPropertyHandler.sendAudioFocusState( 201 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 202 request[1], 203 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 204 205 // nav guidance start 206 AudioFocusListener listenerNav = new AudioFocusListener(); 207 AudioAttributes navAttrib = (new AudioAttributes.Builder()). 208 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION). 209 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 210 build(); 211 res = mAudioManager.requestAudioFocus(listenerNav, navAttrib, 212 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 213 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 214 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 215 assertEquals(0x3, request[1]); 216 assertEquals(0, request[2]); 217 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG | 218 VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 219 mAudioFocusPropertyHandler.sendAudioFocusState( 220 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, request[1], 221 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 222 223 // nav guidance done 224 mAudioManager.abandonAudioFocus(listenerNav); 225 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 226 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 227 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 228 assertEquals(0, request[2]); 229 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 230 mAudioFocusPropertyHandler.sendAudioFocusState( 231 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, request[1], 232 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 233 234 // music done 235 mAudioManager.abandonAudioFocus(listenerMusic); 236 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 237 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 238 assertEquals(0, request[1]); 239 assertEquals(0, request[2]); 240 assertEquals(0, request[3]); 241 mAudioFocusPropertyHandler.sendAudioFocusState( 242 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, request[1], 243 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 244 } 245 246 public void testMediaExternalMediaNavFocus() throws Exception { 247 // android music 248 AudioFocusListener listenerMusic = new AudioFocusListener(); 249 int res = mAudioManager.requestAudioFocus(listenerMusic, 250 AudioManager.STREAM_MUSIC, 251 AudioManager.AUDIOFOCUS_GAIN); 252 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 253 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 254 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 255 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 256 assertEquals(0, request[2]); 257 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 258 mAudioFocusPropertyHandler.sendAudioFocusState( 259 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 260 request[1], 261 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 262 263 // car plays external media (=outside Android) 264 mAudioFocusPropertyHandler.sendAudioFocusState( 265 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 266 0, 267 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG); 268 int focusChange = listenerMusic.waitAndGetFocusChange(TIMEOUT_MS); 269 assertEquals(AudioManager.AUDIOFOCUS_LOSS, focusChange); 270 271 // nav guidance start 272 AudioFocusListener listenerNav = new AudioFocusListener(); 273 AudioAttributes navAttrib = (new AudioAttributes.Builder()). 274 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION). 275 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 276 build(); 277 res = mAudioManager.requestAudioFocus(listenerNav, navAttrib, 278 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 279 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 280 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK, 281 request[0]); 282 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, request[1]); 283 assertEquals(0, request[2]); 284 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 285 mAudioFocusPropertyHandler.sendAudioFocusState( 286 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT, 287 0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, 288 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG); 289 290 // nav guidance ends 291 mAudioManager.abandonAudioFocus(listenerNav); 292 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 293 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 294 assertEquals(0, request[1]); 295 assertEquals(0, request[2]); 296 assertEquals(0, request[3]); 297 mAudioFocusPropertyHandler.sendAudioFocusState( 298 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 299 0, 300 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PERMANENT_FLAG); 301 302 // now ends external play 303 mAudioFocusPropertyHandler.sendAudioFocusState( 304 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 305 0, 306 0); 307 // music picks up 308 listenerMusic.waitForFocus(TIMEOUT_MS, AudioManager.AUDIOFOCUS_GAIN); 309 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 310 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 311 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 312 assertEquals(0, request[2]); 313 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 314 mAudioFocusPropertyHandler.sendAudioFocusState( 315 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 316 request[1], 317 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 318 319 // now ends music 320 mAudioManager.abandonAudioFocus(listenerMusic); 321 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 322 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 323 assertEquals(0, request[1]); 324 assertEquals(0, request[2]); 325 assertEquals(0, request[3]); 326 mAudioFocusPropertyHandler.sendAudioFocusState( 327 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 328 0, 329 0); 330 } 331 332 public void testMediaExternalRadioNavMediaFocus() throws Exception { 333 // android music 334 AudioFocusListener listenerMusic = new AudioFocusListener(); 335 int res = mAudioManager.requestAudioFocus(listenerMusic, 336 AudioManager.STREAM_MUSIC, 337 AudioManager.AUDIOFOCUS_GAIN); 338 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 339 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 340 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 341 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 342 assertEquals(0, request[2]); 343 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 344 mAudioFocusPropertyHandler.sendAudioFocusState( 345 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 346 request[1], 347 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 348 349 // android radio 350 AudioFocusListener listenerRadio = new AudioFocusListener(); 351 CarAudioManager carAudioManager = (CarAudioManager) getSupportCar().getCarManager( 352 Car.AUDIO_SERVICE); 353 assertNotNull(carAudioManager); 354 AudioAttributes radioAttributes = carAudioManager.getAudioAttributesForCarUsage( 355 CarAudioManager.CAR_AUDIO_USAGE_RADIO); 356 res = mAudioManager.requestAudioFocus(listenerRadio, 357 radioAttributes, AudioManager.AUDIOFOCUS_GAIN, 0); 358 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 359 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 360 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 361 assertEquals(0, request[1]); 362 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 363 request[2]); 364 // no android side context for radio 365 assertEquals(0, request[3]); 366 mAudioFocusPropertyHandler.sendAudioFocusState( 367 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 368 0, 369 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 370 371 // nav guidance start 372 AudioFocusListener listenerNav = new AudioFocusListener(); 373 AudioAttributes navAttrib = (new AudioAttributes.Builder()). 374 setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION). 375 setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE). 376 build(); 377 res = mAudioManager.requestAudioFocus(listenerNav, navAttrib, 378 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, 0); 379 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 380 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 381 request[0]); 382 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, request[1]); 383 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 384 request[2]); 385 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_NAVIGATION_FLAG, request[3]); 386 mAudioFocusPropertyHandler.sendAudioFocusState( 387 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 388 0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM1, 389 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 390 391 // nav guidance ends 392 mAudioManager.abandonAudioFocus(listenerNav); 393 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 394 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, 395 request[0]); 396 assertEquals(0, request[1]); 397 assertEquals(VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG, 398 request[2]); 399 assertEquals(0, request[3]); 400 mAudioFocusPropertyHandler.sendAudioFocusState( 401 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 402 0, 403 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_CAR_PLAY_ONLY_FLAG); 404 405 // ends radio. music will get the focus GAIN. 406 // Music app is supposed to stop and release focus when it has lost focus, but here just 407 // check if focus is working. 408 mAudioManager.abandonAudioFocus(listenerRadio); 409 listenerMusic.waitForFocus(TIMEOUT_MS, AudioManager.AUDIOFOCUS_GAIN); 410 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 411 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN, request[0]); 412 assertEquals(0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, request[1]); 413 assertEquals(0, request[2]); 414 assertEquals(VehicleAudioContextFlag.VEHICLE_AUDIO_CONTEXT_MUSIC_FLAG, request[3]); 415 mAudioFocusPropertyHandler.sendAudioFocusState( 416 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN, 417 0x1 << VehicleAudioStream.VEHICLE_AUDIO_STREAM0, 418 0); 419 420 // now music release focus. 421 mAudioManager.abandonAudioFocus(listenerMusic); 422 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 423 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 424 assertEquals(0, request[1]); 425 assertEquals(0, request[2]); 426 assertEquals(0, request[3]); 427 mAudioFocusPropertyHandler.sendAudioFocusState( 428 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 429 0, 430 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 431 } 432 433 private void checkSingleRequestRelease(int streamType, int androidFocus, int streamNumber, 434 int context) 435 throws Exception { 436 AudioFocusListener lister = new AudioFocusListener(); 437 int res = mAudioManager.requestAudioFocus(lister, 438 streamType, 439 androidFocus); 440 assertEquals(AudioManager.AUDIOFOCUS_REQUEST_GRANTED, res); 441 int[] request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 442 int expectedRequest = VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE; 443 int response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 444 switch (androidFocus) { 445 case AudioManager.AUDIOFOCUS_GAIN: 446 expectedRequest = VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN; 447 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN; 448 break; 449 case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT: 450 expectedRequest = 451 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT; 452 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT; 453 break; 454 case AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK: 455 expectedRequest = 456 VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_GAIN_TRANSIENT_MAY_DUCK; 457 response = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_GAIN_TRANSIENT; 458 break; 459 } 460 assertEquals(expectedRequest, request[0]); 461 assertEquals(0x1 << streamNumber, request[1]); 462 assertEquals(0, request[2]); 463 assertEquals(context, request[3]); 464 mAudioFocusPropertyHandler.sendAudioFocusState( 465 response, 466 request[1], 467 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 468 mAudioManager.abandonAudioFocus(lister); 469 request = mAudioFocusPropertyHandler.waitForAudioFocusRequest(TIMEOUT_MS); 470 assertEquals(VehicleAudioFocusRequest.VEHICLE_AUDIO_FOCUS_REQUEST_RELEASE, request[0]); 471 assertEquals(0, request[1]); 472 assertEquals(0, request[2]); 473 assertEquals(0, request[3]); 474 mAudioFocusPropertyHandler.sendAudioFocusState( 475 VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS, 476 request[1], 477 VehicleAudioExtFocusFlag.VEHICLE_AUDIO_EXT_FOCUS_NONE_FLAG); 478 } 479 480 private class AudioFocusListener implements AudioManager.OnAudioFocusChangeListener { 481 private final Semaphore mFocusChangeWait = new Semaphore(0); 482 private int mLastFocusChange; 483 484 public int waitAndGetFocusChange(long timeoutMs) throws Exception { 485 if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 486 fail("timeout waiting for focus change"); 487 } 488 return mLastFocusChange; 489 } 490 491 public void waitForFocus(long timeoutMs, int expectedFocus) throws Exception { 492 while (mLastFocusChange != expectedFocus) { 493 if (!mFocusChangeWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 494 fail("timeout waiting for focus change"); 495 } 496 } 497 } 498 499 @Override 500 public void onAudioFocusChange(int focusChange) { 501 mLastFocusChange = focusChange; 502 mFocusChangeWait.release(); 503 } 504 } 505 506 private class FocusPropertyHandler implements VehicleHalPropertyHandler { 507 508 private int mState = VehicleAudioFocusState.VEHICLE_AUDIO_FOCUS_STATE_LOSS; 509 private int mStreams = 0; 510 private int mExtFocus = 0; 511 private int mRequest; 512 private int mRequestedStreams; 513 private int mRequestedExtFocus; 514 private int mRequestedAudioContexts; 515 516 private final Semaphore mSetWaitSemaphore = new Semaphore(0); 517 518 public void sendAudioFocusState(int state, int streams, int extFocus) { 519 synchronized (this) { 520 mState = state; 521 mStreams = streams; 522 mExtFocus = extFocus; 523 } 524 int[] values = { state, streams, extFocus, 0 }; 525 getVehicleHalEmulator().injectEvent(VehiclePropValueUtil.createIntVectorValue( 526 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 527 SystemClock.elapsedRealtimeNanos())); 528 } 529 530 public int[] waitForAudioFocusRequest(long timeoutMs) throws Exception { 531 if (!mSetWaitSemaphore.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS)) { 532 fail("timeout"); 533 } 534 synchronized (this) { 535 return new int[] { mRequest, mRequestedStreams, mRequestedExtFocus, 536 mRequestedAudioContexts }; 537 } 538 } 539 540 @Override 541 public void onPropertySet(VehiclePropValue value) { 542 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, value.getProp()); 543 synchronized (this) { 544 mRequest = value.getInt32Values( 545 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_FOCUS); 546 mRequestedStreams = value.getInt32Values( 547 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_STREAMS); 548 mRequestedExtFocus = value.getInt32Values( 549 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_EXTERNAL_FOCUS_STATE); 550 mRequestedAudioContexts = value.getInt32Values( 551 VehicleAudioFocusIndex.VEHICLE_AUDIO_FOCUS_INDEX_AUDIO_CONTEXTS); 552 } 553 mSetWaitSemaphore.release(); 554 } 555 556 @Override 557 public VehiclePropValue onPropertyGet(VehiclePropValue value) { 558 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, value.getProp()); 559 int state, streams, extFocus; 560 synchronized (this) { 561 state = mState; 562 streams = mStreams; 563 extFocus = mExtFocus; 564 } 565 int[] values = { state, streams, extFocus, 0 }; 566 return VehiclePropValueUtil.createIntVectorValue( 567 VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, values, 568 SystemClock.elapsedRealtimeNanos()); 569 } 570 571 @Override 572 public void onPropertySubscribe(int property, float sampleRate, int zones) { 573 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, property); 574 } 575 576 @Override 577 public void onPropertyUnsubscribe(int property) { 578 assertEquals(VehicleNetworkConsts.VEHICLE_PROPERTY_AUDIO_FOCUS, property); 579 } 580 } 581} 582