Home | History | Annotate | Download | only in tests
      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