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