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

This reverts commit 14c797702543bb5ced989565d90abcfa55c7db46.
This commit is contained in:
Wei Wang
2014-08-01 11:12:37 -07:00
parent 9aa499ac42
commit 6bf513d32d
8 changed files with 272 additions and 171 deletions

View File

@@ -6582,22 +6582,20 @@ package android.bluetooth.le {
method public int describeContents();
method public boolean getIncludeDeviceName();
method public boolean getIncludeTxPowerLevel();
method public int getManufacturerId();
method public byte[] getManufacturerSpecificData();
method public byte[] getServiceData();
method public android.os.ParcelUuid getServiceDataUuid();
method public android.util.SparseArray<byte[]> getManufacturerSpecificData();
method public java.util.Map<android.os.ParcelUuid, byte[]> getServiceData();
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 {
@@ -6658,6 +6656,7 @@ 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);
@@ -6681,10 +6680,10 @@ package android.bluetooth.le {
method public int getAdvertiseFlags();
method public byte[] getBytes();
method public java.lang.String getDeviceName();
method public int getManufacturerId();
method public byte[] getManufacturerSpecificData();
method public byte[] getServiceData();
method public android.os.ParcelUuid getServiceDataUuid();
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 java.util.List<android.os.ParcelUuid> getServiceUuids();
method public int getTxPowerLevel();
}

View File

@@ -17,14 +17,15 @@
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;
/**
@@ -42,27 +43,18 @@ public final class AdvertiseData implements Parcelable {
@Nullable
private final List<ParcelUuid> mServiceUuids;
private final int mManufacturerId;
@Nullable
private final byte[] mManufacturerSpecificData;
@Nullable
private final ParcelUuid mServiceDataUuid;
@Nullable
private final byte[] mServiceData;
private final SparseArray<byte[]> mManufacturerSpecificData;
private final Map<ParcelUuid, byte[]> mServiceData;
private final boolean mIncludeTxPowerLevel;
private final boolean mIncludeDeviceName;
private AdvertiseData(List<ParcelUuid> serviceUuids,
ParcelUuid serviceDataUuid, byte[] serviceData,
int manufacturerId,
byte[] manufacturerSpecificData, boolean includeTxPowerLevel,
SparseArray<byte[]> manufacturerData,
Map<ParcelUuid, byte[]> serviceData,
boolean includeTxPowerLevel,
boolean includeDeviceName) {
mServiceUuids = serviceUuids;
mManufacturerId = manufacturerId;
mManufacturerSpecificData = manufacturerSpecificData;
mServiceDataUuid = serviceDataUuid;
mManufacturerSpecificData = manufacturerData;
mServiceData = serviceData;
mIncludeTxPowerLevel = includeTxPowerLevel;
mIncludeDeviceName = includeDeviceName;
@@ -77,32 +69,17 @@ public final class AdvertiseData implements Parcelable {
}
/**
* Returns the manufacturer identifier, which is a non-negative number assigned by Bluetooth
* SIG.
* Returns an array of manufacturer Id and the corresponding manufacturer specific data. The
* manufacturer id is a non-negative number assigned by Bluetooth SIG.
*/
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() {
public SparseArray<byte[]> getManufacturerSpecificData() {
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() {
return mServiceDataUuid;
}
/**
* Returns service data.
*/
public byte[] getServiceData() {
public Map<ParcelUuid, byte[]> getServiceData() {
return mServiceData;
}
@@ -125,8 +102,8 @@ public final class AdvertiseData implements Parcelable {
*/
@Override
public int hashCode() {
return Objects.hash(mServiceUuids, mManufacturerId, mManufacturerSpecificData,
mServiceDataUuid, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel);
return Objects.hash(mServiceUuids, mManufacturerSpecificData, mServiceData,
mIncludeDeviceName, mIncludeTxPowerLevel);
}
/**
@@ -142,20 +119,17 @@ public final class AdvertiseData implements Parcelable {
}
AdvertiseData other = (AdvertiseData) obj;
return Objects.equals(mServiceUuids, other.mServiceUuids) &&
mManufacturerId == other.mManufacturerId &&
Objects.deepEquals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
Objects.equals(mServiceDataUuid, other.mServiceDataUuid) &&
Objects.deepEquals(mServiceData, other.mServiceData) &&
Utils.equals(mManufacturerSpecificData, other.mManufacturerSpecificData) &&
Utils.equals(mServiceData, other.mServiceData) &&
mIncludeDeviceName == other.mIncludeDeviceName &&
mIncludeTxPowerLevel == other.mIncludeTxPowerLevel;
}
@Override
public String toString() {
return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerId="
+ mManufacturerId + ", mManufacturerSpecificData="
+ Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid="
+ mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData)
return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mManufacturerSpecificData="
+ Utils.toString(mManufacturerSpecificData) + ", mServiceData="
+ Utils.toString(mServiceData)
+ ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
+ mIncludeDeviceName + "]";
}
@@ -169,21 +143,30 @@ public final class AdvertiseData implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(mServiceUuids);
dest.writeInt(mManufacturerId);
if (mManufacturerSpecificData == null) {
dest.writeInt(0);
} else {
dest.writeInt(1);
dest.writeInt(mManufacturerSpecificData.length);
dest.writeByteArray(mManufacturerSpecificData);
// 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(0);
} else {
dest.writeInt(1);
dest.writeInt(data.length);
dest.writeByteArray(data);
}
}
dest.writeParcelable(mServiceDataUuid, flags);
if (mServiceData == null) {
dest.writeInt(0);
} else {
dest.writeInt(1);
dest.writeInt(mServiceData.length);
dest.writeByteArray(mServiceData);
dest.writeInt(mServiceData.size());
for (ParcelUuid uuid : mServiceData.keySet()) {
dest.writeParcelable(uuid, flags);
byte[] data = mServiceData.get(uuid);
if (data == null) {
dest.writeInt(0);
} else {
dest.writeInt(1);
dest.writeInt(data.length);
dest.writeByteArray(data);
}
}
dest.writeByte((byte) (getIncludeTxPowerLevel() ? 1 : 0));
dest.writeByte((byte) (getIncludeDeviceName() ? 1 : 0));
@@ -209,20 +192,26 @@ public final class AdvertiseData implements Parcelable {
builder.addServiceUuid(uuid);
}
}
int manufacturerId = in.readInt();
if (in.readInt() == 1) {
int manufacturerDataLength = in.readInt();
byte[] manufacturerData = new byte[manufacturerDataLength];
in.readByteArray(manufacturerData);
builder.setManufacturerData(manufacturerId, manufacturerData);
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);
}
}
ParcelUuid serviceDataUuid = in.readParcelable(
ParcelUuid.class.getClassLoader());
if (in.readInt() == 1) {
int serviceDataLength = in.readInt();
byte[] serviceData = new byte[serviceDataLength];
in.readByteArray(serviceData);
builder.setServiceData(serviceDataUuid, serviceData);
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.setIncludeTxPowerLevel(in.readByte() == 1);
builder.setIncludeDeviceName(in.readByte() == 1);
@@ -236,13 +225,8 @@ public final class AdvertiseData implements Parcelable {
public static final class Builder {
@Nullable
private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
private int mManufacturerId = -1;
@Nullable
private byte[] mManufacturerSpecificData;
@Nullable
private ParcelUuid mServiceDataUuid;
@Nullable
private byte[] mServiceData;
private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>();
private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>();
private boolean mIncludeTxPowerLevel;
private boolean mIncludeDeviceName;
@@ -268,18 +252,17 @@ public final class AdvertiseData implements Parcelable {
* @throws IllegalArgumentException If the {@code serviceDataUuid} or {@code serviceData} is
* empty.
*/
public Builder setServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
public Builder addServiceData(ParcelUuid serviceDataUuid, byte[] serviceData) {
if (serviceDataUuid == null || serviceData == null) {
throw new IllegalArgumentException(
"serviceDataUuid or serviceDataUuid is null");
}
mServiceDataUuid = serviceDataUuid;
mServiceData = serviceData;
mServiceData.put(serviceDataUuid, serviceData);
return this;
}
/**
* Set manufacturer specific data.
* Add 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
@@ -290,7 +273,7 @@ public final class AdvertiseData implements Parcelable {
* @throws IllegalArgumentException If the {@code manufacturerId} is negative or
* {@code manufacturerSpecificData} is null.
*/
public Builder setManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) {
public Builder addManufacturerData(int manufacturerId, byte[] manufacturerSpecificData) {
if (manufacturerId < 0) {
throw new IllegalArgumentException(
"invalid manufacturerId - " + manufacturerId);
@@ -298,8 +281,7 @@ public final class AdvertiseData implements Parcelable {
if (manufacturerSpecificData == null) {
throw new IllegalArgumentException("manufacturerSpecificData is null");
}
mManufacturerId = manufacturerId;
mManufacturerSpecificData = manufacturerSpecificData;
mManufacturerSpecificData.put(manufacturerId, manufacturerSpecificData);
return this;
}
@@ -324,9 +306,7 @@ public final class AdvertiseData implements Parcelable {
* Build the {@link AdvertiseData}.
*/
public AdvertiseData build() {
return new AdvertiseData(mServiceUuids,
mServiceDataUuid,
mServiceData, mManufacturerId, mManufacturerSpecificData,
return new AdvertiseData(mServiceUuids, mManufacturerSpecificData, mServiceData,
mIncludeTxPowerLevel, mIncludeDeviceName);
}
}

View File

@@ -209,13 +209,13 @@ public final class BluetoothLeAdvertiser {
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
+ 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 +
byteLength(data.getManufacturerSpecificData());
byteLength(data.getManufacturerSpecificData().valueAt(i));
}
if (data.getIncludeTxPowerLevel()) {
size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte.

View File

@@ -181,7 +181,7 @@ public final class ScanFilter implements Parcelable {
byte[] serviceDataMask = new byte[serviceDataMaskLength];
in.readByteArray(serviceDataMask);
builder.setServiceData(
servcieDataUuid, serviceData, serviceDataMask);
servcieDataUuid, serviceData, serviceDataMask);
}
}
}
@@ -242,9 +242,6 @@ public final class ScanFilter implements Parcelable {
return mServiceDataMask;
}
/**
* @hide
*/
@Nullable
public ParcelUuid getServiceDataUuid() {
return mServiceDataUuid;
@@ -303,19 +300,17 @@ public final class ScanFilter implements Parcelable {
}
// Service data match
if (mServiceData != null) {
if (!Objects.equals(mServiceDataUuid, scanRecord.getServiceDataUuid()) ||
!matchesPartialData(mServiceData, mServiceDataMask,
scanRecord.getServiceData())) {
if (mServiceDataUuid != null) {
if (!matchesPartialData(mServiceData, mServiceDataMask,
scanRecord.getServiceData(mServiceDataUuid))) {
return false;
}
}
// Manufacturer data match.
if (mManufacturerData != null) {
if (mManufacturerId != scanRecord.getManufacturerId() ||
!matchesPartialData(mManufacturerData,
mManufacturerDataMask, scanRecord.getManufacturerSpecificData())) {
if (mManufacturerId >= 0) {
if (!matchesPartialData(mManufacturerData, mManufacturerDataMask,
scanRecord.getManufacturerSpecificData(mManufacturerId))) {
return false;
}
}

View File

@@ -19,11 +19,14 @@ 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.
@@ -53,14 +56,9 @@ public final class ScanRecord {
@Nullable
private final List<ParcelUuid> mServiceUuids;
private final int mManufacturerId;
@Nullable
private final byte[] mManufacturerSpecificData;
private final SparseArray<byte[]> mManufacturerSpecificData;
@Nullable
private final ParcelUuid mServiceDataUuid;
@Nullable
private final byte[] mServiceData;
private final Map<ParcelUuid, byte[]> mServiceData;
// Transmission power level(in dB).
private final int mTxPowerLevel;
@@ -81,42 +79,48 @@ 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 the manufacturer identifier, which is a non-negative number assigned by Bluetooth
* SIG.
* Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific
* data.
*/
public int getManufacturerId() {
return mManufacturerId;
}
/**
* Returns the manufacturer specific data which is the content of manufacturer specific data
* field.
*/
public byte[] getManufacturerSpecificData() {
public SparseArray<byte[]> getManufacturerSpecificData() {
return mManufacturerSpecificData;
}
/**
* Returns a 16-bit UUID of the service that the service data is associated with.
* Returns the manufacturer specific data associated with the manufacturer id. Returns
* {@code null} if the {@code manufacturerId} is not found.
*/
public ParcelUuid getServiceDataUuid() {
return mServiceDataUuid;
@Nullable
public byte[] getManufacturerSpecificData(int manufacturerId) {
return mManufacturerSpecificData.get(manufacturerId);
}
/**
* Returns service data.
* Returns a map of service UUID and its corresponding service data.
*/
public byte[] getServiceData() {
public Map<ParcelUuid, byte[]> getServiceData() {
return mServiceData;
}
/**
* Returns the service data byte array associated with the {@code serviceUuid}. Returns
* {@code null} if the {@code serviceDataUuid} is not found.
*/
@Nullable
public byte[] getServiceData(ParcelUuid serviceDataUuid) {
if (serviceDataUuid == null) {
return null;
}
return mServiceData.get(serviceDataUuid);
}
/**
* Returns the transmission power level of the packet in dBm. Returns {@link Integer#MIN_VALUE}
* if the field is not set. This value can be used to calculate the path loss of a received
@@ -144,14 +148,12 @@ public final class ScanRecord {
}
private ScanRecord(List<ParcelUuid> serviceUuids,
ParcelUuid serviceDataUuid, byte[] serviceData,
int manufacturerId,
byte[] manufacturerSpecificData, int advertiseFlags, int txPowerLevel,
SparseArray<byte[]> manufacturerData,
Map<ParcelUuid, byte[]> serviceData,
int advertiseFlags, int txPowerLevel,
String localName, byte[] bytes) {
mServiceUuids = serviceUuids;
mManufacturerId = manufacturerId;
mManufacturerSpecificData = manufacturerSpecificData;
mServiceDataUuid = serviceDataUuid;
mManufacturerSpecificData = manufacturerData;
mServiceData = serviceData;
mDeviceName = localName;
mAdvertiseFlags = advertiseFlags;
@@ -168,7 +170,6 @@ 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) {
@@ -181,10 +182,9 @@ public final class ScanRecord {
List<ParcelUuid> serviceUuids = new ArrayList<ParcelUuid>();
String localName = null;
int txPowerLevel = Integer.MIN_VALUE;
ParcelUuid serviceDataUuid = null;
byte[] serviceData = null;
int manufacturerId = -1;
byte[] manufacturerSpecificData = null;
SparseArray<byte[]> manufacturerData = new SparseArray<byte[]>();
Map<ParcelUuid, byte[]> serviceData = new ArrayMap<ParcelUuid, byte[]>();
try {
while (currentPos < scanRecord.length) {
@@ -230,16 +230,20 @@ public final class ScanRecord {
int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
serviceUuidLength);
serviceDataUuid = BluetoothUuid.parseUuidFrom(serviceDataUuidBytes);
serviceData = extractBytes(scanRecord, currentPos + 2, dataLength - 2);
ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
serviceDataUuidBytes);
byte[] serviceDataArray = extractBytes(scanRecord,
currentPos + serviceUuidLength, dataLength - serviceUuidLength);
serviceData.put(serviceDataUuid, serviceDataArray);
break;
case DATA_TYPE_MANUFACTURER_SPECIFIC_DATA:
// The first two bytes of the manufacturer specific data are
// manufacturer ids in little endian.
manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) +
int manufacturerId = ((scanRecord[currentPos + 1] & 0xFF) << 8) +
(scanRecord[currentPos] & 0xFF);
manufacturerSpecificData = extractBytes(scanRecord, currentPos + 2,
byte[] manufacturerDataBytes = extractBytes(scanRecord, currentPos + 2,
dataLength - 2);
manufacturerData.put(manufacturerId, manufacturerDataBytes);
break;
default:
// Just ignore, we don't handle such data type.
@@ -251,9 +255,8 @@ public final class ScanRecord {
if (serviceUuids.isEmpty()) {
serviceUuids = null;
}
return new ScanRecord(serviceUuids, serviceDataUuid, serviceData,
manufacturerId, manufacturerSpecificData, advertiseFlag, txPowerLevel,
localName, scanRecord);
return new ScanRecord(serviceUuids, manufacturerData, serviceData,
advertiseFlag, txPowerLevel, localName, scanRecord);
} catch (IndexOutOfBoundsException e) {
Log.e(TAG, "unable to parse scan record: " + Arrays.toString(scanRecord));
return null;
@@ -263,13 +266,11 @@ public final class ScanRecord {
@Override
public String toString() {
return "ScanRecord [mAdvertiseFlags=" + mAdvertiseFlags + ", mServiceUuids=" + mServiceUuids
+ ", mManufacturerId=" + mManufacturerId + ", mManufacturerSpecificData="
+ Arrays.toString(mManufacturerSpecificData) + ", mServiceDataUuid="
+ mServiceDataUuid + ", mServiceData=" + Arrays.toString(mServiceData)
+ ", mManufacturerSpecificData=" + Utils.toString(mManufacturerSpecificData)
+ ", mServiceData=" + Utils.toString(mServiceData)
+ ", mTxPowerLevel=" + mTxPowerLevel + ", mDeviceName=" + mDeviceName + "]";
}
// Parse service UUIDs.
private static int parseServiceUuid(byte[] scanRecord, int currentPos, int dataLength,
int uuidLength, List<ParcelUuid> serviceUuids) {

View File

@@ -0,0 +1,126 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth.le;
import android.util.SparseArray;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Helper class for Bluetooth LE utils.
*
* @hide
*/
public class Utils {
/**
* Returns a string composed from a {@link SparseArray}.
*/
static String toString(SparseArray<byte[]> array) {
if (array == null) {
return "null";
}
if (array.size() == 0) {
return "{}";
}
StringBuilder buffer = new StringBuilder();
buffer.append('{');
for (int i = 0; i < array.size(); ++i) {
buffer.append(array.keyAt(i)).append("=").append(array.valueAt(i));
}
buffer.append('}');
return buffer.toString();
}
/**
* Returns a string composed from a {@link Map}.
*/
static <T> String toString(Map<T, byte[]> map) {
if (map == null) {
return "null";
}
if (map.isEmpty()) {
return "{}";
}
StringBuilder buffer = new StringBuilder();
buffer.append('{');
Iterator<Map.Entry<T, byte[]>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<T, byte[]> entry = it.next();
Object key = entry.getKey();
buffer.append(key).append("=").append(Arrays.toString(map.get(key)));
if (it.hasNext()) {
buffer.append(", ");
}
}
buffer.append('}');
return buffer.toString();
}
/**
* Check whether two {@link SparseArray} equal.
*/
static boolean equals(SparseArray<byte[]> array, SparseArray<byte[]> otherArray) {
if (array == otherArray) {
return true;
}
if (array == null || otherArray == null) {
return false;
}
if (array.size() != otherArray.size()) {
return false;
}
// Keys are guaranteed in ascending order when indices are in ascending order.
for (int i = 0; i < array.size(); ++i) {
if (array.keyAt(i) != otherArray.keyAt(i) ||
!Arrays.equals(array.valueAt(i), otherArray.valueAt(i))) {
return false;
}
}
return true;
}
/**
* Check whether two {@link Map} equal.
*/
static <T> boolean equals(Map<T, byte[]> map, Map<T, byte[]> otherMap) {
if (map == otherMap) {
return true;
}
if (map == null || otherMap == null) {
return false;
}
if (map.size() != otherMap.size()) {
return false;
}
Set<T> keys = map.keySet();
if (!keys.equals(otherMap.keySet())) {
return false;
}
for (T key : keys) {
if (!Objects.deepEquals(map.get(key), otherMap.get(key))) {
return false;
}
}
return true;
}
}

View File

@@ -66,7 +66,7 @@ public class AdvertiseDataTest extends TestCase {
byte[] manufacturerData = new byte[0];
AdvertiseData data =
mAdvertiseDataBuilder.setIncludeDeviceName(true)
.setManufacturerData(manufacturerId, manufacturerData).build();
.addManufacturerData(manufacturerId, manufacturerData).build();
data.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
AdvertiseData dataFromParcel =
@@ -81,7 +81,7 @@ public class AdvertiseDataTest extends TestCase {
byte[] serviceData = new byte[0];
AdvertiseData data =
mAdvertiseDataBuilder.setIncludeDeviceName(true)
.setServiceData(uuid, serviceData).build();
.addServiceData(uuid, serviceData).build();
data.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
AdvertiseData dataFromParcel =
@@ -117,7 +117,7 @@ public class AdvertiseDataTest extends TestCase {
AdvertiseData data =
mAdvertiseDataBuilder.setIncludeDeviceName(true)
.addServiceUuid(uuid).addServiceUuid(uuid2)
.setManufacturerData(manufacturerId, manufacturerData).build();
.addManufacturerData(manufacturerId, manufacturerData).build();
data.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
@@ -134,7 +134,7 @@ public class AdvertiseDataTest extends TestCase {
(byte) 0xF0, 0x00, 0x02, 0x15 };
AdvertiseData data =
mAdvertiseDataBuilder.setIncludeDeviceName(true)
.setServiceData(uuid, serviceData).build();
.addServiceData(uuid, serviceData).build();
data.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
AdvertiseData dataFromParcel =

View File

@@ -53,13 +53,13 @@ public class ScanRecordTest extends TestCase {
assertEquals("Ped", data.getDeviceName());
assertEquals(-20, data.getTxPowerLevel());
assertEquals(0x00e0, data.getManufacturerId());
assertTrue(data.getManufacturerSpecificData().get(0x00E0) != null);
assertArrayEquals(new byte[] {
0x02, 0x15 }, data.getManufacturerSpecificData());
0x02, 0x15 }, data.getManufacturerSpecificData().get(0x00E0));
assertEquals(uuid2, data.getServiceDataUuid());
assertTrue(data.getServiceData().containsKey(uuid2));
assertArrayEquals(new byte[] {
0x50, 0x64 }, data.getServiceData());
0x50, 0x64 }, data.getServiceData().get(uuid2));
}
// Assert two byte arrays are equal.