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