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

Commit 67c01a4b authored by Sungsoo Lim's avatar Sungsoo Lim
Browse files

Revert "Service data and manufacturer data can be repeated fields."

This reverts commit 26dc9b99b17ca9d8ce3632c48e8b6c1450ee53e9.

Change-Id: I1846d0a6491c5b2ba5905411bd98f5d17909b705
parent 3f7a3906
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -6580,20 +6580,22 @@ package android.bluetooth.le {
    method public int describeContents();
    method public boolean getIncludeDeviceName();
    method public boolean getIncludeTxPowerLevel();
    method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
    method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData();
    method public int getManufacturerId();
    method public byte[] getManufacturerSpecificData();
    method public byte[] getServiceData();
    method public android.os.ParcelUuid getServiceDataUuid();
    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
    method public void writeToParcel(android.os.Parcel, int);
  }
  public static final class AdvertiseData.Builder {
    ctor public AdvertiseData.Builder();
    method public android.bluetooth.le.AdvertiseData.Builder addManufacturerData(int, byte[]);
    method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]);
    method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
    method public android.bluetooth.le.AdvertiseData build();
    method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
    method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean);
    method public android.bluetooth.le.AdvertiseData.Builder setManufacturerData(int, byte[]);
    method public android.bluetooth.le.AdvertiseData.Builder setServiceData(android.os.ParcelUuid, byte[]);
  }
  public final class AdvertiseSettings implements android.os.Parcelable {
@@ -6654,7 +6656,6 @@ package android.bluetooth.le {
    method public int getManufacturerId();
    method public byte[] getServiceData();
    method public byte[] getServiceDataMask();
    method public android.os.ParcelUuid getServiceDataUuid();
    method public android.os.ParcelUuid getServiceUuid();
    method public android.os.ParcelUuid getServiceUuidMask();
    method public boolean matches(android.bluetooth.le.ScanResult);
@@ -6678,10 +6679,10 @@ package android.bluetooth.le {
    method public int getAdvertiseFlags();
    method public byte[] getBytes();
    method public java.lang.String getDeviceName();
    method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
    method public byte[] getManufacturerSpecificData(int);
    method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData();
    method public byte[] getServiceData(android.os.ParcelUuid);
    method public int getManufacturerId();
    method public byte[] getManufacturerSpecificData();
    method public byte[] getServiceData();
    method public android.os.ParcelUuid getServiceDataUuid();
    method public java.util.List<android.os.ParcelUuid> getServiceUuids();
    method public int getTxPowerLevel();
  }
+91 −71
Original line number Diff line number Diff line
@@ -17,15 +17,14 @@
package android.bluetooth.le;

import android.annotation.Nullable;
import android.bluetooth.BluetoothUuid;
import android.os.Parcel;
import android.os.ParcelUuid;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
@@ -43,18 +42,27 @@ public final class AdvertiseData implements Parcelable {
    @Nullable
    private final List<ParcelUuid> mServiceUuids;

    private final SparseArray<byte[]> mManufacturerSpecificData;
    private final Map<ParcelUuid, byte[]> mServiceData;
    private final int mManufacturerId;
    @Nullable
    private final byte[] mManufacturerSpecificData;

    @Nullable
    private final ParcelUuid mServiceDataUuid;
    @Nullable
    private final byte[] mServiceData;

    private final boolean mIncludeTxPowerLevel;
    private final boolean mIncludeDeviceName;

    private AdvertiseData(List<ParcelUuid> serviceUuids,
            SparseArray<byte[]> manufacturerData,
            Map<ParcelUuid, byte[]> serviceData,
            boolean includeTxPowerLevel,
            ParcelUuid serviceDataUuid, byte[] serviceData,
            int manufacturerId,
            byte[] manufacturerSpecificData, boolean includeTxPowerLevel,
            boolean includeDeviceName) {
        mServiceUuids = serviceUuids;
        mManufacturerSpecificData = manufacturerData;
        mManufacturerId = manufacturerId;
        mManufacturerSpecificData = manufacturerSpecificData;
        mServiceDataUuid = serviceDataUuid;
        mServiceData = serviceData;
        mIncludeTxPowerLevel = includeTxPowerLevel;
        mIncludeDeviceName = includeDeviceName;
@@ -69,17 +77,32 @@ public final class AdvertiseData implements Parcelable {
    }

    /**
     * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The
     * manufacturer id is a non-negative number assigned by Bluetooth SIG.
     * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth
     * SIG.
     */
    public SparseArray<byte[]> getManufacturerSpecificData() {
    public int getManufacturerId() {
        return mManufacturerId;
    }

    /**
     * Returns the manufacturer specific data which is the content of manufacturer specific data
     * field. The first 2 bytes of the data contain the company id.
     */
    public byte[] getManufacturerSpecificData() {
        return mManufacturerSpecificData;
    }

    /**
     * Returns a map of 16-bit UUID and its corresponding service data.
     * Returns a 16-bit UUID of the service that the service data is associated with.
     */
    public Map<ParcelUuid, byte[]> getServiceData() {
    public ParcelUuid getServiceDataUuid() {
        return mServiceDataUuid;
    }

    /**
     * Returns service data.
     */
    public byte[] getServiceData() {
        return mServiceData;
    }

@@ -102,8 +125,8 @@ public final class AdvertiseData implements Parcelable {
     */
    @Override
    public int hashCode() {
        return Objects.hash(mServiceUuids, mManufacturerSpecificData, mServiceData,
                mIncludeDeviceName, mIncludeTxPowerLevel);
        return Objects.hash(mServiceUuids, mManufacturerId, mManufacturerSpecificData,
                mServiceDataUuid, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel);
    }

    /**
@@ -119,17 +142,20 @@ public final class AdvertiseData implements Parcelable {
        }
        AdvertiseData other = (AdvertiseData) obj;
        return Objects.equals(mServiceUuids, other.mServiceUuids) &&
                Utils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
                Utils.equals(mServiceData, other.mServiceData) &&
                mManufacturerId == other.mManufacturerId &&
                Objects.deepEquals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
                Objects.equals(mServiceDataUuid, other.mServiceDataUuid) &&
                Objects.deepEquals(mServiceData, other.mServiceData) &&
                        mIncludeDeviceName == other.mIncludeDeviceName &&
                        mIncludeTxPowerLevel == other.mIncludeTxPowerLevel;
    }

    @Override
    public String toString() {
        return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData="
                + Utils.toString(mManufacturerSpecificData) + ", mServiceData="
                + Utils.toString(mServiceData)
        return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerId="
                + mManufacturerId + ", mManufacturerSpecificData="
                + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid="
                + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData)
                + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
                + mIncludeDeviceName + "]";
    }
@@ -143,30 +169,21 @@ public final class AdvertiseData implements Parcelable {
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeList(mServiceUuids);

        // mManufacturerSpecificData could not be null.
        dest.writeInt(mManufacturerSpecificData.size());
        for (int i = 0; i < mManufacturerSpecificData.size(); ++i) {
            dest.writeInt(mManufacturerSpecificData.keyAt(i));
            byte[] data = mManufacturerSpecificData.valueAt(i);
            if (data == null) {
        dest.writeInt(mManufacturerId);
        if (mManufacturerSpecificData == null) {
            dest.writeInt(0);
        } else {
            dest.writeInt(1);
                dest.writeInt(data.length);
                dest.writeByteArray(data);
            }
            dest.writeInt(mManufacturerSpecificData.length);
            dest.writeByteArray(mManufacturerSpecificData);
        }
        dest.writeInt(mServiceData.size());
        for (ParcelUuid uuid : mServiceData.keySet()) {
            dest.writeParcelable(uuid, flags);
            byte[] data = mServiceData.get(uuid);
            if (data == null) {
        dest.writeParcelable(mServiceDataUuid, flags);
        if (mServiceData == null) {
            dest.writeInt(0);
        } else {
            dest.writeInt(1);
                dest.writeInt(data.length);
                dest.writeByteArray(data);
            }
            dest.writeInt(mServiceData.length);
            dest.writeByteArray(mServiceData);
        }
        dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0));
        dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0));
@@ -192,26 +209,20 @@ public final class AdvertiseData implements Parcelable {
                            builder.addServiceUuid(uuid);
                        }
                    }
                    int manufacturerSize = in.readInt();
                    for (int i = 0; i < manufacturerSize; ++i) {
                    int manufacturerId = in.readInt();
                    if (in.readInt() == 1) {
                        int manufacturerDataLength = in.readInt();
                        byte[] manufacturerData = new byte[manufacturerDataLength];
                        in.readByteArray(manufacturerData);
                            builder.addManufacturerData(manufacturerId, manufacturerData);
                        }
                        builder.setManufacturerData(manufacturerId, manufacturerData);
                    }
                    int serviceDataSize = in.readInt();
                    for (int i = 0; i < serviceDataSize; ++i) {
                    ParcelUuid serviceDataUuid = in.readParcelable(
                            ParcelUuid.class.getClassLoader());
                    if (in.readInt() == 1) {
                        int serviceDataLength = in.readInt();
                        byte[] serviceData = new byte[serviceDataLength];
                        in.readByteArray(serviceData);
                            builder.addServiceData(serviceDataUuid, serviceData);
                        }
                        builder.setServiceData(serviceDataUuid, serviceData);
                    }
                    builder.setIncludeTxPowerLevel(in.readByte() == 1);
                    builder.setIncludeDeviceName(in.readByte() == 1);
@@ -225,8 +236,13 @@ public final class AdvertiseData implements Parcelable {
    public static final class Builder {
        @Nullable
        private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
        private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>();
        private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>();
        private int mManufacturerId = -1;
        @Nullable
        private byte[] mManufacturerSpecificData;
        @Nullable
        private ParcelUuid mServiceDataUuid;
        @Nullable
        private byte[] mServiceData;
        private boolean mIncludeTxPowerLevel;
        private boolean mIncludeDeviceName;

@@ -252,17 +268,18 @@ public final class AdvertiseData implements Parcelable {
         * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is
         *             empty.
         */
        public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
        public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
            if (serviceDataUuid == null || serviceData == null) {
                throw new IllegalArgumentException(
                        "serviceDataUuid or serviceDataUuid is null");
            }
            mServiceData.put(serviceDataUuid, serviceData);
            mServiceDataUuid = serviceDataUuid;
            mServiceData = serviceData;
            return this;
        }

        /**
         * Add manufacturer specific data.
         * Set manufacturer specific data.
         * <p>
         * Please refer to the Bluetooth Assigned Numbers document provided by the <a
         * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company
@@ -273,7 +290,7 @@ public final class AdvertiseData implements Parcelable {
         * @throws IllegalArgumentException If the {@code manufacturerId} is negative or
         *             {@code manufacturerSpecificData} is null.
         */
        public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) {
        public Builder setManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) {
            if (manufacturerId < 0) {
                throw new IllegalArgumentException(
                        "invalid manufacturerId - " + manufacturerId);
@@ -281,7 +298,8 @@ public final class AdvertiseData implements Parcelable {
            if (manufacturerSpecificData == null) {
                throw new IllegalArgumentException("manufacturerSpecificData is null");
            }
            mManufacturerSpecificData.put(manufacturerId, manufacturerSpecificData);
            mManufacturerId = manufacturerId;
            mManufacturerSpecificData = manufacturerSpecificData;
            return this;
        }

@@ -306,7 +324,9 @@ public final class AdvertiseData implements Parcelable {
         * Build the {@link AdvertiseData}.
         */
        public AdvertiseData build() {
            return new AdvertiseData(mServiceUuids, mManufacturerSpecificData, mServiceData,
            return new AdvertiseData(mServiceUuids,
                    mServiceDataUuid,
                    mServiceData, mManufacturerId, mManufacturerSpecificData,
                    mIncludeTxPowerLevel, mIncludeDeviceName);
        }
    }
+4 −4
Original line number Diff line number Diff line
@@ -209,13 +209,13 @@ public final class BluetoothLeAdvertiser {
                        num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
            }
        }
        for (ParcelUuid uuid : data.getServiceData().keySet()) {
        if (data.getServiceDataUuid() != null) {
            size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH
                    + byteLength(data.getServiceData().get(uuid));
                    + byteLength(data.getServiceData());
        }
        for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) {
        if (data.getManufacturerId() > 0) {
            size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH +
                    byteLength(data.getManufacturerSpecificData().valueAt(i));
                    byteLength(data.getManufacturerSpecificData());
        }
        if (data.getIncludeTxPowerLevel()) {
            size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte.
+12 −7
Original line number Diff line number Diff line
@@ -242,6 +242,9 @@ public final class ScanFilter implements Parcelable {
        return mServiceDataMask;
    }

    /**
     * @hide
     */
    @Nullable
    public ParcelUuid getServiceDataUuid() {
        return mServiceDataUuid;
@@ -300,17 +303,19 @@ public final class ScanFilter implements Parcelable {
        }

        // Service data match
        if (mServiceDataUuid != null) {
            if (!matchesPartialData(mServiceData, mServiceDataMask,
                    scanRecord.getServiceData(mServiceDataUuid))) {
        if (mServiceData != null) {
            if (!Objects.equals(mServiceDataUuid, scanRecord.getServiceDataUuid()) ||
                    !matchesPartialData(mServiceData, mServiceDataMask,
                            scanRecord.getServiceData())) {
                return false;
            }
        }

        // Manufacturer data match.
        if (mManufacturerId >= 0) {
            if (!matchesPartialData(mManufacturerData, mManufacturerDataMask,
                    scanRecord.getManufacturerSpecificData(mManufacturerId))) {
        if (mManufacturerData != null) {
            if (mManufacturerId != scanRecord.getManufacturerId() ||
                    !matchesPartialData(mManufacturerData,
                            mManufacturerDataMask, scanRecord.getManufacturerSpecificData())) {
                return false;
            }
        }
+44 −45
Original line number Diff line number Diff line
@@ -19,14 +19,11 @@ package android.bluetooth.le;
import android.annotation.Nullable;
import android.bluetooth.BluetoothUuid;
import android.os.ParcelUuid;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * Represents a scan record from Bluetooth LE scan.
@@ -56,9 +53,14 @@ public final class ScanRecord {
    @Nullable
    private final List<ParcelUuid> mServiceUuids;

    private final SparseArray<byte[]> mManufacturerSpecificData;
    private final int mManufacturerId;
    @Nullable
    private final byte[] mManufacturerSpecificData;

    private final Map<ParcelUuid, byte[]> mServiceData;
    @Nullable
    private final ParcelUuid mServiceDataUuid;
    @Nullable
    private final byte[] mServiceData;

    // Transmission power level(in dB).
    private final int mTxPowerLevel;
@@ -79,46 +81,40 @@ public final class ScanRecord {

    /**
     * Returns a list of service UUIDs within the advertisement that are used to identify the
     * bluetooth GATT services.
     * bluetooth gatt services.
     */
    public List<ParcelUuid> getServiceUuids() {
        return mServiceUuids;
    }

    /**
     * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific
     * data.
     * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth
     * SIG.
     */
    public SparseArray<byte[]> getManufacturerSpecificData() {
        return mManufacturerSpecificData;
    public int getManufacturerId() {
        return mManufacturerId;
    }

    /**
     * Returns the manufacturer specific data associated with the manufacturer id. Returns
     * {@code null} if the {@code manufacturerId} is not found.
     * Returns the manufacturer specific data which is the content of manufacturer specific data
     * field.
     */
    @Nullable
    public byte[] getManufacturerSpecificData(int manufacturerId) {
        return mManufacturerSpecificData.get(manufacturerId);
    public byte[] getManufacturerSpecificData() {
        return mManufacturerSpecificData;
    }

    /**
     * Returns a map of service UUID and its corresponding service data.
     * Returns a 16-bit UUID of the service that the service data is associated with.
     */
    public Map<ParcelUuid, byte[]> getServiceData() {
        return mServiceData;
    public ParcelUuid getServiceDataUuid() {
        return mServiceDataUuid;
    }

    /**
     * Returns the service data byte array associated with the {@code serviceUuid}. Returns
     * {@code null} if the {@code serviceDataUuid} is not found.
     * Returns service data.
     */
    @Nullable
    public byte[] getServiceData(ParcelUuid serviceDataUuid) {
        if (serviceDataUuid == null) {
            return null;
        }
        return mServiceData.get(serviceDataUuid);
    public byte[] getServiceData() {
        return mServiceData;
    }

    /**
@@ -148,12 +144,14 @@ public final class ScanRecord {
    }

    private ScanRecord(List<ParcelUuid> serviceUuids,
            SparseArray<byte[]> manufacturerData,
            Map<ParcelUuid, byte[]> serviceData,
            int advertiseFlags, int txPowerLevel,
            ParcelUuid serviceDataUuid, byte[] serviceData,
            int manufacturerId,
            byte[] manufacturerSpecificData, int advertiseFlags, int txPowerLevel,
            String localName, byte[] bytes) {
        mServiceUuids = serviceUuids;
        mManufacturerSpecificData = manufacturerData;
        mManufacturerId = manufacturerId;
        mManufacturerSpecificData = manufacturerSpecificData;
        mServiceDataUuid = serviceDataUuid;
        mServiceData = serviceData;
        mDeviceName = localName;
        mAdvertiseFlags = advertiseFlags;
@@ -170,6 +168,7 @@ public final class ScanRecord {
     * order.
     *
     * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response.
     *
     * @hide
     */
    public static ScanRecord parseFromBytes(byte[] scanRecord) {
@@ -182,9 +181,10 @@ public final class ScanRecord {
        List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
        String localName = null;
        int txPowerLevel = Integer.MIN_VALUE;

        SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>();
        Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>();
        ParcelUuid serviceDataUuid = null;
        byte[] serviceData = null;
        int manufacturerId = -1;
        byte[] manufacturerSpecificData = null;

        try {
            while (currentPos < scanRecord.length) {
@@ -230,20 +230,16 @@ public final class ScanRecord {
                        int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
                        byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
                                serviceUuidLength);
                        ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
                                serviceDataUuidBytes);
                        byte[] serviceDataArray = extractBytes(scanRecord,
                                currentPos + serviceUuidLength, dataLength - serviceUuidLength);
                        serviceData.put(serviceDataUuid, serviceDataArray);
                        serviceDataUuid = BluetoothUuid.parseUuidFrom(serviceDataUuidBytes);
                        serviceData = extractBytes(scanRecord, currentPos + 2, dataLength - 2);
                        break;
                    case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
                        // The first two bytes of the manufacturer specific data are
                        // manufacturer ids in little endian.
                        int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) +
                        manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) +
                                (scanRecord[currentPos] & 0xFF);
                        byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
                        manufacturerSpecificData = extractBytes(scanRecord, currentPos + 2,
                                dataLength - 2);
                        manufacturerData.put(manufacturerId, manufacturerDataBytes);
                        break;
                    default:
                        // Just ignore, we don't handle such data type.
@@ -255,8 +251,9 @@ public final class ScanRecord {
            if (serviceUuids.isEmpty()) {
                serviceUuids = null;
            }
            return new ScanRecord(serviceUuids, manufacturerData, serviceData,
                    advertiseFlag, txPowerLevel, localName, scanRecord);
            return new ScanRecord(serviceUuids, serviceDataUuid, serviceData,
                    manufacturerId, manufacturerSpecificData, advertiseFlag, txPowerLevel,
                    localName, scanRecord);
        } catch (IndexOutOfBoundsException e) {
            Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
            return null;
@@ -266,11 +263,13 @@ public final class ScanRecord {
    @Override
    public String toString() {
        return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids
                + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData)
                + ", mServiceData=" + Utils.toString(mServiceData)
                + ", mManufacturerId=" + mManufacturerId + ", mManufacturerSpecificData="
                + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid="
                + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData)
                + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]";
    }


    // Parse service UUIDs.
    private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength,
            int uuidLength, List<ParcelUuid> serviceUuids) {
Loading