Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 96c7f18a authored by Himanshu Rawat's avatar Himanshu Rawat
Browse files

Test case to reconnect after restart

Test: atest BumbleBluetoothTests:PairingTests
Bug: 297156490
Flag: TEST_ONLY
Change-Id: Ia437fbb1694ac61f63163c6d06cb3edfdbdcd2aa
parent 3eb89c16
Loading
Loading
Loading
Loading
+269 −150
Original line number Diff line number Diff line
@@ -31,8 +31,10 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.PandoraDevice;
import android.bluetooth.StreamObserverSpliterator;
import android.bluetooth.test_utils.BlockingBluetoothAdapter;
import android.bluetooth.test_utils.EnableBluetoothRule;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -105,14 +107,13 @@ public class PairingTest {
    @Rule(order = 3)
    public final EnableBluetoothRule mEnableBluetoothRule =
        new EnableBluetoothRule(false /* enableTestMode */, true /* toggleBluetooth */);

    @Mock private BroadcastReceiver mReceiver;
    private final Map<String, Integer> mActionRegistrationCounts = new HashMap<>();
    private InOrder mInOrder = null;
    private BluetoothDevice mBumbleDevice;

    private final StreamObserverSpliterator<PairingEvent> mPairingEventStreamObserver =
        new StreamObserverSpliterator<>();
    @Mock
    private BroadcastReceiver mReceiver;
    private InOrder mInOrder = null;
    private BluetoothDevice mBumbleDevice;

    @Before
    public void setUp() throws Exception {
@@ -299,7 +300,7 @@ public class PairingTest {
     *   <li>Service discovery completes
     *   <li>Android cancels the pairing
     * </ol>
     *
     * <p>
     * Expectation: Pairing gets cancelled instead of getting timed out
     */
    @Test
@@ -349,7 +350,7 @@ public class PairingTest {
     *   <li>Android does confirms the pairing
     *   <li>Pairing is successful
     * </ol>
     *
     * <p>
     * Expectation: Pairing succeeds
     */
    @Test
@@ -377,6 +378,124 @@ public class PairingTest {
        unregisterIntentActions(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    }

    /**
     * Test if bonded LE device can reconnect after BT restart
     *
     * <p>Prerequisites:
     *
     * <ol>
     *   <li>Bumble and Android are not bonded
     * </ol>
     *
     * <p>Steps:
     *
     * <ol>
     *   <li>Bumble is discoverable and connectable over LE
     *   <li>Android pairs with Bumble over LE
     *   <li>Android restarts
     *   <li>Bumble is connectable over LE
     *   <li>Android reconnects to Bumble successfully and re-encrypts the link
     * </ol>
     * <p>
     * Expectation: Pairing succeeds
     */
    @Test
    public void testBondLe_Reconnect() {
        registerIntentActions(BluetoothDevice.ACTION_ACL_CONNECTED);

        testStep_BondLe();
        assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice);

        testStep_restartBt();

        assertThat(sAdapter.getBondedDevices()).contains(mBumbleDevice);

        mBumble.hostBlocking()
                .advertise(
                        AdvertiseRequest.newBuilder()
                                .setLegacy(true)
                                .setConnectable(true)
                                .setOwnAddressType(OwnAddressType.PUBLIC)
                                .build());
        assertThat(mBumbleDevice.connect()).isEqualTo(BluetoothStatusCodes.SUCCESS);
        verifyIntentReceived(
                hasAction(BluetoothDevice.ACTION_ACL_CONNECTED),
                hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE),
                hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice));
        verifyNoMoreInteractions(mReceiver);
        unregisterIntentActions(BluetoothDevice.ACTION_ACL_CONNECTED);
    }

    private void testStep_BondLe() {
        registerIntentActions(
                BluetoothDevice.ACTION_BOND_STATE_CHANGED,
                BluetoothDevice.ACTION_ACL_CONNECTED,
                BluetoothDevice.ACTION_PAIRING_REQUEST);

        mBumble.gattBlocking()
            .registerService(
                GattProto.RegisterServiceRequest.newBuilder()
                    .setService(
                        GattProto.GattServiceParams.newBuilder()
                            .setUuid(BATTERY_UUID.toString())
                            .build())
                    .build());

        mBumble.hostBlocking()
            .advertise(
                AdvertiseRequest.newBuilder()
                    .setLegacy(true)
                    .setConnectable(true)
                    .setOwnAddressType(OwnAddressType.PUBLIC)
                    .build());

        StreamObserver<PairingEventAnswer> pairingEventAnswerObserver =
            mBumble.security()
                .withDeadlineAfter(BOND_INTENT_TIMEOUT.toMillis(), TimeUnit.MILLISECONDS)
                .onPairing(mPairingEventStreamObserver);

        assertThat(mBumbleDevice.createBond(BluetoothDevice.TRANSPORT_LE)).isTrue();

        verifyIntentReceivedUnordered(
            hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED),
            hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice),
            hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING));
        verifyIntentReceived(hasAction(BluetoothDevice.ACTION_ACL_CONNECTED),
            hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice),
            hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE));
        verifyIntentReceivedUnordered(
            hasAction(BluetoothDevice.ACTION_PAIRING_REQUEST),
            hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice),
            hasExtra(
                BluetoothDevice.EXTRA_PAIRING_VARIANT,
                BluetoothDevice.PAIRING_VARIANT_CONSENT));

        // Approve pairing from Android
        assertThat(mBumbleDevice.setPairingConfirmation(true)).isTrue();

        PairingEvent pairingEvent = mPairingEventStreamObserver.iterator().next();
        assertThat(pairingEvent.hasJustWorks()).isTrue();
        pairingEventAnswerObserver.onNext(
            PairingEventAnswer.newBuilder().setEvent(pairingEvent).setConfirm(true).build());

        // Ensure that pairing succeeds
        verifyIntentReceived(
            hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED),
            hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice),
            hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED));

        verifyNoMoreInteractions(mReceiver);
        unregisterIntentActions(
                BluetoothDevice.ACTION_BOND_STATE_CHANGED,
                BluetoothDevice.ACTION_ACL_CONNECTED,
                BluetoothDevice.ACTION_PAIRING_REQUEST);
    }

    private void testStep_restartBt() {
        assertThat(BlockingBluetoothAdapter.disable(true)).isTrue();
        assertThat(BlockingBluetoothAdapter.enable()).isTrue();
    }

    /* Starts outgoing GATT service discovery and incoming LE pairing in parallel */
    private StreamObserverSpliterator<SecureResponse>
    helper_OutgoingGattServiceDiscoveryWithIncomingLePairing() {