summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWei Wang <weiwa@google.com>2014-07-23 20:33:31 -0700
committerWei Wang <weiwa@google.com>2014-07-23 20:39:12 -0700
commit0e81ca25432b3606eba841206b7a4a6ed74bd54b (patch)
tree4d1565684bef55f3d6e07ffff5d7462c281141d7
parent35efc633d0af55ebe6402bd03b91f1903927cec5 (diff)
downloadframeworks_base-0e81ca25432b3606eba841206b7a4a6ed74bd54b.zip
frameworks_base-0e81ca25432b3606eba841206b7a4a6ed74bd54b.tar.gz
frameworks_base-0e81ca25432b3606eba841206b7a4a6ed74bd54b.tar.bz2
Move AdvertiseData length check to BluetoothAdvertiser.
This will keep AdvertiseData simple and avoid coupling with BluetoothAdapter. Change-Id: I3609652bdea1c6e757bac7d2dada7f8ddf20a5e3
-rw-r--r--core/java/android/bluetooth/le/AdvertiseData.java51
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeAdvertiser.java70
2 files changed, 71 insertions, 50 deletions
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
index 34fecfa..b137eeb 100644
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ b/core/java/android/bluetooth/le/AdvertiseData.java
@@ -202,6 +202,7 @@ public final class AdvertiseData implements Parcelable {
@Override
public AdvertiseData createFromParcel(Parcel in) {
Builder builder = new Builder();
+ @SuppressWarnings("unchecked")
List<ParcelUuid> uuids = in.readArrayList(ParcelUuid.class.getClassLoader());
if (uuids != null) {
for (ParcelUuid uuid : uuids) {
@@ -233,12 +234,6 @@ public final class AdvertiseData implements Parcelable {
* Builder for {@link AdvertiseData}.
*/
public static final class Builder {
- private static final int MAX_ADVERTISING_DATA_BYTES = 31;
- // Each fields need one byte for field length and another byte for field type.
- private static final int OVERHEAD_BYTES_PER_FIELD = 2;
- // Flags field will be set by system.
- private static final int FLAGS_FIELD_BYTES = 3;
-
@Nullable
private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
private int mManufacturerId = -1;
@@ -334,49 +329,5 @@ public final class AdvertiseData implements Parcelable {
mServiceData, mManufacturerId, mManufacturerSpecificData,
mIncludeTxPowerLevel, mIncludeDeviceName);
}
-
- // Compute the size of the advertisement data.
- private int totalBytes() {
- int size = FLAGS_FIELD_BYTES; // flags field is always set.
- if (mServiceUuids != null) {
- int num16BitUuids = 0;
- int num32BitUuids = 0;
- int num128BitUuids = 0;
- for (ParcelUuid uuid : mServiceUuids) {
- if (BluetoothUuid.is16BitUuid(uuid)) {
- ++num16BitUuids;
- } else if (BluetoothUuid.is32BitUuid(uuid)) {
- ++num32BitUuids;
- } else {
- ++num128BitUuids;
- }
- }
- // 16 bit service uuids are grouped into one field when doing advertising.
- if (num16BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD +
- num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
- }
- // 32 bit service uuids are grouped into one field when doing advertising.
- if (num32BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD +
- num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
- }
- // 128 bit service uuids are grouped into one field when doing advertising.
- if (num128BitUuids != 0) {
- size += OVERHEAD_BYTES_PER_FIELD +
- num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
- }
- }
- if (mServiceData != null) {
- size += OVERHEAD_BYTES_PER_FIELD + mServiceData.length;
- }
- if (mManufacturerSpecificData != null) {
- size += OVERHEAD_BYTES_PER_FIELD + mManufacturerSpecificData.length;
- }
- if (mIncludeTxPowerLevel) {
- size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte.
- }
- return size;
- }
}
}
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index fc53afe..93d4349 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -18,6 +18,7 @@ package android.bluetooth.le;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothGattCallback;
import android.bluetooth.IBluetoothManager;
@@ -49,6 +50,14 @@ public final class BluetoothLeAdvertiser {
private static final String TAG = "BluetoothLeAdvertiser";
+ private static final int MAX_ADVERTISING_DATA_BYTES = 31;
+ // Each fields need one byte for field length and another byte for field type.
+ private static final int OVERHEAD_BYTES_PER_FIELD = 2;
+ // Flags field will be set by system.
+ private static final int FLAGS_FIELD_BYTES = 3;
+ private static final int MANUFACTURER_SPECIFIC_DATA_LENGTH = 2;
+ private static final int SERVICE_DATA_UUID_LENGTH = 2;
+
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
@@ -101,6 +110,11 @@ public final class BluetoothLeAdvertiser {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");
}
+ if (totalBytes(advertiseData) > MAX_ADVERTISING_DATA_BYTES ||
+ totalBytes(scanResponse) > MAX_ADVERTISING_DATA_BYTES) {
+ postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
+ return;
+ }
if (mLeAdvertisers.containsKey(callback)) {
postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
return;
@@ -159,6 +173,62 @@ public final class BluetoothLeAdvertiser {
}
}
+ // Compute the size of the advertise data.
+ private int totalBytes(AdvertiseData data) {
+ if (data == null) {
+ return 0;
+ }
+ int size = FLAGS_FIELD_BYTES; // flags field is always set.
+ if (data.getServiceUuids() != null) {
+ int num16BitUuids = 0;
+ int num32BitUuids = 0;
+ int num128BitUuids = 0;
+ for (ParcelUuid uuid : data.getServiceUuids()) {
+ if (BluetoothUuid.is16BitUuid(uuid)) {
+ ++num16BitUuids;
+ } else if (BluetoothUuid.is32BitUuid(uuid)) {
+ ++num32BitUuids;
+ } else {
+ ++num128BitUuids;
+ }
+ }
+ // 16 bit service uuids are grouped into one field when doing advertising.
+ if (num16BitUuids != 0) {
+ size += OVERHEAD_BYTES_PER_FIELD +
+ num16BitUuids * BluetoothUuid.UUID_BYTES_16_BIT;
+ }
+ // 32 bit service uuids are grouped into one field when doing advertising.
+ if (num32BitUuids != 0) {
+ size += OVERHEAD_BYTES_PER_FIELD +
+ num32BitUuids * BluetoothUuid.UUID_BYTES_32_BIT;
+ }
+ // 128 bit service uuids are grouped into one field when doing advertising.
+ if (num128BitUuids != 0) {
+ size += OVERHEAD_BYTES_PER_FIELD +
+ num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
+ }
+ }
+ if (data.getServiceDataUuid() != null) {
+ size += OVERHEAD_BYTES_PER_FIELD + SERVICE_DATA_UUID_LENGTH
+ + byteLength(data.getServiceData());
+ }
+ if (data.getManufacturerId() > 0) {
+ size += OVERHEAD_BYTES_PER_FIELD + MANUFACTURER_SPECIFIC_DATA_LENGTH +
+ byteLength(data.getManufacturerSpecificData());
+ }
+ if (data.getIncludeTxPowerLevel()) {
+ size += OVERHEAD_BYTES_PER_FIELD + 1; // tx power level value is one byte.
+ }
+ if (data.getIncludeDeviceName() && mBluetoothAdapter.getName() != null) {
+ size += OVERHEAD_BYTES_PER_FIELD + mBluetoothAdapter.getName().length();
+ }
+ return size;
+ }
+
+ private int byteLength(byte[] array) {
+ return array == null ? 0 : array.length;
+ }
+
/**
* Bluetooth GATT interface callbacks for advertising.
*/