CallAudioRouteStateMachineTest.java revision 5b8551ef79dc6e31bd945380097c13ff18b37359
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 */ 16 17package com.android.server.telecom.tests; 18 19import android.app.NotificationManager; 20import android.content.Context; 21import android.media.AudioManager; 22import android.media.IAudioService; 23import android.telecom.CallAudioState; 24import android.test.suitebuilder.annotation.LargeTest; 25import android.test.suitebuilder.annotation.MediumTest; 26import android.test.suitebuilder.annotation.SmallTest; 27 28import com.android.server.telecom.bluetooth.BluetoothRouteManager; 29import com.android.server.telecom.Call; 30import com.android.server.telecom.CallAudioModeStateMachine; 31import com.android.server.telecom.CallAudioRouteStateMachine; 32import com.android.server.telecom.CallsManager; 33import com.android.server.telecom.ConnectionServiceWrapper; 34import com.android.server.telecom.CallAudioManager; 35import com.android.server.telecom.InterruptionFilterProxy; 36import com.android.server.telecom.StatusBarNotifier; 37import com.android.server.telecom.TelecomSystem; 38import com.android.server.telecom.WiredHeadsetManager; 39 40import org.mockito.ArgumentCaptor; 41import org.mockito.Mock; 42import org.mockito.MockitoAnnotations; 43import org.mockito.invocation.InvocationOnMock; 44import org.mockito.stubbing.Answer; 45 46import java.util.ArrayList; 47import java.util.List; 48import java.util.Objects; 49 50import static org.mockito.Matchers.any; 51import static org.mockito.Matchers.anyInt; 52import static org.mockito.Matchers.eq; 53import static org.mockito.Matchers.same; 54import static org.mockito.Mockito.doAnswer; 55import static org.mockito.Mockito.doNothing; 56import static org.mockito.Mockito.doReturn; 57import static org.mockito.Mockito.mock; 58import static org.mockito.Mockito.never; 59import static org.mockito.Mockito.reset; 60import static org.mockito.Mockito.timeout; 61import static org.mockito.Mockito.times; 62import static org.mockito.Mockito.verify; 63import static org.mockito.Mockito.when; 64 65 66public class CallAudioRouteStateMachineTest 67 extends StateMachineTestBase<CallAudioRouteStateMachine> { 68 private static final int NONE = 0; 69 private static final int ON = 1; 70 private static final int OFF = 2; 71 72 static class RoutingTestParameters extends TestParameters { 73 public String name; 74 public int initialRoute; 75 public int initialNotificationFilter; 76 public int availableRoutes; // may excl. speakerphone, because that's always available 77 public int speakerInteraction; // one of NONE, ON, or OFF 78 public int bluetoothInteraction; // one of NONE, ON, or OFF 79 public int action; 80 public int expectedRoute; 81 public int expectedAvailableRoutes; // also may exclude the speakerphone. 82 public int expectedNotificationFilter; // expected end notification filter. 83 public boolean isNotificationChangeExpected; // indicates whether we expect the notification 84 // filter to change during the process of the 85 // test. 86 public boolean doesDeviceSupportEarpiece; // set to false in the case of Wear devices 87 public boolean shouldRunWithFocus; 88 89 public int callSupportedRoutes = CallAudioState.ROUTE_ALL; 90 91 public RoutingTestParameters(String name, int initialRoute, 92 int initialNotificationFilter, int availableRoutes, int speakerInteraction, 93 int bluetoothInteraction, int action, int expectedRoute, 94 int expectedAvailableRoutes, int expectedNotificationFilter, 95 boolean isNotificationChangeExpected, boolean doesDeviceSupportEarpiece, 96 boolean shouldRunWithFocus) { 97 this.name = name; 98 this.initialRoute = initialRoute; 99 this.initialNotificationFilter = initialNotificationFilter; 100 this.availableRoutes = availableRoutes; 101 this.speakerInteraction = speakerInteraction; 102 this.bluetoothInteraction = bluetoothInteraction; 103 this.action = action; 104 this.expectedRoute = expectedRoute; 105 this.expectedAvailableRoutes = expectedAvailableRoutes; 106 this.expectedNotificationFilter = expectedNotificationFilter; 107 this.isNotificationChangeExpected = isNotificationChangeExpected; 108 this.doesDeviceSupportEarpiece = doesDeviceSupportEarpiece; 109 this.shouldRunWithFocus = shouldRunWithFocus; 110 } 111 112 public RoutingTestParameters setCallSupportedRoutes(int routes) { 113 callSupportedRoutes = routes; 114 return this; 115 } 116 117 @Override 118 public String toString() { 119 return "RoutingTestParameters{" + 120 "name='" + name + '\'' + 121 ", initialRoute=" + initialRoute + 122 ", initialNotificationFilter=" + initialNotificationFilter + 123 ", availableRoutes=" + availableRoutes + 124 ", speakerInteraction=" + speakerInteraction + 125 ", bluetoothInteraction=" + bluetoothInteraction + 126 ", action=" + action + 127 ", expectedRoute=" + expectedRoute + 128 ", expectedAvailableRoutes=" + expectedAvailableRoutes + 129 ", expectedNotificationFilter= " + expectedNotificationFilter + 130 ", isNotificationChangeExpected=" + isNotificationChangeExpected + 131 ", doesDeviceSupportEarpiece=" + doesDeviceSupportEarpiece + 132 ", shouldRunWithFocus=" + shouldRunWithFocus + 133 '}'; 134 } 135 } 136 137 @Mock CallsManager mockCallsManager; 138 @Mock BluetoothRouteManager mockBluetoothRouteManager; 139 @Mock IAudioService mockAudioService; 140 @Mock ConnectionServiceWrapper mockConnectionServiceWrapper; 141 @Mock WiredHeadsetManager mockWiredHeadsetManager; 142 @Mock StatusBarNotifier mockStatusBarNotifier; 143 @Mock Call fakeCall; 144 @Mock InterruptionFilterProxy mMockInterruptionFilterProxy; 145 146 private CallAudioManager.AudioServiceFactory mAudioServiceFactory; 147 private static final int TEST_TIMEOUT = 500; 148 private AudioManager mockAudioManager; 149 private final TelecomSystem.SyncRoot mLock = new TelecomSystem.SyncRoot() { }; 150 151 @Override 152 public void setUp() throws Exception { 153 super.setUp(); 154 MockitoAnnotations.initMocks(this); 155 mContext = mComponentContextFixture.getTestDouble().getApplicationContext(); 156 mockAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 157 158 mAudioServiceFactory = new CallAudioManager.AudioServiceFactory() { 159 @Override 160 public IAudioService getAudioService() { 161 return mockAudioService; 162 } 163 }; 164 165 when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall); 166 when(mockCallsManager.getLock()).thenReturn(mLock); 167 when(mockCallsManager.hasVideoCall()).thenReturn(false); 168 when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper); 169 when(fakeCall.isAlive()).thenReturn(true); 170 when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL); 171 setupInterruptionFilterMocks(); 172 173 doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class), 174 any(CallAudioState.class)); 175 } 176 177 private void setupInterruptionFilterMocks() { 178 // These mock implementations keep track of when the caller sets the current notification 179 // filter, and ensures the same value is returned via getCurrentInterruptionFilter. 180 final int objId = Objects.hashCode(mMockInterruptionFilterProxy); 181 when(mMockInterruptionFilterProxy.getCurrentInterruptionFilter()).thenReturn( 182 NotificationManager.INTERRUPTION_FILTER_ALL); 183 doAnswer(new Answer<Void>() { 184 @Override 185 public Void answer(InvocationOnMock i) { 186 int requestedFilter = (int) i.getArguments()[0]; 187 when(mMockInterruptionFilterProxy.getCurrentInterruptionFilter()).thenReturn( 188 requestedFilter); 189 return null; 190 } 191 }).when(mMockInterruptionFilterProxy).setInterruptionFilter(anyInt()); 192 } 193 194 @LargeTest 195 public void testStateMachineTransitionsWithFocus() throws Throwable { 196 List<RoutingTestParameters> paramList = generateTransitionTests(true); 197 parametrizedTestStateMachine(paramList); 198 } 199 200 @LargeTest 201 public void testStateMachineTransitionsWithoutFocus() throws Throwable { 202 List<RoutingTestParameters> paramList = generateTransitionTests(false); 203 parametrizedTestStateMachine(paramList); 204 } 205 206 @MediumTest 207 public void testSpeakerPersistence() { 208 CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( 209 mContext, 210 mockCallsManager, 211 mockBluetoothRouteManager, 212 mockWiredHeadsetManager, 213 mockStatusBarNotifier, 214 mAudioServiceFactory, 215 mMockInterruptionFilterProxy, 216 true); 217 218 when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); 219 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); 220 when(mockAudioManager.isSpeakerphoneOn()).thenReturn(true); 221 doAnswer(new Answer() { 222 @Override 223 public Object answer(InvocationOnMock invocation) throws Throwable { 224 Object[] args = invocation.getArguments(); 225 when(mockAudioManager.isSpeakerphoneOn()).thenReturn((Boolean) args[0]); 226 return null; 227 } 228 }).when(mockAudioManager).setSpeakerphoneOn(any(Boolean.class)); 229 CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER, 230 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER); 231 stateMachine.initialize(initState); 232 233 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, 234 CallAudioRouteStateMachine.ACTIVE_FOCUS); 235 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET); 236 CallAudioState expectedMiddleState = new CallAudioState(false, 237 CallAudioState.ROUTE_WIRED_HEADSET, 238 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_SPEAKER); 239 waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); 240 waitForHandlerAction(stateMachine.getHandler(), TEST_TIMEOUT); 241 verifyNewSystemCallAudioState(initState, expectedMiddleState); 242 resetMocks(true); 243 244 stateMachine.sendMessageWithSessionInfo( 245 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET); 246 verifyNewSystemCallAudioState(expectedMiddleState, initState); 247 } 248 249 @MediumTest 250 public void testUserBluetoothSwitchOff() { 251 CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( 252 mContext, 253 mockCallsManager, 254 mockBluetoothRouteManager, 255 mockWiredHeadsetManager, 256 mockStatusBarNotifier, 257 mAudioServiceFactory, 258 mMockInterruptionFilterProxy, 259 true); 260 261 when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); 262 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); 263 when(mockAudioManager.isSpeakerphoneOn()).thenReturn(true); 264 265 CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, 266 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); 267 stateMachine.initialize(initState); 268 269 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, 270 CallAudioRouteStateMachine.ACTIVE_FOCUS); 271 stateMachine.sendMessageWithSessionInfo( 272 CallAudioRouteStateMachine.USER_SWITCH_BASELINE_ROUTE); 273 CallAudioState expectedEndState = new CallAudioState(false, 274 CallAudioState.ROUTE_EARPIECE, 275 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); 276 277 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 278 verifyNewSystemCallAudioState(initState, expectedEndState); 279 // Expecting to end up in earpiece, so we expect notifications to be filtered. 280 assertEquals(NotificationManager.INTERRUPTION_FILTER_ALARMS, 281 mMockInterruptionFilterProxy.getCurrentInterruptionFilter()); 282 resetMocks(false); 283 stateMachine.sendMessageWithSessionInfo( 284 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH); 285 stateMachine.sendMessageWithSessionInfo( 286 CallAudioRouteStateMachine.CONNECT_BLUETOOTH); 287 288 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 289 assertEquals(expectedEndState, stateMachine.getCurrentCallAudioState()); 290 } 291 292 @MediumTest 293 public void testBluetoothRinging() { 294 CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( 295 mContext, 296 mockCallsManager, 297 mockBluetoothRouteManager, 298 mockWiredHeadsetManager, 299 mockStatusBarNotifier, 300 mAudioServiceFactory, 301 mMockInterruptionFilterProxy, 302 true); 303 304 when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); 305 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); 306 when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false); 307 308 CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, 309 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); 310 stateMachine.initialize(initState); 311 312 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, 313 CallAudioRouteStateMachine.RINGING_FOCUS); 314 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 315 316 verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null); 317 // Shouldn't change interruption filter when in bluetooth route. 318 assertEquals(NotificationManager.INTERRUPTION_FILTER_ALL, 319 mMockInterruptionFilterProxy.getCurrentInterruptionFilter()); 320 321 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, 322 CallAudioRouteStateMachine.ACTIVE_FOCUS); 323 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 324 verify(mockBluetoothRouteManager, times(1)).connectBluetoothAudio(null); 325 } 326 327 @MediumTest 328 public void testConnectBluetoothDuringRinging() { 329 CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( 330 mContext, 331 mockCallsManager, 332 mockBluetoothRouteManager, 333 mockWiredHeadsetManager, 334 mockStatusBarNotifier, 335 mAudioServiceFactory, 336 mMockInterruptionFilterProxy, 337 true); 338 339 when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn(false); 340 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(false); 341 when(mockAudioManager.isSpeakerphoneOn()).thenReturn(false); 342 CallAudioState initState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, 343 CallAudioState.ROUTE_EARPIECE); 344 stateMachine.initialize(initState); 345 346 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, 347 CallAudioRouteStateMachine.RINGING_FOCUS); 348 349 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn(true); 350 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.CONNECT_BLUETOOTH); 351 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 352 353 verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null); 354 CallAudioState expectedEndState = new CallAudioState(false, 355 CallAudioState.ROUTE_BLUETOOTH, 356 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH); 357 verifyNewSystemCallAudioState(initState, expectedEndState); 358 359 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, 360 CallAudioRouteStateMachine.ACTIVE_FOCUS); 361 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 362 verify(mockBluetoothRouteManager, times(1)).connectBluetoothAudio(null); 363 } 364 365 @SmallTest 366 public void testInitializationWithEarpieceNoHeadsetNoBluetooth() { 367 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_EARPIECE, 368 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER); 369 initializationTestHelper(expectedState, true); 370 } 371 372 @SmallTest 373 public void testInitializationWithEarpieceAndHeadsetNoBluetooth() { 374 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_WIRED_HEADSET, 375 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_SPEAKER); 376 initializationTestHelper(expectedState, true); 377 } 378 379 @SmallTest 380 public void testInitializationWithEarpieceAndHeadsetAndBluetooth() { 381 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, 382 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_SPEAKER 383 | CallAudioState.ROUTE_BLUETOOTH); 384 initializationTestHelper(expectedState, true); 385 } 386 387 @SmallTest 388 public void testInitializationWithEarpieceAndBluetoothNoHeadset() { 389 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, 390 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_SPEAKER 391 | CallAudioState.ROUTE_BLUETOOTH); 392 initializationTestHelper(expectedState, true); 393 } 394 395 @SmallTest 396 public void testInitializationWithNoEarpieceNoHeadsetNoBluetooth() { 397 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_SPEAKER, 398 CallAudioState.ROUTE_SPEAKER); 399 initializationTestHelper(expectedState, false); 400 } 401 402 @SmallTest 403 public void testInitializationWithHeadsetNoBluetoothNoEarpiece() { 404 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_WIRED_HEADSET, 405 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_SPEAKER); 406 initializationTestHelper(expectedState, false); 407 } 408 409 @SmallTest 410 public void testInitializationWithHeadsetAndBluetoothNoEarpiece() { 411 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, 412 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_SPEAKER 413 | CallAudioState.ROUTE_BLUETOOTH); 414 initializationTestHelper(expectedState, false); 415 } 416 417 @SmallTest 418 public void testInitializationWithBluetoothNoHeadsetNoEarpiece() { 419 CallAudioState expectedState = new CallAudioState(false, CallAudioState.ROUTE_BLUETOOTH, 420 CallAudioState.ROUTE_SPEAKER | CallAudioState.ROUTE_BLUETOOTH); 421 initializationTestHelper(expectedState, false); 422 } 423 424 private void initializationTestHelper(CallAudioState expectedState, 425 boolean doesDeviceSupportEarpiece) { 426 when(mockWiredHeadsetManager.isPluggedIn()).thenReturn( 427 (expectedState.getSupportedRouteMask() & CallAudioState.ROUTE_WIRED_HEADSET) != 0); 428 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn( 429 (expectedState.getSupportedRouteMask() & CallAudioState.ROUTE_BLUETOOTH) != 0); 430 431 CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( 432 mContext, 433 mockCallsManager, 434 mockBluetoothRouteManager, 435 mockWiredHeadsetManager, 436 mockStatusBarNotifier, 437 mAudioServiceFactory, 438 mMockInterruptionFilterProxy, 439 doesDeviceSupportEarpiece); 440 stateMachine.initialize(); 441 assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); 442 } 443 444 private List<RoutingTestParameters> generateTransitionTests(boolean shouldRunWithFocus) { 445 List<RoutingTestParameters> params = new ArrayList<>(); 446 params.add(new RoutingTestParameters( 447 "Connect headset during earpiece", // name 448 CallAudioState.ROUTE_EARPIECE, // initialRoute 449 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 450 CallAudioState.ROUTE_EARPIECE, // availableRoutes 451 NONE, // speakerInteraction 452 NONE, // bluetoothInteraction 453 CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET, // action 454 CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute 455 CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes 456 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 457 true, // isNotificationChangeExpected 458 true, // doesDeviceSupportEarpiece 459 shouldRunWithFocus 460 )); 461 462 params.add(new RoutingTestParameters( 463 "Connect headset during bluetooth", // name 464 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 465 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 466 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 467 NONE, // speakerInteraction 468 OFF, // bluetoothInteraction 469 CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET, // action 470 CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute 471 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // expectedAvai 472 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 473 false, // isNotificationChangeExpected 474 true, // doesDeviceSupportEarpiece 475 shouldRunWithFocus 476 )); 477 478 params.add(new RoutingTestParameters( 479 "Connect headset during speakerphone", // name 480 CallAudioState.ROUTE_SPEAKER, // initialRoute 481 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 482 CallAudioState.ROUTE_EARPIECE, // availableRoutes 483 OFF, // speakerInteraction 484 NONE, // bluetoothInteraction 485 CallAudioRouteStateMachine.CONNECT_WIRED_HEADSET, // action 486 CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute 487 CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes 488 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 489 false, // isNotificationChangeExpected 490 true, // doesDeviceSupportEarpiece 491 shouldRunWithFocus 492 )); 493 494 params.add(new RoutingTestParameters( 495 "Disconnect headset during headset", // name 496 CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute 497 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 498 CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes 499 NONE, // speakerInteraction 500 NONE, // bluetoothInteraction 501 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action 502 CallAudioState.ROUTE_EARPIECE, // expectedRoute 503 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 504 NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter 505 true, // isNotificationChangeExpected 506 true, // doesDeviceSupportEarpiece 507 shouldRunWithFocus 508 )); 509 510 params.add(new RoutingTestParameters( 511 "Disconnect headset during headset with bluetooth available", // name 512 CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute 513 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 514 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou 515 NONE, // speakerInteraction 516 NONE, // bluetoothInteraction 517 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action 518 CallAudioState.ROUTE_EARPIECE, // expectedRoute 519 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable 520 NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter 521 true, // isNotificationChangeExpected 522 true, // doesDeviceSupportEarpiece 523 shouldRunWithFocus 524 )); 525 526 params.add(new RoutingTestParameters( 527 "Disconnect headset during bluetooth", // name 528 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 529 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 530 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou 531 NONE, // speakerInteraction 532 NONE, // bluetoothInteraction 533 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action 534 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute 535 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable 536 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 537 false, // isNotificationChangeExpected 538 true, // doesDeviceSupportEarpiece 539 shouldRunWithFocus 540 )); 541 542 params.add(new RoutingTestParameters( 543 "Disconnect headset during speakerphone", // name 544 CallAudioState.ROUTE_SPEAKER, // initialRoute 545 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 546 CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes 547 NONE, // speakerInteraction 548 NONE, // bluetoothInteraction 549 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action 550 CallAudioState.ROUTE_SPEAKER, // expectedRoute 551 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 552 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 553 false, // isNotificationChangeExpected 554 true, // doesDeviceSupportEarpiece 555 shouldRunWithFocus 556 )); 557 558 params.add(new RoutingTestParameters( 559 "Disconnect headset during speakerphone with bluetooth available", // name 560 CallAudioState.ROUTE_SPEAKER, // initialRoute 561 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 562 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou 563 NONE, // speakerInteraction 564 NONE, // bluetoothInteraction 565 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action 566 CallAudioState.ROUTE_SPEAKER, // expectedRoute 567 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable 568 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 569 false, // isNotificationChangeExpected 570 true, // doesDeviceSupportEarpiece 571 shouldRunWithFocus 572 )); 573 574 params.add(new RoutingTestParameters( 575 "Connect bluetooth during earpiece", // name 576 CallAudioState.ROUTE_EARPIECE, // initialRoute 577 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 578 CallAudioState.ROUTE_EARPIECE, // availableRoutes 579 NONE, // speakerInteraction 580 ON, // bluetoothInteraction 581 CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action 582 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute 583 CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_EARPIECE, // expectedAvailable 584 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 585 true, // isNotificationChangeExpected 586 true, // doesDeviceSupportEarpiece 587 shouldRunWithFocus 588 )); 589 590 params.add(new RoutingTestParameters( 591 "Connect bluetooth during wired headset", // name 592 CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute 593 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 594 CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes 595 NONE, // speakerInteraction 596 ON, // bluetoothInteraction 597 CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action 598 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute 599 CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvai 600 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 601 false, // isNotificationChangeExpected 602 true, // doesDeviceSupportEarpiece 603 shouldRunWithFocus 604 )); 605 606 params.add(new RoutingTestParameters( 607 "Connect bluetooth during speakerphone", // name 608 CallAudioState.ROUTE_SPEAKER, // initialRoute 609 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 610 CallAudioState.ROUTE_EARPIECE, // availableRoutes 611 OFF, // speakerInteraction 612 ON, // bluetoothInteraction 613 CallAudioRouteStateMachine.CONNECT_BLUETOOTH, // action 614 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute 615 CallAudioState.ROUTE_BLUETOOTH | CallAudioState.ROUTE_EARPIECE, // expectedAvailable 616 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 617 false, // isNotificationChangeExpected 618 true, // doesDeviceSupportEarpiece 619 shouldRunWithFocus 620 )); 621 622 params.add(new RoutingTestParameters( 623 "Disconnect bluetooth during bluetooth without headset in", // name 624 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 625 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 626 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 627 NONE, // speakerInteraction 628 OFF, // bluetoothInteraction 629 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action 630 CallAudioState.ROUTE_EARPIECE, // expectedRoute 631 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 632 NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter 633 true, // isNotificationChangeExpected 634 true, // doesDeviceSupportEarpiece 635 shouldRunWithFocus 636 )); 637 638 params.add(new RoutingTestParameters( 639 "Disconnect bluetooth during bluetooth without headset in, priority mode ", // name 640 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 641 NotificationManager.INTERRUPTION_FILTER_PRIORITY, // initialNotificationFilter 642 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 643 NONE, // speakerInteraction 644 OFF, // bluetoothInteraction 645 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action 646 CallAudioState.ROUTE_EARPIECE, // expectedRoute 647 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 648 NotificationManager.INTERRUPTION_FILTER_PRIORITY, // expectedNotificationFilter 649 false, // isNotificationChangeExpected 650 true, // doesDeviceSupportEarpiece 651 shouldRunWithFocus 652 )); 653 654 params.add(new RoutingTestParameters( 655 "Disconnect bluetooth during bluetooth with headset in", // name 656 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 657 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 658 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou 659 NONE, // speakerInteraction 660 OFF, // bluetoothInteraction 661 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action 662 CallAudioState.ROUTE_WIRED_HEADSET, // expectedRoute 663 CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes 664 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 665 false, // isNotificationChangeExpected 666 true, // doesDeviceSupportEarpiece 667 shouldRunWithFocus 668 )); 669 670 params.add(new RoutingTestParameters( 671 "Disconnect bluetooth during speakerphone", // name 672 CallAudioState.ROUTE_SPEAKER, // initialRoute 673 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 674 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou 675 NONE, // speakerInteraction 676 NONE, // bluetoothInteraction 677 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action 678 CallAudioState.ROUTE_SPEAKER, // expectedRoute 679 CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes 680 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 681 false, // isNotificationChangeExpected 682 true, // doesDeviceSupportEarpiece 683 shouldRunWithFocus 684 )); 685 686 params.add(new RoutingTestParameters( 687 "Disconnect bluetooth during earpiece", // name 688 CallAudioState.ROUTE_EARPIECE, // initialRoute 689 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 690 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 691 NONE, // speakerInteraction 692 NONE, // bluetoothInteraction 693 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action 694 CallAudioState.ROUTE_EARPIECE, // expectedRoute 695 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 696 NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter 697 true, // isNotificationChangeExpected 698 true, // doesDeviceSupportEarpiece 699 shouldRunWithFocus 700 )); 701 702 params.add(new RoutingTestParameters( 703 "Switch to speakerphone from earpiece", // name 704 CallAudioState.ROUTE_EARPIECE, // initialRoute 705 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 706 CallAudioState.ROUTE_EARPIECE, // availableRoutes 707 ON, // speakerInteraction 708 NONE, // bluetoothInteraction 709 CallAudioRouteStateMachine.SWITCH_SPEAKER, // action 710 CallAudioState.ROUTE_SPEAKER, // expectedRoute 711 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 712 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 713 true, // isNotificationChangeExpected 714 true, // doesDeviceSupportEarpiece 715 shouldRunWithFocus 716 )); 717 718 params.add(new RoutingTestParameters( 719 "Switch to speakerphone from headset", // name 720 CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute 721 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 722 CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes 723 ON, // speakerInteraction 724 NONE, // bluetoothInteraction 725 CallAudioRouteStateMachine.SWITCH_SPEAKER, // action 726 CallAudioState.ROUTE_SPEAKER, // expectedRoute 727 CallAudioState.ROUTE_WIRED_HEADSET, // expectedAvailableRoutes 728 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 729 false, // isNotificationChangeExpected 730 true, // doesDeviceSupportEarpiece 731 shouldRunWithFocus 732 )); 733 734 params.add(new RoutingTestParameters( 735 "Switch to speakerphone from bluetooth", // name 736 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 737 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 738 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou 739 ON, // speakerInteraction 740 OFF, // bluetoothInteraction 741 CallAudioRouteStateMachine.SWITCH_SPEAKER, // action 742 CallAudioState.ROUTE_SPEAKER, // expectedRoute 743 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // expectedAvai 744 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 745 false, // isNotificationChangeExpected 746 true, // doesDeviceSupportEarpiece 747 shouldRunWithFocus 748 )); 749 750 params.add(new RoutingTestParameters( 751 "Switch to earpiece from bluetooth", // name 752 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 753 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 754 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 755 NONE, // speakerInteraction 756 OFF, // bluetoothInteraction 757 CallAudioRouteStateMachine.SWITCH_EARPIECE, // action 758 CallAudioState.ROUTE_EARPIECE, // expectedRoute 759 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable 760 NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter 761 true, // isNotificationChangeExpected 762 true, // doesDeviceSupportEarpiece 763 shouldRunWithFocus 764 )); 765 766 params.add(new RoutingTestParameters( 767 "Switch to earpiece from speakerphone", // name 768 CallAudioState.ROUTE_SPEAKER, // initialRoute 769 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 770 CallAudioState.ROUTE_EARPIECE, // availableRoutes 771 OFF, // speakerInteraction 772 NONE, // bluetoothInteraction 773 CallAudioRouteStateMachine.SWITCH_EARPIECE, // action 774 CallAudioState.ROUTE_EARPIECE, // expectedRoute 775 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 776 NotificationManager.INTERRUPTION_FILTER_ALARMS, // expectedNotificationFilter 777 true, // isNotificationChangeExpected 778 true, // doesDeviceSupportEarpiece 779 shouldRunWithFocus 780 )); 781 782 params.add(new RoutingTestParameters( 783 "Switch to earpiece from speakerphone, priority notifications", // name 784 CallAudioState.ROUTE_SPEAKER, // initialRoute 785 NotificationManager.INTERRUPTION_FILTER_PRIORITY, // initialNotificationFilter 786 CallAudioState.ROUTE_EARPIECE, // availableRoutes 787 OFF, // speakerInteraction 788 NONE, // bluetoothInteraction 789 CallAudioRouteStateMachine.SWITCH_EARPIECE, // action 790 CallAudioState.ROUTE_EARPIECE, // expectedRoute 791 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 792 NotificationManager.INTERRUPTION_FILTER_PRIORITY, // expectedNotificationFilter 793 false, // isNotificationChangeExpected 794 true, // doesDeviceSupportEarpiece 795 shouldRunWithFocus 796 )); 797 798 params.add(new RoutingTestParameters( 799 "Switch to earpiece from speakerphone, silent mode", // name 800 CallAudioState.ROUTE_SPEAKER, // initialRoute 801 NotificationManager.INTERRUPTION_FILTER_NONE, // initialNotificationFilter 802 CallAudioState.ROUTE_EARPIECE, // availableRoutes 803 OFF, // speakerInteraction 804 NONE, // bluetoothInteraction 805 CallAudioRouteStateMachine.SWITCH_EARPIECE, // action 806 CallAudioState.ROUTE_EARPIECE, // expectedRoute 807 CallAudioState.ROUTE_EARPIECE, // expectedAvailableRoutes 808 NotificationManager.INTERRUPTION_FILTER_NONE, // expectedNotificationFilter 809 false, // isNotificationChangeExpected 810 true, // doesDeviceSupportEarpiece 811 shouldRunWithFocus 812 )); 813 814 params.add(new RoutingTestParameters( 815 "Switch to bluetooth from speakerphone", // name 816 CallAudioState.ROUTE_SPEAKER, // initialRoute 817 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 818 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 819 OFF, // speakerInteraction 820 ON, // bluetoothInteraction 821 CallAudioRouteStateMachine.SWITCH_BLUETOOTH, // action 822 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute 823 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable 824 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 825 false, // isNotificationChangeExpected 826 true, // doesDeviceSupportEarpiece 827 shouldRunWithFocus 828 )); 829 830 params.add(new RoutingTestParameters( 831 "Switch to bluetooth from earpiece", // name 832 CallAudioState.ROUTE_EARPIECE, // initialRoute 833 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 834 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 835 NONE, // speakerInteraction 836 ON, // bluetoothInteraction 837 CallAudioRouteStateMachine.SWITCH_BLUETOOTH, // action 838 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute 839 CallAudioState.ROUTE_EARPIECE | CallAudioState.ROUTE_BLUETOOTH, // expectedAvailable 840 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 841 true, // isNotificationChangeExpected 842 true, // doesDeviceSupportEarpiece 843 shouldRunWithFocus 844 )); 845 846 params.add(new RoutingTestParameters( 847 "Switch to bluetooth from wired headset", // name 848 CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute 849 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 850 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // availableRou 851 NONE, // speakerInteraction 852 ON, // bluetoothInteraction 853 CallAudioRouteStateMachine.SWITCH_BLUETOOTH, // action 854 CallAudioState.ROUTE_BLUETOOTH, // expectedRoute 855 CallAudioState.ROUTE_WIRED_HEADSET | CallAudioState.ROUTE_BLUETOOTH, // expectedAvai 856 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 857 false, // isNotificationChangeExpected 858 true, // doesDeviceSupportEarpiece 859 shouldRunWithFocus 860 )); 861 862 params.add(new RoutingTestParameters( 863 "Switch from bluetooth to wired/earpiece when neither are available", // name 864 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 865 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 866 CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 867 ON, // speakerInteraction 868 OFF, // bluetoothInteraction 869 CallAudioRouteStateMachine.SWITCH_BASELINE_ROUTE, // action 870 CallAudioState.ROUTE_SPEAKER, // expectedRoute 871 CallAudioState.ROUTE_BLUETOOTH, // expectedAvailableRoutes 872 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 873 false, // isNotificationChangeExpected 874 false, // doesDeviceSupportEarpiece 875 shouldRunWithFocus 876 )); 877 878 params.add(new RoutingTestParameters( 879 "Disconnect wired headset when device does not support earpiece", // name 880 CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute 881 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 882 CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes 883 ON, // speakerInteraction 884 NONE, // bluetoothInteraction 885 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action 886 CallAudioState.ROUTE_SPEAKER, // expectedRoute 887 CallAudioState.ROUTE_SPEAKER, // expectedAvailableRoutes 888 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 889 false, // isNotificationChangeExpected 890 false, // doesDeviceSupportEarpiece 891 shouldRunWithFocus 892 )); 893 894 params.add(new RoutingTestParameters( 895 "Disconnect wired headset when call doesn't support earpiece", // name 896 CallAudioState.ROUTE_WIRED_HEADSET, // initialRoute 897 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 898 CallAudioState.ROUTE_WIRED_HEADSET, // availableRoutes 899 ON, // speakerInteraction 900 NONE, // bluetoothInteraction 901 CallAudioRouteStateMachine.DISCONNECT_WIRED_HEADSET, // action 902 CallAudioState.ROUTE_SPEAKER, // expectedRoute 903 CallAudioState.ROUTE_SPEAKER, // expectedAvailableRoutes 904 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 905 false, // isNotificationChangeExpected 906 true, // doesDeviceSupportEarpiece 907 shouldRunWithFocus 908 ).setCallSupportedRoutes(CallAudioState.ROUTE_ALL & ~CallAudioState.ROUTE_EARPIECE)); 909 910 params.add(new RoutingTestParameters( 911 "Disconnect bluetooth when call does not support earpiece", // name 912 CallAudioState.ROUTE_BLUETOOTH, // initialRoute 913 NotificationManager.INTERRUPTION_FILTER_ALL, // initialNotificationFilter 914 CallAudioState.ROUTE_BLUETOOTH, // availableRoutes 915 ON, // speakerInteraction 916 OFF, // bluetoothInteraction 917 CallAudioRouteStateMachine.DISCONNECT_BLUETOOTH, // action 918 CallAudioState.ROUTE_SPEAKER, // expectedRoute 919 CallAudioState.ROUTE_SPEAKER, // expectedAvailableRoutes 920 NotificationManager.INTERRUPTION_FILTER_ALL, // expectedNotificationFilter 921 false, // isNotificationChangeExpected 922 true, // doesDeviceSupportEarpiece 923 shouldRunWithFocus 924 ).setCallSupportedRoutes(CallAudioState.ROUTE_ALL & ~CallAudioState.ROUTE_EARPIECE)); 925 926 return params; 927 } 928 929 @Override 930 protected void runParametrizedTestCase(TestParameters _params) throws Throwable { 931 RoutingTestParameters params = (RoutingTestParameters) _params; 932 if (params.shouldRunWithFocus) { 933 runParametrizedTestCaseWithFocus(params); 934 } else { 935 runParametrizedTestCaseWithoutFocus(params); 936 } 937 } 938 939 private void runParametrizedTestCaseWithFocus(final RoutingTestParameters params) 940 throws Throwable { 941 resetMocks(true); 942 when(mMockInterruptionFilterProxy.getCurrentInterruptionFilter()).thenReturn( 943 params.initialNotificationFilter); 944 945 // Construct a fresh state machine on every case 946 final CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( 947 mContext, 948 mockCallsManager, 949 mockBluetoothRouteManager, 950 mockWiredHeadsetManager, 951 mockStatusBarNotifier, 952 mAudioServiceFactory, 953 mMockInterruptionFilterProxy, 954 params.doesDeviceSupportEarpiece); 955 956 setupMocksForParams(params); 957 958 // Set the initial CallAudioState object 959 final CallAudioState initState = new CallAudioState(false, 960 params.initialRoute, (params.availableRoutes | CallAudioState.ROUTE_SPEAKER)); 961 stateMachine.initialize(initState); 962 963 // Make the state machine have focus so that we actually do something 964 stateMachine.sendMessageWithSessionInfo(CallAudioRouteStateMachine.SWITCH_FOCUS, 965 CallAudioRouteStateMachine.ACTIVE_FOCUS); 966 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 967 968 // Reset mocks one more time to discard stuff from initialization 969 resetMocks(false); 970 setupMocksForParams(params); 971 stateMachine.sendMessageWithSessionInfo(params.action); 972 973 waitForStateMachineActionCompletion(stateMachine, CallAudioRouteStateMachine.RUN_RUNNABLE); 974 975 // Capture the changes made to the interruption filter and verify that the last change 976 // made to it matches the expected interruption filter. 977 if (params.isNotificationChangeExpected) { 978 ArgumentCaptor<Integer> interruptionCaptor = ArgumentCaptor.forClass(Integer.class); 979 verify(mMockInterruptionFilterProxy, timeout(TEST_TIMEOUT).atLeastOnce()) 980 .setInterruptionFilter(interruptionCaptor.capture()); 981 List<Integer> interruptionFilterValues = interruptionCaptor.getAllValues(); 982 983 int lastChange = interruptionFilterValues.get(interruptionFilterValues.size() - 1) 984 .intValue(); 985 assertEquals(params.expectedNotificationFilter, lastChange); 986 } else { 987 Thread.sleep(TEST_TIMEOUT); 988 verify(mMockInterruptionFilterProxy, never()).setInterruptionFilter(anyInt()); 989 } 990 991 stateMachine.quitStateMachine(); 992 993 // Verify interactions with the speakerphone and bluetooth systems 994 switch (params.bluetoothInteraction) { 995 case NONE: 996 verify(mockBluetoothRouteManager, never()).disconnectBluetoothAudio(); 997 verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null); 998 break; 999 case ON: 1000 verify(mockBluetoothRouteManager).connectBluetoothAudio(null); 1001 1002 verify(mockBluetoothRouteManager, never()).disconnectBluetoothAudio(); 1003 break; 1004 case OFF: 1005 verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null); 1006 verify(mockBluetoothRouteManager).disconnectBluetoothAudio(); 1007 } 1008 1009 switch (params.speakerInteraction) { 1010 case NONE: 1011 verify(mockAudioManager, never()).setSpeakerphoneOn(any(Boolean.class)); 1012 break; 1013 case ON: // fall through 1014 case OFF: 1015 verify(mockAudioManager).setSpeakerphoneOn(params.speakerInteraction == ON); 1016 } 1017 1018 // Verify the end state 1019 CallAudioState expectedState = new CallAudioState(false, params.expectedRoute, 1020 params.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER); 1021 verifyNewSystemCallAudioState(initState, expectedState); 1022 } 1023 1024 private void setupMocksForParams(RoutingTestParameters params) { 1025 // Set up bluetooth and speakerphone state 1026 when(mockBluetoothRouteManager.isBluetoothAudioConnectedOrPending()).thenReturn( 1027 params.initialRoute == CallAudioState.ROUTE_BLUETOOTH); 1028 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn( 1029 (params.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0 1030 || (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0); 1031 when(mockAudioManager.isSpeakerphoneOn()).thenReturn( 1032 params.initialRoute == CallAudioState.ROUTE_SPEAKER); 1033 when(fakeCall.getSupportedAudioRoutes()).thenReturn(params.callSupportedRoutes); 1034 } 1035 1036 private void runParametrizedTestCaseWithoutFocus(final RoutingTestParameters params) 1037 throws Throwable { 1038 resetMocks(true); 1039 1040 // Construct a fresh state machine on every case 1041 final CallAudioRouteStateMachine stateMachine = new CallAudioRouteStateMachine( 1042 mContext, 1043 mockCallsManager, 1044 mockBluetoothRouteManager, 1045 mockWiredHeadsetManager, 1046 mockStatusBarNotifier, 1047 mAudioServiceFactory, 1048 mMockInterruptionFilterProxy, 1049 params.doesDeviceSupportEarpiece); 1050 1051 // Set up bluetooth and speakerphone state 1052 when(mockBluetoothRouteManager.isBluetoothAvailable()).thenReturn( 1053 (params.availableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0 1054 || (params.expectedAvailableRoutes & CallAudioState.ROUTE_BLUETOOTH) != 0); 1055 when(mockAudioManager.isSpeakerphoneOn()).thenReturn( 1056 params.initialRoute == CallAudioState.ROUTE_SPEAKER); 1057 when(fakeCall.getSupportedAudioRoutes()).thenReturn(params.callSupportedRoutes); 1058 1059 // Set the initial CallAudioState object 1060 CallAudioState initState = new CallAudioState(false, 1061 params.initialRoute, (params.availableRoutes | CallAudioState.ROUTE_SPEAKER)); 1062 stateMachine.initialize(initState); 1063 // Omit the focus-getting statement 1064 stateMachine.sendMessageWithSessionInfo(params.action); 1065 1066 waitForStateMachineActionCompletion(stateMachine, CallAudioModeStateMachine.RUN_RUNNABLE); 1067 1068 stateMachine.quitStateMachine(); 1069 1070 // Verify that no substantive interactions have taken place with the 1071 // rest of the system 1072 verifyNoSystemAudioChanges(); 1073 1074 // Verify the end state 1075 CallAudioState expectedState = new CallAudioState(false, params.expectedRoute, 1076 params.expectedAvailableRoutes | CallAudioState.ROUTE_SPEAKER); 1077 assertEquals(expectedState, stateMachine.getCurrentCallAudioState()); 1078 } 1079 1080 private void verifyNoSystemAudioChanges() { 1081 verify(mockBluetoothRouteManager, never()).disconnectBluetoothAudio(); 1082 verify(mockBluetoothRouteManager, never()).connectBluetoothAudio(null); 1083 verify(mockAudioManager, never()).setSpeakerphoneOn(any(Boolean.class)); 1084 verify(mockCallsManager, never()).onCallAudioStateChanged(any(CallAudioState.class), 1085 any(CallAudioState.class)); 1086 verify(mockConnectionServiceWrapper, never()).onCallAudioStateChanged( 1087 any(Call.class), any(CallAudioState.class)); 1088 } 1089 1090 private void verifyNewSystemCallAudioState(CallAudioState expectedOldState, 1091 CallAudioState expectedNewState) { 1092 ArgumentCaptor<CallAudioState> oldStateCaptor = ArgumentCaptor.forClass( 1093 CallAudioState.class); 1094 ArgumentCaptor<CallAudioState> newStateCaptor1 = ArgumentCaptor.forClass( 1095 CallAudioState.class); 1096 ArgumentCaptor<CallAudioState> newStateCaptor2 = ArgumentCaptor.forClass( 1097 CallAudioState.class); 1098 verify(mockCallsManager, timeout(TEST_TIMEOUT).atLeastOnce()).onCallAudioStateChanged( 1099 oldStateCaptor.capture(), newStateCaptor1.capture()); 1100 verify(mockConnectionServiceWrapper, timeout(TEST_TIMEOUT).atLeastOnce()) 1101 .onCallAudioStateChanged(same(fakeCall), newStateCaptor2.capture()); 1102 1103 assertTrue(oldStateCaptor.getValue().equals(expectedOldState)); 1104 assertTrue(newStateCaptor1.getValue().equals(expectedNewState)); 1105 assertTrue(newStateCaptor2.getValue().equals(expectedNewState)); 1106 } 1107 1108 private void resetMocks(boolean resetNotificationFilter) { 1109 reset(mockAudioManager, mockBluetoothRouteManager, mockCallsManager, 1110 mockConnectionServiceWrapper, fakeCall); 1111 if (resetNotificationFilter) { 1112 reset(mMockInterruptionFilterProxy); 1113 mMockInterruptionFilterProxy = mock(InterruptionFilterProxy.class); 1114 setupInterruptionFilterMocks(); 1115 } 1116 when(mockCallsManager.getForegroundCall()).thenReturn(fakeCall); 1117 when(fakeCall.getConnectionService()).thenReturn(mockConnectionServiceWrapper); 1118 when(fakeCall.isAlive()).thenReturn(true); 1119 when(fakeCall.getSupportedAudioRoutes()).thenReturn(CallAudioState.ROUTE_ALL); 1120 when(mockCallsManager.getLock()).thenReturn(mLock); 1121 doNothing().when(mockConnectionServiceWrapper).onCallAudioStateChanged(any(Call.class), 1122 any(CallAudioState.class)); 1123 } 1124} 1125