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

Commit 34c494db authored by Himanshu Rawat's avatar Himanshu Rawat Committed by Automerger Merge Worker
Browse files

Avoid duplicate UUID intent on successful service discovery am: 4a36a39d am: e11a6292

parents 34f39a03 e11a6292
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ public class RemoteDevices {
                case MESSAGE_UUID_INTENT:
                    BluetoothDevice device = (BluetoothDevice) msg.obj;
                    if (device != null) {
                        debugLog("MESSAGE_UUID_INTENT: " + device);
                        // SDP Sending delayed SDP UUID intent
                        MetricsLogger.getInstance()
                                .cacheCount(BluetoothProtoEnums.SDP_SENDING_DELAYED_UUID, 1);
@@ -739,7 +740,19 @@ public class RemoteDevices {

        // SDP Sent UUID Intent here
        MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.SDP_SENT_UUID, 1);

        // Remove the outstanding UUID request
        if (Flags.preventDuplicateUuidIntent()) {
            // Handler.removeMessages() compares the object pointer so we cannot use the device
            // directly. So we have to extract original BluetoothDevice object from mSdpTracker.
            int index = mSdpTracker.indexOf(device);
            if (index >= 0) {
                BluetoothDevice originalDevice = mSdpTracker.get(index);
                if (originalDevice != null) {
                    mHandler.removeMessages(MESSAGE_UUID_INTENT, originalDevice);
                }
            }
        }
        mSdpTracker.remove(device);
    }

+132 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.ParcelUuid;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.util.Log;
@@ -46,6 +47,7 @@ import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.bluetooth.flags.Flags;
import com.android.compatibility.common.util.AdoptShellPermissionsRule;

import io.grpc.stub.StreamObserver;
@@ -64,6 +66,7 @@ import org.mockito.MockitoAnnotations;
import org.mockito.hamcrest.MockitoHamcrest;

import pandora.GattProto;
import pandora.HostProto;
import pandora.HostProto.AdvertiseRequest;
import pandora.HostProto.AdvertiseResponse;
import pandora.HostProto.OwnAddressType;
@@ -378,6 +381,135 @@ public class PairingTest {
        unregisterIntentActions(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    }

    /**
     * Ensure that successful BR/EDR service discovery results in a single ACTION_UUID intent
     *
     * <p>Prerequisites:
     *
     * <ol>
     *   <li>Bumble and Android are not bonded
     *   <li>Bumble has BR/EDR services
     * </ol>
     *
     * <p>Steps:
     *
     * <ol>
     *   <li>Bumble is discoverable and connectable over BR/EDR
     *   <li>Android connects to Bumble over BR/EDR
     *   <li>Android starts service discovery
     * </ol>
     *
     * Expectation: A single ACTION_UUID intent is received The ACTION_UUID intent is not empty
     */
    @Test
    @RequiresFlagsEnabled({Flags.FLAG_PREVENT_DUPLICATE_UUID_INTENT})
    public void testServiceDiscoveryBredr_SingleIntent() {
        // Setup intent filters
        registerIntentActions(
                BluetoothDevice.ACTION_UUID,
                BluetoothDevice.ACTION_ACL_CONNECTED,
                BluetoothDevice.ACTION_ACL_DISCONNECTED);

        // Start GATT service discovery, this will establish BR/EDR ACL
        assertThat(mBumbleDevice.fetchUuidsWithSdp(BluetoothDevice.TRANSPORT_BREDR)).isTrue();

        // Wait for connection on Android
        verifyIntentReceived(
                hasAction(BluetoothDevice.ACTION_ACL_CONNECTED),
                hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR));

        // Wait for the service discovery to complete on Android
        verifyIntentReceived(hasAction(BluetoothDevice.ACTION_UUID));

        verifyIntentReceived(
                hasAction(BluetoothDevice.ACTION_ACL_DISCONNECTED),
                hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR));

        // Ensure that no other ACTION_UUID intent is received
        verifyNoMoreInteractions(mReceiver);

        unregisterIntentActions(
                BluetoothDevice.ACTION_UUID,
                BluetoothDevice.ACTION_ACL_CONNECTED,
                BluetoothDevice.ACTION_ACL_DISCONNECTED);
    }

    /**
     * Ensure that successful LE service discovery results in a single ACTION_UUID intent
     *
     * <p>Prerequisites:
     *
     * <ol>
     *   <li>Bumble and Android are not bonded
     *   <li>Bumble has GATT services in addition to GAP and GATT services
     * </ol>
     *
     * <p>Steps:
     *
     * <ol>
     *   <li>Bumble is discoverable and connectable over LE
     *   <li>Android connects to Bumble over LE
     *   <li>Android starts GATT service discovery
     * </ol>
     *
     * Expectation: A single ACTION_UUID intent is received The ACTION_UUID intent is not empty
     */
    @Test
    @RequiresFlagsEnabled({Flags.FLAG_PREVENT_DUPLICATE_UUID_INTENT})
    public void testServiceDiscoveryLe_SingleIntent() {
        // Setup intent filters
        registerIntentActions(
                BluetoothDevice.ACTION_UUID,
                BluetoothDevice.ACTION_ACL_CONNECTED,
                BluetoothDevice.ACTION_ACL_DISCONNECTED);

        // Register some services on Bumble
        for (int i = 0; i < 6; i++) {
            mBumble.gattBlocking()
                    .registerService(
                            GattProto.RegisterServiceRequest.newBuilder()
                                    .setService(
                                            GattProto.GattServiceParams.newBuilder()
                                                    .setUuid(BATTERY_UUID.toString())
                                                    .build())
                                    .build());
        }

        // Make Bumble connectable
        mBumble.hostBlocking()
                .advertise(
                        HostProto.AdvertiseRequest.newBuilder()
                                .setLegacy(true)
                                .setConnectable(true)
                                .setOwnAddressType(HostProto.OwnAddressType.PUBLIC)
                                .build());

        // Start GATT service discovery, this will establish LE ACL
        assertThat(mBumbleDevice.fetchUuidsWithSdp(BluetoothDevice.TRANSPORT_LE)).isTrue();

        // Wait for connection on Android
        verifyIntentReceived(
                hasAction(BluetoothDevice.ACTION_ACL_CONNECTED),
                hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE));

        // Wait for GATT service discovery to complete on Android
        verifyIntentReceived(
                hasAction(BluetoothDevice.ACTION_UUID),
                hasExtra(BluetoothDevice.EXTRA_UUID, Matchers.hasItemInArray(BATTERY_UUID)));

        verifyIntentReceived(
                hasAction(BluetoothDevice.ACTION_ACL_DISCONNECTED),
                hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE));

        // Ensure that no other ACTION_UUID intent is received
        verifyNoMoreInteractions(mReceiver);

        unregisterIntentActions(
                BluetoothDevice.ACTION_UUID,
                BluetoothDevice.ACTION_ACL_CONNECTED,
                BluetoothDevice.ACTION_ACL_DISCONNECTED);
    }

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