1 /* 2 * Copyright (C) 2018 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 17 package com.android.server.telecom.tests; 18 19 import android.bluetooth.BluetoothDevice; 20 import android.bluetooth.BluetoothHeadset; 21 import android.content.ContentResolver; 22 import android.test.suitebuilder.annotation.SmallTest; 23 24 import com.android.server.telecom.BluetoothHeadsetProxy; 25 import com.android.server.telecom.TelecomSystem; 26 import com.android.server.telecom.Timeouts; 27 import com.android.server.telecom.bluetooth.BluetoothDeviceManager; 28 import com.android.server.telecom.bluetooth.BluetoothRouteManager; 29 30 import org.junit.Before; 31 import org.junit.Test; 32 import org.junit.runner.RunWith; 33 import org.junit.runners.Parameterized; 34 import org.mockito.Mock; 35 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.Collection; 39 import java.util.List; 40 import java.util.Objects; 41 42 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE1; 43 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE2; 44 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.DEVICE3; 45 import static com.android.server.telecom.tests.BluetoothRouteManagerTest.executeRoutingAction; 46 import static org.junit.Assert.assertEquals; 47 import static org.mockito.ArgumentMatchers.eq; 48 import static org.mockito.ArgumentMatchers.nullable; 49 import static org.mockito.Mockito.doAnswer; 50 import static org.mockito.Mockito.never; 51 import static org.mockito.Mockito.reset; 52 import static org.mockito.Mockito.verify; 53 import static org.mockito.Mockito.when; 54 55 @RunWith(Parameterized.class) 56 public class BluetoothRouteTransitionTests extends TelecomTestCase { 57 private enum ListenerUpdate { 58 DEVICE_LIST_CHANGED, ACTIVE_DEVICE_PRESENT, ACTIVE_DEVICE_GONE, 59 AUDIO_CONNECTED, AUDIO_DISCONNECTED 60 } 61 62 private static class BluetoothRouteTestParametersBuilder { 63 private String name; 64 private String initialBluetoothState; 65 private BluetoothDevice initialDevice; 66 private BluetoothDevice audioOnDevice; 67 private int messageType; 68 private BluetoothDevice messageDevice; 69 private ListenerUpdate[] expectedListenerUpdates; 70 private int expectedBluetoothInteraction; 71 private BluetoothDevice expectedConnectionDevice; 72 private String expectedFinalStateName; 73 private BluetoothDevice[] connectedDevices; 74 // the active device as returned by BluetoothHeadset#getActiveDevice 75 private BluetoothDevice activeDevice = null; 76 77 public BluetoothRouteTestParametersBuilder setName(String name) { 78 this.name = name; 79 return this; 80 } 81 82 public BluetoothRouteTestParametersBuilder setInitialBluetoothState( 83 String initialBluetoothState) { 84 this.initialBluetoothState = initialBluetoothState; 85 return this; 86 } 87 88 public BluetoothRouteTestParametersBuilder setInitialDevice(BluetoothDevice 89 initialDevice) { 90 this.initialDevice = initialDevice; 91 return this; 92 } 93 94 public BluetoothRouteTestParametersBuilder setMessageType(int messageType) { 95 this.messageType = messageType; 96 return this; 97 } 98 99 public BluetoothRouteTestParametersBuilder setMessageDevice(BluetoothDevice messageDevice) { 100 this.messageDevice = messageDevice; 101 return this; 102 } 103 104 public BluetoothRouteTestParametersBuilder setExpectedListenerUpdates( 105 ListenerUpdate... expectedListenerUpdates) { 106 this.expectedListenerUpdates = expectedListenerUpdates; 107 return this; 108 } 109 110 public BluetoothRouteTestParametersBuilder setExpectedBluetoothInteraction( 111 int expectedBluetoothInteraction) { 112 this.expectedBluetoothInteraction = expectedBluetoothInteraction; 113 return this; 114 } 115 116 public BluetoothRouteTestParametersBuilder setExpectedConnectionDevice( 117 BluetoothDevice expectedConnectionDevice) { 118 this.expectedConnectionDevice = expectedConnectionDevice; 119 return this; 120 } 121 122 public BluetoothRouteTestParametersBuilder setExpectedFinalStateName( 123 String expectedFinalStateName) { 124 this.expectedFinalStateName = expectedFinalStateName; 125 return this; 126 } 127 128 public BluetoothRouteTestParametersBuilder setConnectedDevices( 129 BluetoothDevice... connectedDevices) { 130 this.connectedDevices = connectedDevices; 131 return this; 132 } 133 134 public BluetoothRouteTestParametersBuilder setAudioOnDevice(BluetoothDevice device) { 135 this.audioOnDevice = device; 136 return this; 137 } 138 139 public BluetoothRouteTestParametersBuilder setActiveDevice(BluetoothDevice device) { 140 this.activeDevice = device; 141 return this; 142 } 143 144 public BluetoothRouteTestParameters build() { 145 return new BluetoothRouteTestParameters(name, 146 initialBluetoothState, 147 initialDevice, 148 messageType, 149 expectedListenerUpdates, 150 expectedBluetoothInteraction, 151 expectedConnectionDevice, 152 expectedFinalStateName, 153 connectedDevices, 154 messageDevice, 155 audioOnDevice, 156 activeDevice); 157 158 } 159 } 160 161 private static class BluetoothRouteTestParameters { 162 public String name; 163 public String initialBluetoothState; // One of the state names or prefixes from BRM. 164 public BluetoothDevice initialDevice; // null if we start from AudioOff 165 public BluetoothDevice audioOnDevice; // The device (if any) that is active 166 public int messageType; // Any of the commands from the state machine 167 public BluetoothDevice messageDevice; // The device that should be specified in the message. 168 public ListenerUpdate[] expectedListenerUpdates; // what the listener should expect. 169 public int expectedBluetoothInteraction; // NONE, CONNECT, or DISCONNECT 170 public BluetoothDevice expectedConnectionDevice; // Expected device to connect to. 171 public String expectedFinalStateName; // Expected name of the final state. 172 public BluetoothDevice[] connectedDevices; // array of connected devices 173 // the active device as returned by BluetoothHeadset#getActiveDevice 174 private BluetoothDevice activeDevice = null; 175 176 public BluetoothRouteTestParameters(String name, String initialBluetoothState, 177 BluetoothDevice initialDevice, int messageType, ListenerUpdate[] 178 expectedListenerUpdates, int expectedBluetoothInteraction, BluetoothDevice 179 expectedConnectionDevice, String expectedFinalStateName, 180 BluetoothDevice[] connectedDevices, BluetoothDevice messageDevice, 181 BluetoothDevice audioOnDevice, BluetoothDevice activeDevice) { 182 this.name = name; 183 this.initialBluetoothState = initialBluetoothState; 184 this.initialDevice = initialDevice; 185 this.messageType = messageType; 186 this.expectedListenerUpdates = expectedListenerUpdates; 187 this.expectedBluetoothInteraction = expectedBluetoothInteraction; 188 this.expectedConnectionDevice = expectedConnectionDevice; 189 this.expectedFinalStateName = expectedFinalStateName; 190 this.connectedDevices = connectedDevices; 191 this.messageDevice = messageDevice; 192 this.audioOnDevice = audioOnDevice; 193 this.activeDevice = activeDevice; 194 } 195 196 @Override 197 public String toString() { 198 return "BluetoothRouteTestParameters{" + 199 "name='" + name + '\'' + 200 ", initialBluetoothState='" + initialBluetoothState + '\'' + 201 ", initialDevice=" + initialDevice + 202 ", messageType=" + messageType + 203 ", messageDevice='" + messageDevice + '\'' + 204 ", expectedListenerUpdate=" + expectedListenerUpdates + 205 ", expectedBluetoothInteraction=" + expectedBluetoothInteraction + 206 ", expectedConnectionDevice='" + expectedConnectionDevice + '\'' + 207 ", expectedFinalStateName='" + expectedFinalStateName + '\'' + 208 ", connectedDevices=" + Arrays.toString(connectedDevices) + 209 ", activeDevice='" + activeDevice + '\'' + 210 '}'; 211 } 212 } 213 214 private static final int NONE = 1; 215 private static final int CONNECT = 2; 216 private static final int DISCONNECT = 3; 217 218 private static final int TEST_TIMEOUT = 1000; 219 220 private final BluetoothRouteTestParameters mParams; 221 @Mock private BluetoothDeviceManager mDeviceManager; 222 @Mock private BluetoothHeadsetProxy mHeadsetProxy; 223 @Mock private Timeouts.Adapter mTimeoutsAdapter; 224 @Mock private BluetoothRouteManager.BluetoothStateListener mListener; 225 226 @Override 227 @Before 228 public void setUp() throws Exception { 229 super.setUp(); 230 } 231 232 public BluetoothRouteTransitionTests(BluetoothRouteTestParameters params) { 233 mParams = params; 234 } 235 236 @Test 237 @SmallTest 238 public void testTransitions() { 239 BluetoothRouteManager sm = setupStateMachine( 240 mParams.initialBluetoothState, mParams.initialDevice); 241 242 setupConnectedDevices(mParams.connectedDevices, 243 mParams.audioOnDevice, mParams.activeDevice); 244 sm.setActiveDeviceCacheForTesting(mParams.activeDevice); 245 246 // Go through the utility methods for these two messages 247 if (mParams.messageType == BluetoothRouteManager.NEW_DEVICE_CONNECTED) { 248 sm.onDeviceAdded(mParams.messageDevice.getAddress()); 249 sm.onActiveDeviceChanged(mParams.messageDevice); 250 } else if (mParams.messageType == BluetoothRouteManager.LOST_DEVICE) { 251 sm.onDeviceLost(mParams.messageDevice.getAddress()); 252 sm.onActiveDeviceChanged(null); 253 } else { 254 executeRoutingAction(sm, mParams.messageType, 255 mParams.messageDevice == null ? null : mParams.messageDevice.getAddress()); 256 } 257 258 waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); 259 assertEquals(mParams.expectedFinalStateName, sm.getCurrentState().getName()); 260 261 for (ListenerUpdate lu : mParams.expectedListenerUpdates) { 262 switch (lu) { 263 case DEVICE_LIST_CHANGED: 264 verify(mListener).onBluetoothDeviceListChanged(); 265 break; 266 case ACTIVE_DEVICE_PRESENT: 267 verify(mListener).onBluetoothActiveDevicePresent(); 268 break; 269 case ACTIVE_DEVICE_GONE: 270 verify(mListener).onBluetoothActiveDeviceGone(); 271 break; 272 case AUDIO_CONNECTED: 273 verify(mListener).onBluetoothAudioConnected(); 274 break; 275 case AUDIO_DISCONNECTED: 276 verify(mListener).onBluetoothAudioDisconnected(); 277 break; 278 } 279 } 280 281 switch (mParams.expectedBluetoothInteraction) { 282 case NONE: 283 verify(mHeadsetProxy, never()).connectAudio(); 284 verify(mHeadsetProxy, never()).setActiveDevice(nullable(BluetoothDevice.class)); 285 verify(mHeadsetProxy, never()).disconnectAudio(); 286 break; 287 case CONNECT: 288 verify(mHeadsetProxy).connectAudio(); 289 verify(mHeadsetProxy).setActiveDevice(mParams.expectedConnectionDevice); 290 verify(mHeadsetProxy, never()).disconnectAudio(); 291 break; 292 case DISCONNECT: 293 verify(mHeadsetProxy, never()).connectAudio(); 294 verify(mHeadsetProxy, never()).setActiveDevice(nullable(BluetoothDevice.class)); 295 verify(mHeadsetProxy).disconnectAudio(); 296 break; 297 } 298 299 sm.getHandler().removeMessages(BluetoothRouteManager.CONNECTION_TIMEOUT); 300 sm.quitNow(); 301 } 302 303 private void setupConnectedDevices(BluetoothDevice[] devices, 304 BluetoothDevice audioOnDevice, BluetoothDevice activeDevice) { 305 when(mDeviceManager.getNumConnectedDevices()).thenReturn(devices.length); 306 when(mDeviceManager.getConnectedDevices()).thenReturn(Arrays.asList(devices)); 307 when(mHeadsetProxy.getConnectedDevices()).thenReturn(Arrays.asList(devices)); 308 when(mHeadsetProxy.getActiveDevice()).thenReturn(activeDevice); 309 if (audioOnDevice != null) { 310 when(mHeadsetProxy.getAudioState(eq(audioOnDevice))) 311 .thenReturn(BluetoothHeadset.STATE_AUDIO_CONNECTED); 312 } 313 doAnswer(invocation -> { 314 BluetoothDevice first = getFirstExcluding(devices, 315 (String) invocation.getArguments()[0]); 316 return first == null ? null : first.getAddress(); 317 }).when(mDeviceManager).getMostRecentlyConnectedDevice(nullable(String.class)); 318 for (BluetoothDevice device : devices) { 319 when(mDeviceManager.getDeviceFromAddress(device.getAddress())).thenReturn(device); 320 } 321 } 322 323 private BluetoothRouteManager setupStateMachine(String initialState, 324 BluetoothDevice initialDevice) { 325 resetMocks(); 326 BluetoothRouteManager sm = new BluetoothRouteManager(mContext, 327 new TelecomSystem.SyncRoot() { }, mDeviceManager, mTimeoutsAdapter); 328 sm.setListener(mListener); 329 sm.setInitialStateForTesting(initialState, initialDevice); 330 waitForHandlerAction(sm.getHandler(), TEST_TIMEOUT); 331 resetMocks(); 332 return sm; 333 } 334 335 private void resetMocks() { 336 reset(mDeviceManager, mListener, mHeadsetProxy, mTimeoutsAdapter); 337 when(mDeviceManager.getHeadsetService()).thenReturn(mHeadsetProxy); 338 when(mHeadsetProxy.connectAudio()).thenReturn(true); 339 when(mHeadsetProxy.setActiveDevice(nullable(BluetoothDevice.class))).thenReturn(true); 340 when(mTimeoutsAdapter.getRetryBluetoothConnectAudioBackoffMillis( 341 nullable(ContentResolver.class))).thenReturn(100000L); 342 when(mTimeoutsAdapter.getBluetoothPendingTimeoutMillis( 343 nullable(ContentResolver.class))).thenReturn(100000L); 344 } 345 346 private static BluetoothDevice getFirstExcluding( 347 BluetoothDevice[] devices, String excludeAddress) { 348 for (BluetoothDevice x : devices) { 349 if (!Objects.equals(excludeAddress, x.getAddress())) { 350 return x; 351 } 352 } 353 return null; 354 } 355 356 @Parameterized.Parameters(name = "{0}") 357 public static Collection<BluetoothRouteTestParameters> generateTestCases() { 358 List<BluetoothRouteTestParameters> result = new ArrayList<>(); 359 result.add(new BluetoothRouteTestParametersBuilder() 360 .setName("New device connected while audio off") 361 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 362 .setInitialDevice(null) 363 .setConnectedDevices(DEVICE1) 364 .setMessageType(BluetoothRouteManager.NEW_DEVICE_CONNECTED) 365 .setMessageDevice(DEVICE1) 366 .setExpectedListenerUpdates(ListenerUpdate.DEVICE_LIST_CHANGED, 367 ListenerUpdate.ACTIVE_DEVICE_PRESENT) 368 .setExpectedBluetoothInteraction(NONE) 369 .setExpectedConnectionDevice(null) 370 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 371 .build()); 372 373 result.add(new BluetoothRouteTestParametersBuilder() 374 .setName("Nonspecific connection request while audio off with BT-active device") 375 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 376 .setInitialDevice(null) 377 .setConnectedDevices(DEVICE2, DEVICE1) 378 .setActiveDevice(DEVICE1) 379 .setMessageType(BluetoothRouteManager.CONNECT_HFP) 380 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED) 381 .setExpectedBluetoothInteraction(CONNECT) 382 .setExpectedConnectionDevice(DEVICE1) 383 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX 384 + ":" + DEVICE1) 385 .build()); 386 387 result.add(new BluetoothRouteTestParametersBuilder() 388 .setName("Connection to a device succeeds after pending") 389 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX) 390 .setInitialDevice(DEVICE2) 391 .setAudioOnDevice(DEVICE2) 392 .setConnectedDevices(DEVICE2, DEVICE1) 393 .setMessageType(BluetoothRouteManager.HFP_IS_ON) 394 .setMessageDevice(DEVICE2) 395 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED) 396 .setExpectedBluetoothInteraction(NONE) 397 .setExpectedConnectionDevice(null) 398 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX 399 + ":" + DEVICE2) 400 .build()); 401 402 result.add(new BluetoothRouteTestParametersBuilder() 403 .setName("Device loses HFP audio but remains connected. No fallback.") 404 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX) 405 .setInitialDevice(DEVICE2) 406 .setConnectedDevices(DEVICE2) 407 .setMessageType(BluetoothRouteManager.HFP_LOST) 408 .setMessageDevice(DEVICE2) 409 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED) 410 .setExpectedBluetoothInteraction(NONE) 411 .setExpectedConnectionDevice(null) 412 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 413 .build()); 414 415 result.add(new BluetoothRouteTestParametersBuilder() 416 .setName("Device loses HFP audio but remains connected." 417 + " No fallback even though other devices available.") 418 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX) 419 .setInitialDevice(DEVICE2) 420 .setConnectedDevices(DEVICE2, DEVICE1, DEVICE3) 421 .setMessageType(BluetoothRouteManager.HFP_LOST) 422 .setMessageDevice(DEVICE2) 423 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED) 424 .setExpectedBluetoothInteraction(NONE) 425 .setExpectedConnectionDevice(null) 426 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 427 .build()); 428 429 result.add(new BluetoothRouteTestParametersBuilder() 430 .setName("Switch the device that audio is being routed to") 431 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX) 432 .setInitialDevice(DEVICE2) 433 .setConnectedDevices(DEVICE2, DEVICE1, DEVICE3) 434 .setMessageType(BluetoothRouteManager.CONNECT_HFP) 435 .setMessageDevice(DEVICE3) 436 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED) 437 .setExpectedBluetoothInteraction(CONNECT) 438 .setExpectedConnectionDevice(DEVICE3) 439 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX 440 + ":" + DEVICE3) 441 .build()); 442 443 result.add(new BluetoothRouteTestParametersBuilder() 444 .setName("Switch to another device before first device has connected") 445 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX) 446 .setInitialDevice(DEVICE2) 447 .setConnectedDevices(DEVICE2, DEVICE1, DEVICE3) 448 .setMessageType(BluetoothRouteManager.CONNECT_HFP) 449 .setMessageDevice(DEVICE3) 450 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED) 451 .setExpectedBluetoothInteraction(CONNECT) 452 .setExpectedConnectionDevice(DEVICE3) 453 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX 454 + ":" + DEVICE3) 455 .build()); 456 457 result.add(new BluetoothRouteTestParametersBuilder() 458 .setName("Device gets disconnected while active. No fallback.") 459 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX) 460 .setInitialDevice(DEVICE2) 461 .setActiveDevice(DEVICE2) 462 .setConnectedDevices() 463 .setMessageType(BluetoothRouteManager.LOST_DEVICE) 464 .setMessageDevice(DEVICE2) 465 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED, 466 ListenerUpdate.DEVICE_LIST_CHANGED, ListenerUpdate.ACTIVE_DEVICE_GONE) 467 .setExpectedBluetoothInteraction(NONE) 468 .setExpectedConnectionDevice(null) 469 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 470 .build()); 471 472 result.add(new BluetoothRouteTestParametersBuilder() 473 .setName("Device gets disconnected while active." 474 + " No fallback even though other devices available.") 475 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX) 476 .setInitialDevice(DEVICE2) 477 .setConnectedDevices(DEVICE3) 478 .setMessageType(BluetoothRouteManager.LOST_DEVICE) 479 .setMessageDevice(DEVICE2) 480 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED, 481 ListenerUpdate.DEVICE_LIST_CHANGED) 482 .setExpectedBluetoothInteraction(NONE) 483 .setExpectedConnectionDevice(null) 484 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 485 .build()); 486 487 result.add(new BluetoothRouteTestParametersBuilder() 488 .setName("Connection to DEVICE2 times out but device 1 still connected.") 489 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX) 490 .setInitialDevice(DEVICE2) 491 .setConnectedDevices(DEVICE2, DEVICE1) 492 .setAudioOnDevice(DEVICE1) 493 .setMessageType(BluetoothRouteManager.CONNECTION_TIMEOUT) 494 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED) 495 .setExpectedBluetoothInteraction(NONE) 496 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX 497 + ":" + DEVICE1) 498 .build()); 499 500 result.add(new BluetoothRouteTestParametersBuilder() 501 .setName("DEVICE1 somehow becomes active when DEVICE2 is still pending.") 502 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX) 503 .setInitialDevice(DEVICE2) 504 .setConnectedDevices(DEVICE2, DEVICE1) 505 .setAudioOnDevice(DEVICE1) 506 .setMessageType(BluetoothRouteManager.HFP_IS_ON) 507 .setMessageDevice(DEVICE1) 508 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED) 509 .setExpectedBluetoothInteraction(NONE) 510 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX 511 + ":" + DEVICE1) 512 .build()); 513 514 result.add(new BluetoothRouteTestParametersBuilder() 515 .setName("Device gets disconnected while pending." 516 + " No fallback even though other devices available.") 517 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX) 518 .setInitialDevice(DEVICE2) 519 .setConnectedDevices(DEVICE3) 520 .setMessageType(BluetoothRouteManager.LOST_DEVICE) 521 .setMessageDevice(DEVICE2) 522 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED, 523 ListenerUpdate.DEVICE_LIST_CHANGED) 524 .setExpectedBluetoothInteraction(NONE) 525 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 526 .build()); 527 528 result.add(new BluetoothRouteTestParametersBuilder() 529 .setName("Device gets disconnected while pending. No fallback.") 530 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX) 531 .setInitialDevice(DEVICE2) 532 .setConnectedDevices() 533 .setMessageType(BluetoothRouteManager.LOST_DEVICE) 534 .setMessageDevice(DEVICE2) 535 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED, 536 ListenerUpdate.DEVICE_LIST_CHANGED) 537 .setExpectedBluetoothInteraction(NONE) 538 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 539 .build()); 540 541 result.add(new BluetoothRouteTestParametersBuilder() 542 .setName("Audio routing requests HFP disconnection while a device is active") 543 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX) 544 .setInitialDevice(DEVICE2) 545 .setConnectedDevices(DEVICE2, DEVICE3) 546 .setMessageType(BluetoothRouteManager.DISCONNECT_HFP) 547 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED) 548 .setExpectedBluetoothInteraction(DISCONNECT) 549 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 550 .build()); 551 552 result.add(new BluetoothRouteTestParametersBuilder() 553 .setName("Audio routing requests HFP disconnection while a device is pending") 554 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_CONNECTING_STATE_NAME_PREFIX) 555 .setInitialDevice(DEVICE2) 556 .setConnectedDevices(DEVICE2, DEVICE3) 557 .setMessageType(BluetoothRouteManager.DISCONNECT_HFP) 558 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_DISCONNECTED) 559 .setExpectedBluetoothInteraction(DISCONNECT) 560 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 561 .build()); 562 563 result.add(new BluetoothRouteTestParametersBuilder() 564 .setName("Bluetooth turns itself on.") 565 .setInitialBluetoothState(BluetoothRouteManager.AUDIO_OFF_STATE_NAME) 566 .setInitialDevice(null) 567 .setConnectedDevices(DEVICE2, DEVICE3) 568 .setMessageType(BluetoothRouteManager.HFP_IS_ON) 569 .setMessageDevice(DEVICE3) 570 .setExpectedListenerUpdates(ListenerUpdate.AUDIO_CONNECTED) 571 .setExpectedBluetoothInteraction(NONE) 572 .setExpectedFinalStateName(BluetoothRouteManager.AUDIO_CONNECTED_STATE_NAME_PREFIX 573 + ":" + DEVICE3) 574 .build()); 575 576 return result; 577 } 578 } 579