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

Commit 2a5b9e30 authored by Omair Kamil's avatar Omair Kamil
Browse files

Add bumble test for scanning with service data filter.

Also fix some typos in ScanFilterQueue.

Bug: 348818819
Test: atest LeScanningTest
Flag: EXEMPT, test addition and typos
Change-Id: I1ad60262f34240f714c0575634089625aefaa4bb
parent 187eec2b
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -256,8 +256,8 @@ import java.util.UUID;
                serviceDataMask = new byte[serviceData.length];
                Arrays.fill(serviceDataMask, (byte) 0xFF);
            }
            serviceData = concate(serviceDataUuid, serviceData);
            serviceDataMask = concate(serviceDataUuid, serviceDataMask);
            serviceData = concatenate(serviceDataUuid, serviceData);
            serviceDataMask = concatenate(serviceDataUuid, serviceDataMask);
            if (serviceData != null && serviceDataMask != null) {
                addServiceData(serviceData, serviceDataMask);
            }
@@ -293,7 +293,7 @@ import java.util.UUID;
        }
    }

    private byte[] concate(ParcelUuid serviceDataUuid, byte[] serviceData) {
    private byte[] concatenate(ParcelUuid serviceDataUuid, byte[] serviceData) {
        byte[] uuid = BluetoothUuid.uuidToBytes(serviceDataUuid);

        int dataLen = uuid.length + (serviceData == null ? 0 : serviceData.length);
@@ -301,11 +301,11 @@ import java.util.UUID;
        if (dataLen > MAX_LEN_PER_FIELD) {
            return null;
        }
        byte[] concated = new byte[dataLen];
        System.arraycopy(uuid, 0, concated, 0, uuid.length);
        byte[] concatenated = new byte[dataLen];
        System.arraycopy(uuid, 0, concatenated, 0, uuid.length);
        if (serviceData != null) {
            System.arraycopy(serviceData, 0, concated, uuid.length, serviceData.length);
            System.arraycopy(serviceData, 0, concatenated, uuid.length, serviceData.length);
        }
        return concated;
        return concatenated;
    }
}
+75 −21
Original line number Diff line number Diff line
@@ -41,11 +41,12 @@ import android.os.ParcelUuid;
import android.util.Log;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.compatibility.common.util.AdoptShellPermissionsRule;

import com.google.protobuf.ByteString;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;

import org.junit.Rule;
import org.junit.Test;
@@ -63,7 +64,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

