Loading api/current.txt +9 −10 Original line number Original line Diff line number Diff line Loading @@ -6582,22 +6582,20 @@ package android.bluetooth.le { method public int describeContents(); method public int describeContents(); method public boolean getIncludeDeviceName(); method public boolean getIncludeDeviceName(); method public boolean getIncludeTxPowerLevel(); method public boolean getIncludeTxPowerLevel(); method public int getManufacturerId(); method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); method public byte[] getManufacturerSpecificData(); method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData(); method public byte[] getServiceData(); method public android.os.ParcelUuid getServiceDataUuid(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int); } } public static final class AdvertiseData.Builder { public static final class AdvertiseData.Builder { ctor public 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.Builder addServiceUuid(android.os.ParcelUuid); method public android.bluetooth.le.AdvertiseData build(); method public android.bluetooth.le.AdvertiseData build(); method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean); 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 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 { public final class AdvertiseSettings implements android.os.Parcelable { Loading Loading @@ -6658,6 +6656,7 @@ package android.bluetooth.le { method public int getManufacturerId(); method public int getManufacturerId(); method public byte[] getServiceData(); method public byte[] getServiceData(); method public byte[] getServiceDataMask(); method public byte[] getServiceDataMask(); method public android.os.ParcelUuid getServiceDataUuid(); method public android.os.ParcelUuid getServiceUuid(); method public android.os.ParcelUuid getServiceUuid(); method public android.os.ParcelUuid getServiceUuidMask(); method public android.os.ParcelUuid getServiceUuidMask(); method public boolean matches(android.bluetooth.le.ScanResult); method public boolean matches(android.bluetooth.le.ScanResult); Loading @@ -6681,10 +6680,10 @@ package android.bluetooth.le { method public int getAdvertiseFlags(); method public int getAdvertiseFlags(); method public byte[] getBytes(); method public byte[] getBytes(); method public java.lang.String getDeviceName(); method public java.lang.String getDeviceName(); method public int getManufacturerId(); method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); method public byte[] getManufacturerSpecificData(); method public byte[] getManufacturerSpecificData(int); method public byte[] getServiceData(); method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData(); method public android.os.ParcelUuid getServiceDataUuid(); method public byte[] getServiceData(android.os.ParcelUuid); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public int getTxPowerLevel(); method public int getTxPowerLevel(); } } core/java/android/bluetooth/le/AdvertiseData.java +71 −91 Original line number Original line Diff line number Diff line Loading @@ -17,14 +17,15 @@ package android.bluetooth.le; package android.bluetooth.le; import android.annotation.Nullable; import android.annotation.Nullable; import android.bluetooth.BluetoothUuid; import android.os.Parcel; import android.os.Parcel; import android.os.ParcelUuid; import android.os.ParcelUuid; import android.os.Parcelable; import android.os.Parcelable; import android.util.ArrayMap; import android.util.SparseArray; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Objects; /** /** Loading @@ -42,27 +43,18 @@ public final class AdvertiseData implements Parcelable { @Nullable @Nullable private final List<ParcelUuid> mServiceUuids; private final List<ParcelUuid> mServiceUuids; private final int mManufacturerId; private final SparseArray<byte[]> mManufacturerSpecificData; @Nullable private final Map<ParcelUuid, byte[]> mServiceData; private final byte[] mManufacturerSpecificData; @Nullable private final ParcelUuid mServiceDataUuid; @Nullable private final byte[] mServiceData; private final boolean mIncludeTxPowerLevel; private final boolean mIncludeTxPowerLevel; private final boolean mIncludeDeviceName; private final boolean mIncludeDeviceName; private AdvertiseData(List<ParcelUuid> serviceUuids, private AdvertiseData(List<ParcelUuid> serviceUuids, ParcelUuid serviceDataUuid, byte[] serviceData, SparseArray<byte[]> manufacturerData, int manufacturerId, Map<ParcelUuid, byte[]> serviceData, byte[] manufacturerSpecificData, boolean includeTxPowerLevel, boolean includeTxPowerLevel, boolean includeDeviceName) { boolean includeDeviceName) { mServiceUuids = serviceUuids; mServiceUuids = serviceUuids; mManufacturerId = manufacturerId; mManufacturerSpecificData = manufacturerData; mManufacturerSpecificData = manufacturerSpecificData; mServiceDataUuid = serviceDataUuid; mServiceData = serviceData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; mIncludeTxPowerLevel = includeTxPowerLevel; mIncludeDeviceName = includeDeviceName; mIncludeDeviceName = includeDeviceName; Loading @@ -77,32 +69,17 @@ public final class AdvertiseData implements Parcelable { } } /** /** * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The * SIG. * manufacturer id is a non-negative number assigned by Bluetooth SIG. */ */ public int getManufacturerId() { public SparseArray<byte[]> getManufacturerSpecificData() { 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; return mManufacturerSpecificData; } } /** /** * Returns a 16-bit UUID of the service that the service data is associated with. * Returns a map of 16-bit UUID and its corresponding service data. */ */ public ParcelUuid getServiceDataUuid() { public Map<ParcelUuid, byte[]> getServiceData() { return mServiceDataUuid; } /** * Returns service data. */ public byte[] getServiceData() { return mServiceData; return mServiceData; } } Loading @@ -125,8 +102,8 @@ public final class AdvertiseData implements Parcelable { */ */ @Override @Override public int hashCode() { public int hashCode() { return Objects.hash(mServiceUuids, mManufacturerId, mManufacturerSpecificData, return Objects.hash(mServiceUuids, mManufacturerSpecificData, mServiceData, mServiceDataUuid, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); mIncludeDeviceName, mIncludeTxPowerLevel); } } /** /** Loading @@ -142,20 +119,17 @@ public final class AdvertiseData implements Parcelable { } } AdvertiseData other = (AdvertiseData) obj; AdvertiseData other = (AdvertiseData) obj; return Objects.equals(mServiceUuids, other.mServiceUuids) && return Objects.equals(mServiceUuids, other.mServiceUuids) && mManufacturerId == other.mManufacturerId && Utils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && Objects.deepEquals(mManufacturerSpecificData, other.mManufacturerSpecificData) && Utils.equals(mServiceData, other.mServiceData) && Objects.equals(mServiceDataUuid, other.mServiceDataUuid) && Objects.deepEquals(mServiceData, other.mServiceData) && mIncludeDeviceName == other.mIncludeDeviceName && mIncludeDeviceName == other.mIncludeDeviceName && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; } } @Override @Override public String toString() { public String toString() { return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerId=" return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData=" + mManufacturerId + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData) + ", mServiceData=" + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid=" + Utils.toString(mServiceData) + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" + mIncludeDeviceName + "]"; + mIncludeDeviceName + "]"; } } Loading @@ -169,21 +143,30 @@ public final class AdvertiseData implements Parcelable { public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) { dest.writeList(mServiceUuids); dest.writeList(mServiceUuids); dest.writeInt(mManufacturerId); // mManufacturerSpecificData could not be null. if (mManufacturerSpecificData == 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(0); dest.writeInt(0); } else { } else { dest.writeInt(1); dest.writeInt(1); dest.writeInt(mManufacturerSpecificData.length); dest.writeInt(data.length); dest.writeByteArray(mManufacturerSpecificData); dest.writeByteArray(data); } } } dest.writeParcelable(mServiceDataUuid, flags); dest.writeInt(mServiceData.size()); if (mServiceData == null) { for (ParcelUuid uuid : mServiceData.keySet()) { dest.writeParcelable(uuid, flags); byte[] data = mServiceData.get(uuid); if (data == null) { dest.writeInt(0); dest.writeInt(0); } else { } else { dest.writeInt(1); dest.writeInt(1); dest.writeInt(mServiceData.length); dest.writeInt(data.length); dest.writeByteArray(mServiceData); dest.writeByteArray(data); } } } dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); Loading @@ -209,20 +192,26 @@ public final class AdvertiseData implements Parcelable { builder.addServiceUuid(uuid); builder.addServiceUuid(uuid); } } } } int manufacturerSize = in.readInt(); for (int i = 0; i < manufacturerSize; ++i) { int manufacturerId = in.readInt(); int manufacturerId = in.readInt(); if (in.readInt() == 1) { if (in.readInt() == 1) { int manufacturerDataLength = in.readInt(); int manufacturerDataLength = in.readInt(); byte[] manufacturerData = new byte[manufacturerDataLength]; byte[] manufacturerData = new byte[manufacturerDataLength]; in.readByteArray(manufacturerData); in.readByteArray(manufacturerData); builder.setManufacturerData(manufacturerId, manufacturerData); builder.addManufacturerData(manufacturerId, manufacturerData); } } } int serviceDataSize = in.readInt(); for (int i = 0; i < serviceDataSize; ++i) { ParcelUuid serviceDataUuid = in.readParcelable( ParcelUuid serviceDataUuid = in.readParcelable( ParcelUuid.class.getClassLoader()); ParcelUuid.class.getClassLoader()); if (in.readInt() == 1) { if (in.readInt() == 1) { int serviceDataLength = in.readInt(); int serviceDataLength = in.readInt(); byte[] serviceData = new byte[serviceDataLength]; byte[] serviceData = new byte[serviceDataLength]; in.readByteArray(serviceData); in.readByteArray(serviceData); builder.setServiceData(serviceDataUuid, serviceData); builder.addServiceData(serviceDataUuid, serviceData); } } } builder.setIncludeTxPowerLevel(in.readByte() == 1); builder.setIncludeTxPowerLevel(in.readByte() == 1); builder.setIncludeDeviceName(in.readByte() == 1); builder.setIncludeDeviceName(in.readByte() == 1); Loading @@ -236,13 +225,8 @@ public final class AdvertiseData implements Parcelable { public static final class Builder { public static final class Builder { @Nullable @Nullable private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); private int mManufacturerId = -1; private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>(); @Nullable private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private byte[] mManufacturerSpecificData; @Nullable private ParcelUuid mServiceDataUuid; @Nullable private byte[] mServiceData; private boolean mIncludeTxPowerLevel; private boolean mIncludeTxPowerLevel; private boolean mIncludeDeviceName; private boolean mIncludeDeviceName; Loading @@ -268,18 +252,17 @@ public final class AdvertiseData implements Parcelable { * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is * empty. * empty. */ */ public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) { public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) { if (serviceDataUuid == null || serviceData == null) { if (serviceDataUuid == null || serviceData == null) { throw new IllegalArgumentException( throw new IllegalArgumentException( "serviceDataUuid or serviceDataUuid is null"); "serviceDataUuid or serviceDataUuid is null"); } } mServiceDataUuid = serviceDataUuid; mServiceData.put(serviceDataUuid, serviceData); mServiceData = serviceData; return this; return this; } } /** /** * Set manufacturer specific data. * Add manufacturer specific data. * <p> * <p> * Please refer to the Bluetooth Assigned Numbers document provided by the <a * 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 * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company Loading @@ -290,7 +273,7 @@ public final class AdvertiseData implements Parcelable { * @throws IllegalArgumentException If the {@code manufacturerId} is negative or * @throws IllegalArgumentException If the {@code manufacturerId} is negative or * {@code manufacturerSpecificData} is null. * {@code manufacturerSpecificData} is null. */ */ public Builder setManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) { public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) { if (manufacturerId < 0) { if (manufacturerId < 0) { throw new IllegalArgumentException( throw new IllegalArgumentException( "invalid manufacturerId - " + manufacturerId); "invalid manufacturerId - " + manufacturerId); Loading @@ -298,8 +281,7 @@ public final class AdvertiseData implements Parcelable { if (manufacturerSpecificData == null) { if (manufacturerSpecificData == null) { throw new IllegalArgumentException("manufacturerSpecificData is null"); throw new IllegalArgumentException("manufacturerSpecificData is null"); } } mManufacturerId = manufacturerId; mManufacturerSpecificData.put(manufacturerId, manufacturerSpecificData); mManufacturerSpecificData = manufacturerSpecificData; return this; return this; } } Loading @@ -324,9 +306,7 @@ public final class AdvertiseData implements Parcelable { * Build the {@link AdvertiseData}. * Build the {@link AdvertiseData}. */ */ public AdvertiseData build() { public AdvertiseData build() { return new AdvertiseData(mServiceUuids, return new AdvertiseData(mServiceUuids, mManufacturerSpecificData, mServiceData, mServiceDataUuid, mServiceData, mManufacturerId, mManufacturerSpecificData, mIncludeTxPowerLevel, mIncludeDeviceName); mIncludeTxPowerLevel, mIncludeDeviceName); } } } } Loading core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -209,13 +209,13 @@ public final class BluetoothLeAdvertiser { num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; } } } } if (data.getServiceDataUuid() != null) { for (ParcelUuid uuid : data.getServiceData().keySet()) { size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH + byteLength(data.getServiceData()); + byteLength(data.getServiceData().get(uuid)); } } if (data.getManufacturerId() > 0) { for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) { size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + byteLength(data.getManufacturerSpecificData()); byteLength(data.getManufacturerSpecificData().valueAt(i)); } } if (data.getIncludeTxPowerLevel()) { if (data.getIncludeTxPowerLevel()) { size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte. size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte. Loading core/java/android/bluetooth/le/ScanFilter.java +7 −12 Original line number Original line Diff line number Diff line Loading @@ -242,9 +242,6 @@ public final class ScanFilter implements Parcelable { return mServiceDataMask; return mServiceDataMask; } } /** * @hide */ @Nullable @Nullable public ParcelUuid getServiceDataUuid() { public ParcelUuid getServiceDataUuid() { return mServiceDataUuid; return mServiceDataUuid; Loading Loading @@ -303,19 +300,17 @@ public final class ScanFilter implements Parcelable { } } // Service data match // Service data match if (mServiceData != null) { if (mServiceDataUuid != null) { if (!Objects.equals(mServiceDataUuid, scanRecord.getServiceDataUuid()) || if (!matchesPartialData(mServiceData, mServiceDataMask, !matchesPartialData(mServiceData, mServiceDataMask, scanRecord.getServiceData(mServiceDataUuid))) { scanRecord.getServiceData())) { return false; return false; } } } } // Manufacturer data match. // Manufacturer data match. if (mManufacturerData != null) { if (mManufacturerId >= 0) { if (mManufacturerId != scanRecord.getManufacturerId() || if (!matchesPartialData(mManufacturerData, mManufacturerDataMask, !matchesPartialData(mManufacturerData, scanRecord.getManufacturerSpecificData(mManufacturerId))) { mManufacturerDataMask, scanRecord.getManufacturerSpecificData())) { return false; return false; } } } } Loading core/java/android/bluetooth/le/ScanRecord.java +45 −44 Original line number Original line Diff line number Diff line Loading @@ -19,11 +19,14 @@ package android.bluetooth.le; import android.annotation.Nullable; import android.annotation.Nullable; import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid; import android.os.ParcelUuid; import android.os.ParcelUuid; import android.util.ArrayMap; import android.util.Log; import android.util.Log; import android.util.SparseArray; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.List; import java.util.List; import java.util.Map; /** /** * Represents a scan record from Bluetooth LE scan. * Represents a scan record from Bluetooth LE scan. Loading Loading @@ -53,14 +56,9 @@ public final class ScanRecord { @Nullable @Nullable private final List<ParcelUuid> mServiceUuids; private final List<ParcelUuid> mServiceUuids; private final int mManufacturerId; private final SparseArray<byte[]> mManufacturerSpecificData; @Nullable private final byte[] mManufacturerSpecificData; @Nullable private final Map<ParcelUuid, byte[]> mServiceData; private final ParcelUuid mServiceDataUuid; @Nullable private final byte[] mServiceData; // Transmission power level(in dB). // Transmission power level(in dB). private final int mTxPowerLevel; private final int mTxPowerLevel; Loading @@ -81,40 +79,46 @@ public final class ScanRecord { /** /** * Returns a list of service UUIDs within the advertisement that are used to identify the * 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() { public List<ParcelUuid> getServiceUuids() { return mServiceUuids; return mServiceUuids; } } /** /** * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific * SIG. * data. */ */ public int getManufacturerId() { public SparseArray<byte[]> getManufacturerSpecificData() { return mManufacturerId; return mManufacturerSpecificData; } } /** /** * Returns the manufacturer specific data which is the content of manufacturer specific data * Returns the manufacturer specific data associated with the manufacturer id. Returns * field. * {@code null} if the {@code manufacturerId} is not found. */ */ public byte[] getManufacturerSpecificData() { @Nullable return mManufacturerSpecificData; public byte[] getManufacturerSpecificData(int manufacturerId) { return mManufacturerSpecificData.get(manufacturerId); } } /** /** * Returns a 16-bit UUID of the service that the service data is associated with. * Returns a map of service UUID and its corresponding service data. */ */ public ParcelUuid getServiceDataUuid() { public Map<ParcelUuid, byte[]> getServiceData() { return mServiceDataUuid; return mServiceData; } } /** /** * Returns service data. * Returns the service data byte array associated with the {@code serviceUuid}. Returns * {@code null} if the {@code serviceDataUuid} is not found. */ */ public byte[] getServiceData() { @Nullable return mServiceData; public byte[] getServiceData(ParcelUuid serviceDataUuid) { if (serviceDataUuid == null) { return null; } return mServiceData.get(serviceDataUuid); } } /** /** Loading Loading @@ -144,14 +148,12 @@ public final class ScanRecord { } } private ScanRecord(List<ParcelUuid> serviceUuids, private ScanRecord(List<ParcelUuid> serviceUuids, ParcelUuid serviceDataUuid, byte[] serviceData, SparseArray<byte[]> manufacturerData, int manufacturerId, Map<ParcelUuid, byte[]> serviceData, byte[] manufacturerSpecificData, int advertiseFlags, int txPowerLevel, int advertiseFlags, int txPowerLevel, String localName, byte[] bytes) { String localName, byte[] bytes) { mServiceUuids = serviceUuids; mServiceUuids = serviceUuids; mManufacturerId = manufacturerId; mManufacturerSpecificData = manufacturerData; mManufacturerSpecificData = manufacturerSpecificData; mServiceDataUuid = serviceDataUuid; mServiceData = serviceData; mServiceData = serviceData; mDeviceName = localName; mDeviceName = localName; mAdvertiseFlags = advertiseFlags; mAdvertiseFlags = advertiseFlags; Loading @@ -168,7 +170,6 @@ public final class ScanRecord { * order. * order. * * * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response. * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response. * * @hide * @hide */ */ public static ScanRecord parseFromBytes(byte[] scanRecord) { public static ScanRecord parseFromBytes(byte[] scanRecord) { Loading @@ -181,10 +182,9 @@ public final class ScanRecord { List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); String localName = null; String localName = null; int txPowerLevel = Integer.MIN_VALUE; int txPowerLevel = Integer.MIN_VALUE; ParcelUuid serviceDataUuid = null; byte[] serviceData = null; SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>(); int manufacturerId = -1; Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>(); byte[] manufacturerSpecificData = null; try { try { while (currentPos < scanRecord.length) { while (currentPos < scanRecord.length) { Loading Loading @@ -230,16 +230,20 @@ public final class ScanRecord { int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT; int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT; byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos, byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos, serviceUuidLength); serviceUuidLength); serviceDataUuid = BluetoothUuid.parseUuidFrom(serviceDataUuidBytes); ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom( serviceData = extractBytes(scanRecord, currentPos + 2, dataLength - 2); serviceDataUuidBytes); byte[] serviceDataArray = extractBytes(scanRecord, currentPos + serviceUuidLength, dataLength - serviceUuidLength); serviceData.put(serviceDataUuid, serviceDataArray); break; break; case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // The first two bytes of the manufacturer specific data are // The first two bytes of the manufacturer specific data are // manufacturer ids in little endian. // manufacturer ids in little endian. manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) + int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) + (scanRecord[currentPos] & 0xFF); (scanRecord[currentPos] & 0xFF); manufacturerSpecificData = extractBytes(scanRecord, currentPos + 2, byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2, dataLength - 2); dataLength - 2); manufacturerData.put(manufacturerId, manufacturerDataBytes); break; break; default: default: // Just ignore, we don't handle such data type. // Just ignore, we don't handle such data type. Loading @@ -251,9 +255,8 @@ public final class ScanRecord { if (serviceUuids.isEmpty()) { if (serviceUuids.isEmpty()) { serviceUuids = null; serviceUuids = null; } } return new ScanRecord(serviceUuids, serviceDataUuid, serviceData, return new ScanRecord(serviceUuids, manufacturerData, serviceData, manufacturerId, manufacturerSpecificData, advertiseFlag, txPowerLevel, advertiseFlag, txPowerLevel, localName, scanRecord); localName, scanRecord); } catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) { Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); return null; return null; Loading @@ -263,13 +266,11 @@ public final class ScanRecord { @Override @Override public String toString() { public String toString() { return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids + ", mManufacturerId=" + mManufacturerId + ", mManufacturerSpecificData=" + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData) + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid=" + ", mServiceData=" + Utils.toString(mServiceData) + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData) + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; } } // Parse service UUIDs. // Parse service UUIDs. private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, int uuidLength, List<ParcelUuid> serviceUuids) { int uuidLength, List<ParcelUuid> serviceUuids) { Loading Loading
api/current.txt +9 −10 Original line number Original line Diff line number Diff line Loading @@ -6582,22 +6582,20 @@ package android.bluetooth.le { method public int describeContents(); method public int describeContents(); method public boolean getIncludeDeviceName(); method public boolean getIncludeDeviceName(); method public boolean getIncludeTxPowerLevel(); method public boolean getIncludeTxPowerLevel(); method public int getManufacturerId(); method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); method public byte[] getManufacturerSpecificData(); method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData(); method public byte[] getServiceData(); method public android.os.ParcelUuid getServiceDataUuid(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public void writeToParcel(android.os.Parcel, int); method public void writeToParcel(android.os.Parcel, int); } } public static final class AdvertiseData.Builder { public static final class AdvertiseData.Builder { ctor public 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.Builder addServiceUuid(android.os.ParcelUuid); method public android.bluetooth.le.AdvertiseData build(); method public android.bluetooth.le.AdvertiseData build(); method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean); 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 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 { public final class AdvertiseSettings implements android.os.Parcelable { Loading Loading @@ -6658,6 +6656,7 @@ package android.bluetooth.le { method public int getManufacturerId(); method public int getManufacturerId(); method public byte[] getServiceData(); method public byte[] getServiceData(); method public byte[] getServiceDataMask(); method public byte[] getServiceDataMask(); method public android.os.ParcelUuid getServiceDataUuid(); method public android.os.ParcelUuid getServiceUuid(); method public android.os.ParcelUuid getServiceUuid(); method public android.os.ParcelUuid getServiceUuidMask(); method public android.os.ParcelUuid getServiceUuidMask(); method public boolean matches(android.bluetooth.le.ScanResult); method public boolean matches(android.bluetooth.le.ScanResult); Loading @@ -6681,10 +6680,10 @@ package android.bluetooth.le { method public int getAdvertiseFlags(); method public int getAdvertiseFlags(); method public byte[] getBytes(); method public byte[] getBytes(); method public java.lang.String getDeviceName(); method public java.lang.String getDeviceName(); method public int getManufacturerId(); method public android.util.SparseArray<byte[]> getManufacturerSpecificData(); method public byte[] getManufacturerSpecificData(); method public byte[] getManufacturerSpecificData(int); method public byte[] getServiceData(); method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData(); method public android.os.ParcelUuid getServiceDataUuid(); method public byte[] getServiceData(android.os.ParcelUuid); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public java.util.List<android.os.ParcelUuid> getServiceUuids(); method public int getTxPowerLevel(); method public int getTxPowerLevel(); } }
core/java/android/bluetooth/le/AdvertiseData.java +71 −91 Original line number Original line Diff line number Diff line Loading @@ -17,14 +17,15 @@ package android.bluetooth.le; package android.bluetooth.le; import android.annotation.Nullable; import android.annotation.Nullable; import android.bluetooth.BluetoothUuid; import android.os.Parcel; import android.os.Parcel; import android.os.ParcelUuid; import android.os.ParcelUuid; import android.os.Parcelable; import android.os.Parcelable; import android.util.ArrayMap; import android.util.SparseArray; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Objects; /** /** Loading @@ -42,27 +43,18 @@ public final class AdvertiseData implements Parcelable { @Nullable @Nullable private final List<ParcelUuid> mServiceUuids; private final List<ParcelUuid> mServiceUuids; private final int mManufacturerId; private final SparseArray<byte[]> mManufacturerSpecificData; @Nullable private final Map<ParcelUuid, byte[]> mServiceData; private final byte[] mManufacturerSpecificData; @Nullable private final ParcelUuid mServiceDataUuid; @Nullable private final byte[] mServiceData; private final boolean mIncludeTxPowerLevel; private final boolean mIncludeTxPowerLevel; private final boolean mIncludeDeviceName; private final boolean mIncludeDeviceName; private AdvertiseData(List<ParcelUuid> serviceUuids, private AdvertiseData(List<ParcelUuid> serviceUuids, ParcelUuid serviceDataUuid, byte[] serviceData, SparseArray<byte[]> manufacturerData, int manufacturerId, Map<ParcelUuid, byte[]> serviceData, byte[] manufacturerSpecificData, boolean includeTxPowerLevel, boolean includeTxPowerLevel, boolean includeDeviceName) { boolean includeDeviceName) { mServiceUuids = serviceUuids; mServiceUuids = serviceUuids; mManufacturerId = manufacturerId; mManufacturerSpecificData = manufacturerData; mManufacturerSpecificData = manufacturerSpecificData; mServiceDataUuid = serviceDataUuid; mServiceData = serviceData; mServiceData = serviceData; mIncludeTxPowerLevel = includeTxPowerLevel; mIncludeTxPowerLevel = includeTxPowerLevel; mIncludeDeviceName = includeDeviceName; mIncludeDeviceName = includeDeviceName; Loading @@ -77,32 +69,17 @@ public final class AdvertiseData implements Parcelable { } } /** /** * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The * SIG. * manufacturer id is a non-negative number assigned by Bluetooth SIG. */ */ public int getManufacturerId() { public SparseArray<byte[]> getManufacturerSpecificData() { 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; return mManufacturerSpecificData; } } /** /** * Returns a 16-bit UUID of the service that the service data is associated with. * Returns a map of 16-bit UUID and its corresponding service data. */ */ public ParcelUuid getServiceDataUuid() { public Map<ParcelUuid, byte[]> getServiceData() { return mServiceDataUuid; } /** * Returns service data. */ public byte[] getServiceData() { return mServiceData; return mServiceData; } } Loading @@ -125,8 +102,8 @@ public final class AdvertiseData implements Parcelable { */ */ @Override @Override public int hashCode() { public int hashCode() { return Objects.hash(mServiceUuids, mManufacturerId, mManufacturerSpecificData, return Objects.hash(mServiceUuids, mManufacturerSpecificData, mServiceData, mServiceDataUuid, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel); mIncludeDeviceName, mIncludeTxPowerLevel); } } /** /** Loading @@ -142,20 +119,17 @@ public final class AdvertiseData implements Parcelable { } } AdvertiseData other = (AdvertiseData) obj; AdvertiseData other = (AdvertiseData) obj; return Objects.equals(mServiceUuids, other.mServiceUuids) && return Objects.equals(mServiceUuids, other.mServiceUuids) && mManufacturerId == other.mManufacturerId && Utils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) && Objects.deepEquals(mManufacturerSpecificData, other.mManufacturerSpecificData) && Utils.equals(mServiceData, other.mServiceData) && Objects.equals(mServiceDataUuid, other.mServiceDataUuid) && Objects.deepEquals(mServiceData, other.mServiceData) && mIncludeDeviceName == other.mIncludeDeviceName && mIncludeDeviceName == other.mIncludeDeviceName && mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; mIncludeTxPowerLevel == other.mIncludeTxPowerLevel; } } @Override @Override public String toString() { public String toString() { return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerId=" return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData=" + mManufacturerId + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData) + ", mServiceData=" + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid=" + Utils.toString(mServiceData) + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData) + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName=" + mIncludeDeviceName + "]"; + mIncludeDeviceName + "]"; } } Loading @@ -169,21 +143,30 @@ public final class AdvertiseData implements Parcelable { public void writeToParcel(Parcel dest, int flags) { public void writeToParcel(Parcel dest, int flags) { dest.writeList(mServiceUuids); dest.writeList(mServiceUuids); dest.writeInt(mManufacturerId); // mManufacturerSpecificData could not be null. if (mManufacturerSpecificData == 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(0); dest.writeInt(0); } else { } else { dest.writeInt(1); dest.writeInt(1); dest.writeInt(mManufacturerSpecificData.length); dest.writeInt(data.length); dest.writeByteArray(mManufacturerSpecificData); dest.writeByteArray(data); } } } dest.writeParcelable(mServiceDataUuid, flags); dest.writeInt(mServiceData.size()); if (mServiceData == null) { for (ParcelUuid uuid : mServiceData.keySet()) { dest.writeParcelable(uuid, flags); byte[] data = mServiceData.get(uuid); if (data == null) { dest.writeInt(0); dest.writeInt(0); } else { } else { dest.writeInt(1); dest.writeInt(1); dest.writeInt(mServiceData.length); dest.writeInt(data.length); dest.writeByteArray(mServiceData); dest.writeByteArray(data); } } } dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0)); dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0)); Loading @@ -209,20 +192,26 @@ public final class AdvertiseData implements Parcelable { builder.addServiceUuid(uuid); builder.addServiceUuid(uuid); } } } } int manufacturerSize = in.readInt(); for (int i = 0; i < manufacturerSize; ++i) { int manufacturerId = in.readInt(); int manufacturerId = in.readInt(); if (in.readInt() == 1) { if (in.readInt() == 1) { int manufacturerDataLength = in.readInt(); int manufacturerDataLength = in.readInt(); byte[] manufacturerData = new byte[manufacturerDataLength]; byte[] manufacturerData = new byte[manufacturerDataLength]; in.readByteArray(manufacturerData); in.readByteArray(manufacturerData); builder.setManufacturerData(manufacturerId, manufacturerData); builder.addManufacturerData(manufacturerId, manufacturerData); } } } int serviceDataSize = in.readInt(); for (int i = 0; i < serviceDataSize; ++i) { ParcelUuid serviceDataUuid = in.readParcelable( ParcelUuid serviceDataUuid = in.readParcelable( ParcelUuid.class.getClassLoader()); ParcelUuid.class.getClassLoader()); if (in.readInt() == 1) { if (in.readInt() == 1) { int serviceDataLength = in.readInt(); int serviceDataLength = in.readInt(); byte[] serviceData = new byte[serviceDataLength]; byte[] serviceData = new byte[serviceDataLength]; in.readByteArray(serviceData); in.readByteArray(serviceData); builder.setServiceData(serviceDataUuid, serviceData); builder.addServiceData(serviceDataUuid, serviceData); } } } builder.setIncludeTxPowerLevel(in.readByte() == 1); builder.setIncludeTxPowerLevel(in.readByte() == 1); builder.setIncludeDeviceName(in.readByte() == 1); builder.setIncludeDeviceName(in.readByte() == 1); Loading @@ -236,13 +225,8 @@ public final class AdvertiseData implements Parcelable { public static final class Builder { public static final class Builder { @Nullable @Nullable private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>(); private int mManufacturerId = -1; private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>(); @Nullable private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>(); private byte[] mManufacturerSpecificData; @Nullable private ParcelUuid mServiceDataUuid; @Nullable private byte[] mServiceData; private boolean mIncludeTxPowerLevel; private boolean mIncludeTxPowerLevel; private boolean mIncludeDeviceName; private boolean mIncludeDeviceName; Loading @@ -268,18 +252,17 @@ public final class AdvertiseData implements Parcelable { * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is * @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is * empty. * empty. */ */ public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) { public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) { if (serviceDataUuid == null || serviceData == null) { if (serviceDataUuid == null || serviceData == null) { throw new IllegalArgumentException( throw new IllegalArgumentException( "serviceDataUuid or serviceDataUuid is null"); "serviceDataUuid or serviceDataUuid is null"); } } mServiceDataUuid = serviceDataUuid; mServiceData.put(serviceDataUuid, serviceData); mServiceData = serviceData; return this; return this; } } /** /** * Set manufacturer specific data. * Add manufacturer specific data. * <p> * <p> * Please refer to the Bluetooth Assigned Numbers document provided by the <a * 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 * href="https://www.bluetooth.org">Bluetooth SIG</a> for a list of existing company Loading @@ -290,7 +273,7 @@ public final class AdvertiseData implements Parcelable { * @throws IllegalArgumentException If the {@code manufacturerId} is negative or * @throws IllegalArgumentException If the {@code manufacturerId} is negative or * {@code manufacturerSpecificData} is null. * {@code manufacturerSpecificData} is null. */ */ public Builder setManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) { public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) { if (manufacturerId < 0) { if (manufacturerId < 0) { throw new IllegalArgumentException( throw new IllegalArgumentException( "invalid manufacturerId - " + manufacturerId); "invalid manufacturerId - " + manufacturerId); Loading @@ -298,8 +281,7 @@ public final class AdvertiseData implements Parcelable { if (manufacturerSpecificData == null) { if (manufacturerSpecificData == null) { throw new IllegalArgumentException("manufacturerSpecificData is null"); throw new IllegalArgumentException("manufacturerSpecificData is null"); } } mManufacturerId = manufacturerId; mManufacturerSpecificData.put(manufacturerId, manufacturerSpecificData); mManufacturerSpecificData = manufacturerSpecificData; return this; return this; } } Loading @@ -324,9 +306,7 @@ public final class AdvertiseData implements Parcelable { * Build the {@link AdvertiseData}. * Build the {@link AdvertiseData}. */ */ public AdvertiseData build() { public AdvertiseData build() { return new AdvertiseData(mServiceUuids, return new AdvertiseData(mServiceUuids, mManufacturerSpecificData, mServiceData, mServiceDataUuid, mServiceData, mManufacturerId, mManufacturerSpecificData, mIncludeTxPowerLevel, mIncludeDeviceName); mIncludeTxPowerLevel, mIncludeDeviceName); } } } } Loading
core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +4 −4 Original line number Original line Diff line number Diff line Loading @@ -209,13 +209,13 @@ public final class BluetoothLeAdvertiser { num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT; } } } } if (data.getServiceDataUuid() != null) { for (ParcelUuid uuid : data.getServiceData().keySet()) { size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH + byteLength(data.getServiceData()); + byteLength(data.getServiceData().get(uuid)); } } if (data.getManufacturerId() > 0) { for (int i = 0; i < data.getManufacturerSpecificData().size(); ++i) { size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH + byteLength(data.getManufacturerSpecificData()); byteLength(data.getManufacturerSpecificData().valueAt(i)); } } if (data.getIncludeTxPowerLevel()) { if (data.getIncludeTxPowerLevel()) { size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte. size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte. Loading
core/java/android/bluetooth/le/ScanFilter.java +7 −12 Original line number Original line Diff line number Diff line Loading @@ -242,9 +242,6 @@ public final class ScanFilter implements Parcelable { return mServiceDataMask; return mServiceDataMask; } } /** * @hide */ @Nullable @Nullable public ParcelUuid getServiceDataUuid() { public ParcelUuid getServiceDataUuid() { return mServiceDataUuid; return mServiceDataUuid; Loading Loading @@ -303,19 +300,17 @@ public final class ScanFilter implements Parcelable { } } // Service data match // Service data match if (mServiceData != null) { if (mServiceDataUuid != null) { if (!Objects.equals(mServiceDataUuid, scanRecord.getServiceDataUuid()) || if (!matchesPartialData(mServiceData, mServiceDataMask, !matchesPartialData(mServiceData, mServiceDataMask, scanRecord.getServiceData(mServiceDataUuid))) { scanRecord.getServiceData())) { return false; return false; } } } } // Manufacturer data match. // Manufacturer data match. if (mManufacturerData != null) { if (mManufacturerId >= 0) { if (mManufacturerId != scanRecord.getManufacturerId() || if (!matchesPartialData(mManufacturerData, mManufacturerDataMask, !matchesPartialData(mManufacturerData, scanRecord.getManufacturerSpecificData(mManufacturerId))) { mManufacturerDataMask, scanRecord.getManufacturerSpecificData())) { return false; return false; } } } } Loading
core/java/android/bluetooth/le/ScanRecord.java +45 −44 Original line number Original line Diff line number Diff line Loading @@ -19,11 +19,14 @@ package android.bluetooth.le; import android.annotation.Nullable; import android.annotation.Nullable; import android.bluetooth.BluetoothUuid; import android.bluetooth.BluetoothUuid; import android.os.ParcelUuid; import android.os.ParcelUuid; import android.util.ArrayMap; import android.util.Log; import android.util.Log; import android.util.SparseArray; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Arrays; import java.util.List; import java.util.List; import java.util.Map; /** /** * Represents a scan record from Bluetooth LE scan. * Represents a scan record from Bluetooth LE scan. Loading Loading @@ -53,14 +56,9 @@ public final class ScanRecord { @Nullable @Nullable private final List<ParcelUuid> mServiceUuids; private final List<ParcelUuid> mServiceUuids; private final int mManufacturerId; private final SparseArray<byte[]> mManufacturerSpecificData; @Nullable private final byte[] mManufacturerSpecificData; @Nullable private final Map<ParcelUuid, byte[]> mServiceData; private final ParcelUuid mServiceDataUuid; @Nullable private final byte[] mServiceData; // Transmission power level(in dB). // Transmission power level(in dB). private final int mTxPowerLevel; private final int mTxPowerLevel; Loading @@ -81,40 +79,46 @@ public final class ScanRecord { /** /** * Returns a list of service UUIDs within the advertisement that are used to identify the * 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() { public List<ParcelUuid> getServiceUuids() { return mServiceUuids; return mServiceUuids; } } /** /** * Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth * Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific * SIG. * data. */ */ public int getManufacturerId() { public SparseArray<byte[]> getManufacturerSpecificData() { return mManufacturerId; return mManufacturerSpecificData; } } /** /** * Returns the manufacturer specific data which is the content of manufacturer specific data * Returns the manufacturer specific data associated with the manufacturer id. Returns * field. * {@code null} if the {@code manufacturerId} is not found. */ */ public byte[] getManufacturerSpecificData() { @Nullable return mManufacturerSpecificData; public byte[] getManufacturerSpecificData(int manufacturerId) { return mManufacturerSpecificData.get(manufacturerId); } } /** /** * Returns a 16-bit UUID of the service that the service data is associated with. * Returns a map of service UUID and its corresponding service data. */ */ public ParcelUuid getServiceDataUuid() { public Map<ParcelUuid, byte[]> getServiceData() { return mServiceDataUuid; return mServiceData; } } /** /** * Returns service data. * Returns the service data byte array associated with the {@code serviceUuid}. Returns * {@code null} if the {@code serviceDataUuid} is not found. */ */ public byte[] getServiceData() { @Nullable return mServiceData; public byte[] getServiceData(ParcelUuid serviceDataUuid) { if (serviceDataUuid == null) { return null; } return mServiceData.get(serviceDataUuid); } } /** /** Loading Loading @@ -144,14 +148,12 @@ public final class ScanRecord { } } private ScanRecord(List<ParcelUuid> serviceUuids, private ScanRecord(List<ParcelUuid> serviceUuids, ParcelUuid serviceDataUuid, byte[] serviceData, SparseArray<byte[]> manufacturerData, int manufacturerId, Map<ParcelUuid, byte[]> serviceData, byte[] manufacturerSpecificData, int advertiseFlags, int txPowerLevel, int advertiseFlags, int txPowerLevel, String localName, byte[] bytes) { String localName, byte[] bytes) { mServiceUuids = serviceUuids; mServiceUuids = serviceUuids; mManufacturerId = manufacturerId; mManufacturerSpecificData = manufacturerData; mManufacturerSpecificData = manufacturerSpecificData; mServiceDataUuid = serviceDataUuid; mServiceData = serviceData; mServiceData = serviceData; mDeviceName = localName; mDeviceName = localName; mAdvertiseFlags = advertiseFlags; mAdvertiseFlags = advertiseFlags; Loading @@ -168,7 +170,6 @@ public final class ScanRecord { * order. * order. * * * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response. * @param scanRecord The scan record of Bluetooth LE advertisement and/or scan response. * * @hide * @hide */ */ public static ScanRecord parseFromBytes(byte[] scanRecord) { public static ScanRecord parseFromBytes(byte[] scanRecord) { Loading @@ -181,10 +182,9 @@ public final class ScanRecord { List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>(); String localName = null; String localName = null; int txPowerLevel = Integer.MIN_VALUE; int txPowerLevel = Integer.MIN_VALUE; ParcelUuid serviceDataUuid = null; byte[] serviceData = null; SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>(); int manufacturerId = -1; Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>(); byte[] manufacturerSpecificData = null; try { try { while (currentPos < scanRecord.length) { while (currentPos < scanRecord.length) { Loading Loading @@ -230,16 +230,20 @@ public final class ScanRecord { int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT; int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT; byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos, byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos, serviceUuidLength); serviceUuidLength); serviceDataUuid = BluetoothUuid.parseUuidFrom(serviceDataUuidBytes); ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom( serviceData = extractBytes(scanRecord, currentPos + 2, dataLength - 2); serviceDataUuidBytes); byte[] serviceDataArray = extractBytes(scanRecord, currentPos + serviceUuidLength, dataLength - serviceUuidLength); serviceData.put(serviceDataUuid, serviceDataArray); break; break; case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA: // The first two bytes of the manufacturer specific data are // The first two bytes of the manufacturer specific data are // manufacturer ids in little endian. // manufacturer ids in little endian. manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) + int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) + (scanRecord[currentPos] & 0xFF); (scanRecord[currentPos] & 0xFF); manufacturerSpecificData = extractBytes(scanRecord, currentPos + 2, byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2, dataLength - 2); dataLength - 2); manufacturerData.put(manufacturerId, manufacturerDataBytes); break; break; default: default: // Just ignore, we don't handle such data type. // Just ignore, we don't handle such data type. Loading @@ -251,9 +255,8 @@ public final class ScanRecord { if (serviceUuids.isEmpty()) { if (serviceUuids.isEmpty()) { serviceUuids = null; serviceUuids = null; } } return new ScanRecord(serviceUuids, serviceDataUuid, serviceData, return new ScanRecord(serviceUuids, manufacturerData, serviceData, manufacturerId, manufacturerSpecificData, advertiseFlag, txPowerLevel, advertiseFlag, txPowerLevel, localName, scanRecord); localName, scanRecord); } catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) { Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord)); return null; return null; Loading @@ -263,13 +266,11 @@ public final class ScanRecord { @Override @Override public String toString() { public String toString() { return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids + ", mManufacturerId=" + mManufacturerId + ", mManufacturerSpecificData=" + ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData) + Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid=" + ", mServiceData=" + Utils.toString(mServiceData) + mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData) + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; + ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]"; } } // Parse service UUIDs. // Parse service UUIDs. private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength, int uuidLength, List<ParcelUuid> serviceUuids) { int uuidLength, List<ParcelUuid> serviceUuids) { Loading