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

Commit aaa7dcbe authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12135134 from 399e9bdc to 24Q4-release

Change-Id: I0b967a2f4f6cb66475595baeb77743763de163a6
parents bf0adfbf 399e9bdc
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -519,10 +519,16 @@ public class HidHostService extends ProfileService {

    private void handleMessageOnVirtualUnplug(Message msg) {
        BluetoothDevice device = mAdapterService.getDeviceFromByte((byte[]) msg.obj);
        if (Flags.removeInputDeviceOnVup()) {
            updateConnectionState(
                    device, getTransport(device), BluetoothProfile.STATE_DISCONNECTED);
            mInputDevices.remove(device);
        } else {
            int transport = msg.arg1;
            if (!checkTransport(device, transport, msg.what)) {
                return;
            }
        }
        int status = msg.arg2;
        broadcastVirtualUnplugStatus(device, status);
    }
+11 −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 = concatenate(serviceDataUuid, serviceData);
            serviceDataMask = concatenate(serviceDataUuid, serviceDataMask);
            serviceData = concatenate(serviceDataUuid, serviceData, false);
            serviceDataMask = concatenate(serviceDataUuid, serviceDataMask, true);
            if (serviceData != null && serviceDataMask != null) {
                addServiceData(serviceData, serviceDataMask);
            }
@@ -293,19 +293,23 @@ import java.util.UUID;
        }
    }

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

        int dataLen = uuid.length + (serviceData == null ? 0 : serviceData.length);
        int dataLen = uuid.length + serviceData.length;
        // If data is too long, don't add it to hardware scan filter.
        if (dataLen > MAX_LEN_PER_FIELD) {
            return null;
        }
        byte[] concatenated = new byte[dataLen];
        if (isMask) {
            // For the UUID portion of the mask fill it with 0xFF to indicate that all bits of the
            // UUID need to match the service data filter.
            Arrays.fill(concatenated, 0, uuid.length, (byte) 0xFF);
        } else {
            System.arraycopy(uuid, 0, concatenated, 0, uuid.length);
        if (serviceData != null) {
            System.arraycopy(serviceData, 0, concatenated, uuid.length, serviceData.length);
        }
        System.arraycopy(serviceData, 0, concatenated, uuid.length, serviceData.length);
        return concatenated;
    }
}
+27 −13
Original line number Diff line number Diff line
@@ -396,6 +396,12 @@ public class AdapterServiceTest {
        }
    }

    private List<ProfileService> listOfMockServices() {
        return Flags.scanManagerRefactor()
                ? List.of(mMockGattService, mMockService, mMockService2)
                : List.of(mMockService, mMockService2);
    }

    static void offToBleOn(
            TestLooper looper,
            ProfileService gattService,
@@ -412,7 +418,6 @@ public class AdapterServiceTest {

        if (!Flags.scanManagerRefactor()) {
            TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_REGISTERED);

            TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
        }

@@ -435,8 +440,8 @@ public class AdapterServiceTest {
        verifyStateChange(callback, STATE_ON, STATE_TURNING_OFF);

        if (!onlyGatt) {
            // Stop PBAP and PAN services
            assertThat(adapter.mSetProfileServiceStateCounter).isEqualTo(4);
            // Stop (if Flags.scanManagerRefactor GATT), PBAP, and PAN services
            assertThat(adapter.mSetProfileServiceStateCounter).isEqualTo(services.size() * 2);

            for (ProfileService service : services) {
                adapter.onProfileServiceStateChanged(service, STATE_OFF);
@@ -457,7 +462,7 @@ public class AdapterServiceTest {
                mAdapterService,
                mMockContext,
                onlyGatt,
                List.of(mMockService, mMockService2),
                listOfMockServices(),
                mNativeInterface);
    }

@@ -486,8 +491,8 @@ public class AdapterServiceTest {
        verifyStateChange(callback, STATE_BLE_ON, STATE_TURNING_ON);

        if (!onlyGatt) {
            // Start Mock PBAP and PAN services
            assertThat(adapter.mSetProfileServiceStateCounter).isEqualTo(2);
            // Start Mock (if Flags.scanManagerRefactor GATT), PBAP, and PAN services
            assertThat(adapter.mSetProfileServiceStateCounter).isEqualTo(services.size());

            for (ProfileService service : services) {
                adapter.addProfile(service);
@@ -514,7 +519,7 @@ public class AdapterServiceTest {
                mAdapterService,
                mMockContext,
                onlyGatt,
                List.of(mMockService, mMockService2),
                listOfMockServices(),
                mNativeInterface);
    }

@@ -539,8 +544,10 @@ public class AdapterServiceTest {
        TestUtils.syncHandler(looper, AdapterState.BLE_TURN_OFF);
        verifyStateChange(callback, STATE_BLE_ON, STATE_BLE_TURNING_OFF);

        if (!Flags.scanManagerRefactor()) {
            TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
            TestUtils.syncHandler(looper, MESSAGE_PROFILE_SERVICE_UNREGISTERED);
        }

        verify(nativeInterface).disable();
        adapter.stateChangeCallback(AbstractionLayer.BT_STATE_OFF);
@@ -589,6 +596,7 @@ public class AdapterServiceTest {
     * started and stopped.
     */
    @Test
    @DisableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR)
    public void testEnableDisableOnlyGatt() {
        Context mockContext = mock(Context.class);
        Resources mockResources = mock(Resources.class);
@@ -611,6 +619,7 @@ public class AdapterServiceTest {

    /** Test: Don't start GATT Check whether the AdapterService quits gracefully */
    @Test
    @DisableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR)
    public void testGattStartTimeout() {
        assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF);

@@ -646,6 +655,7 @@ public class AdapterServiceTest {

    /** Test: Don't stop GATT Check whether the AdapterService quits gracefully */
    @Test
    @DisableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR)
    public void testGattStopTimeout() {
        doEnable(false);

@@ -655,7 +665,7 @@ public class AdapterServiceTest {
                mMockContext,
                mIBluetoothCallback,
                false,
                List.of(mMockService, mMockService2));
                listOfMockServices());

        mAdapterService.stopBle();
        syncHandler(AdapterState.BLE_TURN_OFF);
@@ -813,6 +823,7 @@ public class AdapterServiceTest {

    /** Test: Don't start a classic profile Check whether the AdapterService quits gracefully */
    @Test
    @DisableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR)
    public void testProfileStartTimeout() {
        assertThat(mAdapterService.getState()).isEqualTo(STATE_OFF);

@@ -855,6 +866,7 @@ public class AdapterServiceTest {

    /** Test: Don't stop a classic profile Check whether the AdapterService quits gracefully */
    @Test
    @DisableFlags(Flags.FLAG_SCAN_MANAGER_REFACTOR)
    public void testProfileStopTimeout() {
        doEnable(false);

@@ -911,14 +923,16 @@ public class AdapterServiceTest {
                mMockContext,
                mIBluetoothCallback,
                false,
                List.of(mMockService, mMockService2));
                listOfMockServices());

        // Do not call stopBle().  The Adapter should turn itself off.
        syncHandler(AdapterState.BLE_TURN_OFF);
        verifyStateChange(STATE_BLE_ON, STATE_BLE_TURNING_OFF, CONTEXT_SWITCH_MS);

        if (!Flags.scanManagerRefactor()) {
            syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); // stop GATT
            syncHandler(MESSAGE_PROFILE_SERVICE_UNREGISTERED);
        }

        verify(mNativeInterface).disable();

+104 −0
Original line number Diff line number Diff line
@@ -18,12 +18,15 @@ package com.android.bluetooth.le_scan;

import static com.google.common.truth.Truth.assertThat;

import android.bluetooth.BluetoothUuid;
import android.bluetooth.le.ScanFilter;
import android.os.ParcelUuid;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.google.common.primitives.Bytes;

import org.junit.Test;
import org.junit.runner.RunWith;

@@ -33,6 +36,14 @@ import java.util.UUID;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class ScanFilterQueueTest {
    private static final String TEST_UUID_STRING = "00001805-0000-1000-8000-00805f9b34fb";
    private static final String UNMATCHED_UUID_STRING = "00001815-0000-1000-8000-00805f9b34fb";
    private static final byte[] TEST_SERVICE_DATA = new byte[] {(byte) 0x18, (byte) 0x0F};
    private static final byte[] PARTIALLY_MATCHED_SERVICE_DATA =
            new byte[] {(byte) 0x08, (byte) 0x0F, (byte) 0xAB, (byte) 0xCD};
    private static final byte[] UNMATCHED_SERVICE_DATA = new byte[] {(byte) 0x08, (byte) 0x0E};
    private static final byte[] PARTIAL_SERVICE_DATA_MASK = new byte[] {(byte) 0x00, (byte) 0xFF};
    private static final byte[] FULL_SERVICE_DATA_MASK = new byte[] {(byte) 0xFF, (byte) 0xFF};

    @Test
    public void scanFilterQueueParams() {
@@ -195,4 +206,97 @@ public class ScanFilterQueueTest {
        int numOfEntries = 7;
        assertThat(queue.toArray().length).isEqualTo(numOfEntries);
    }

    @Test
    public void serviceDataFilterNoMask1() {
        ScanFilter filter =
                new ScanFilter.Builder()
                        .setServiceData(ParcelUuid.fromString(TEST_UUID_STRING), TEST_SERVICE_DATA)
                        .build();
        testServiceDataFilter(filter, false);
    }

    @Test
    public void serviceDataFilterWithFullMask() {
        ScanFilter filter =
                new ScanFilter.Builder()
                        .setServiceData(
                                ParcelUuid.fromString(TEST_UUID_STRING),
                                TEST_SERVICE_DATA,
                                FULL_SERVICE_DATA_MASK)
                        .build();
        testServiceDataFilter(filter, false);
    }

    @Test
    public void serviceDataFilterWithPartialMask() {
        ScanFilter filter =
                new ScanFilter.Builder()
                        .setServiceData(
                                ParcelUuid.fromString(TEST_UUID_STRING),
                                TEST_SERVICE_DATA,
                                PARTIAL_SERVICE_DATA_MASK)
                        .build();
        testServiceDataFilter(filter, true);
    }

    private void testServiceDataFilter(ScanFilter filter, boolean partialServiceDataMatchResult) {
        ScanFilterQueue queue = new ScanFilterQueue();
        queue.addScanFilter(filter);
        ScanFilterQueue.Entry entry = queue.pop();
        assertThat(entry.type).isEqualTo(ScanFilterQueue.TYPE_SERVICE_DATA);
        assertThat(entry.data)
                .isEqualTo(
                        Bytes.concat(
                                BluetoothUuid.uuidToBytes(ParcelUuid.fromString(TEST_UUID_STRING)),
                                TEST_SERVICE_DATA));
        assertThat(
                        serviceDataMatches(
                                entry.data,
                                Bytes.concat(
                                        BluetoothUuid.uuidToBytes(
                                                ParcelUuid.fromString(TEST_UUID_STRING)),
                                        TEST_SERVICE_DATA),
                                entry.data_mask))
                .isTrue();
        assertThat(
                        serviceDataMatches(
                                entry.data,
                                Bytes.concat(
                                        BluetoothUuid.uuidToBytes(
                                                ParcelUuid.fromString(UNMATCHED_UUID_STRING)),
                                        TEST_SERVICE_DATA),
                                entry.data_mask))
                .isFalse();
        assertThat(
                        serviceDataMatches(
                                entry.data,
                                Bytes.concat(
                                        BluetoothUuid.uuidToBytes(
                                                ParcelUuid.fromString(TEST_UUID_STRING)),
                                        UNMATCHED_SERVICE_DATA),
                                entry.data_mask))
                .isFalse();
        assertThat(
                        serviceDataMatches(
                                entry.data,
                                Bytes.concat(
                                        BluetoothUuid.uuidToBytes(
                                                ParcelUuid.fromString(TEST_UUID_STRING)),
                                        PARTIALLY_MATCHED_SERVICE_DATA),
                                entry.data_mask))
                .isEqualTo(partialServiceDataMatchResult);
    }

    private boolean serviceDataMatches(byte[] filterData, byte[] resultData, byte[] mask) {
        if (filterData.length > resultData.length || filterData.length != mask.length) {
            return false;
        }
        for (int i = 0; i < filterData.length; i++) {
            if ((filterData[i] & mask[i]) != (resultData[i] & mask[i])) {
                return false;
            }
        }
        return true;
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -94,3 +94,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "name_discovery_for_le_pairing"
    namespace: "bluetooth"
    description: "Perform LE name discovery for pairing if device name is not known"
    bug: "355095011"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
Loading