@RunWith(AndroidJUnit4.class)
@RunWith(TestParameterInjector.class)
public class LeScanningTest {
    private static final String TAG = "LeScanningTest";
    private static final int TIMEOUT_SCANNING_MS = 2000;
@@ -71,6 +72,8 @@ public class LeScanningTest {
    private static final String TEST_ADDRESS_RANDOM_STATIC = "F0:43:A8:23:10:11";
    private static final String ACTION_DYNAMIC_RECEIVER_SCAN_RESULT =
            "android.bluetooth.test.ACTION_DYNAMIC_RECEIVER_SCAN_RESULT";
    private static final byte[] TEST_SERVICE_DATA = {(byte) 0xAA, (byte) 0xBB, (byte) 0xCC};
    private static final String TEST_UUID_SUFFIX = "-0000-1000-8000-00805f9b34fb";

    @Rule public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule();

@@ -92,7 +95,8 @@ public class LeScanningTest {
                        .build();

        List<ScanResult> results =
                startScanning(scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
                startScanning(
                        scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES, /* isLegacy= */ true);

        assertThat(results).isNotNull();
        assertThat(results.get(0).getScanRecord().getServiceUuids().get(0))
@@ -114,7 +118,8 @@ public class LeScanningTest {
                        .build();

        List<ScanResult> results =
                startScanning(scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
                startScanning(
                        scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES, /* isLegacy= */ true);

        assertThat(results).isNotEmpty();
        assertThat(results.get(0).getDevice().getAddress()).isEqualTo(TEST_ADDRESS_RANDOM_STATIC);
@@ -295,7 +300,7 @@ public class LeScanningTest {
                AdvertiseRequest.newBuilder()
                        .setConnectable(false)
                        .setOwnAddressType(OwnAddressType.PUBLIC);
        advertiseWithBumble(requestBuilder);
        advertiseWithBumble(requestBuilder, true);

        ScanFilter scanFilter =
                new ScanFilter.Builder()
@@ -303,7 +308,8 @@ public class LeScanningTest {
                        .build();

        List<ScanResult> results =
                startScanning(scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
                startScanning(
                        scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES, /* isLegacy= */ true);

        assertThat(results).isNotNull();
        assertThat(results.get(0).isConnectable()).isFalse();
@@ -324,7 +330,7 @@ public class LeScanningTest {
                        .setConnectable(false)
                        .setOwnAddressType(OwnAddressType.PUBLIC)
                        .setScanResponseData(scanResponse);
        advertiseWithBumble(requestBuilder);
        advertiseWithBumble(requestBuilder, true);

        ScanFilter scanFilter =
                new ScanFilter.Builder()
@@ -332,7 +338,8 @@ public class LeScanningTest {
                        .build();

        List<ScanResult> results =
                startScanning(scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES);
                startScanning(
                        scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES, /* isLegacy= */ true);

        assertThat(results).isNotNull();
        assertThat(results.get(0).isConnectable()).isFalse();
@@ -340,7 +347,46 @@ public class LeScanningTest {
                .isEqualTo(payload);
    }

    private List<ScanResult> startScanning(ScanFilter scanFilter, int callbackType) {
    @Test
    public void startBleScan_withServiceData() {
        advertiseWithBumbleWithServiceData();

        ScanFilter scanFilter =
                new ScanFilter.Builder()
                        .setServiceData(ParcelUuid.fromString(TEST_UUID_STRING), TEST_SERVICE_DATA)
                        .build();

        List<ScanResult> results =
                startScanning(
                        scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES, /* isLegacy= */ false);

        assertThat(results).isNotNull();
        assertThat(results.get(0).getScanRecord().getServiceUuids().get(0))
                .isEqualTo(ParcelUuid.fromString(TEST_UUID_STRING));
    }

    // Test against UUIDs that are close to TEST_UUID_STRING, one that has a few bits unset and one
    // that has an extra bit set.
    @Test
    public void startBleScan_withServiceData_uuidDoesntMatch(
            @TestParameter({"00001800", "00001815"}) String uuid) {
        advertiseWithBumbleWithServiceData();

        ScanFilter scanFilter =
                new ScanFilter.Builder()
                        .setServiceData(
                                ParcelUuid.fromString(uuid + TEST_UUID_SUFFIX), TEST_SERVICE_DATA)
                        .build();

        List<ScanResult> results =
                startScanning(
                        scanFilter, ScanSettings.CALLBACK_TYPE_ALL_MATCHES, /* isLegacy= */ false);

        assertThat(results).isNull();
    }

    private List<ScanResult> startScanning(
            ScanFilter scanFilter, int callbackType, boolean isLegacy) {
        CompletableFuture<List<ScanResult>> future = new CompletableFuture<>();
        List<ScanResult> scanResults = new ArrayList<>();

@@ -348,6 +394,7 @@ public class LeScanningTest {
                new ScanSettings.Builder()
                        .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                        .setCallbackType(callbackType)
                        .setLegacy(isLegacy)
                        .build();

        ScanCallback scanCallback =
@@ -366,14 +413,9 @@ public class LeScanningTest {
                                        + ", service uuids: "
                                        + result.getScanRecord().getServiceUuids());

                        if (callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
                            if (scanResults.size() < 2) {
                                scanResults.add(result);
                            } else {
                                future.complete(scanResults);
                            }
                        } else {
                        scanResults.add(result);
                        if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES
                                || scanResults.size() > 1) {
                            future.complete(scanResults);
                        }
                    }
@@ -395,6 +437,19 @@ public class LeScanningTest {
        return result;
    }

    private void advertiseWithBumbleWithServiceData() {
        AdvertiseRequest.Builder requestBuilder =
                AdvertiseRequest.newBuilder().setOwnAddressType(OwnAddressType.PUBLIC);

        HostProto.DataTypes.Builder dataTypeBuilder = HostProto.DataTypes.newBuilder();
        dataTypeBuilder.addCompleteServiceClassUuids128(TEST_UUID_STRING);
        dataTypeBuilder.putServiceDataUuid128(
                TEST_UUID_STRING, ByteString.copyFrom(TEST_SERVICE_DATA));
        requestBuilder.setData(dataTypeBuilder.build());

        advertiseWithBumble(requestBuilder, false);
    }

    private void advertiseWithBumble(String serviceUuid, OwnAddressType addressType) {
        AdvertiseRequest.Builder requestBuilder =
                AdvertiseRequest.newBuilder().setOwnAddressType(addressType);
@@ -405,12 +460,11 @@ public class LeScanningTest {
            requestBuilder.setData(dataTypeBuilder.build());
        }

        advertiseWithBumble(requestBuilder);
        advertiseWithBumble(requestBuilder, true);
    }

    private void advertiseWithBumble(AdvertiseRequest.Builder requestBuilder) {
        // Bumble currently only supports legacy advertising.
        requestBuilder.setLegacy(true);
    private void advertiseWithBumble(AdvertiseRequest.Builder requestBuilder, boolean isLegacy) {
        requestBuilder.setLegacy(isLegacy);
        // Collect and ignore responses.
        StreamObserverSpliterator<AdvertiseResponse> responseObserver =
                new StreamObserverSpliterator<>();