diff options
author | Wei Wang <weiwa@google.com> | 2014-07-23 20:33:31 -0700 |
---|---|---|
committer | Wei Wang <weiwa@google.com> | 2014-07-23 20:39:12 -0700 |
commit | 0e81ca25432b3606eba841206b7a4a6ed74bd54b (patch) | |
tree | 4d1565684bef55f3d6e07ffff5d7462c281141d7 | |
parent | 35efc633d0af55ebe6402bd03b91f1903927cec5 (diff) | |
download | frameworks_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.java | 51 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/BluetoothLeAdvertiser.java | 70 |
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. */ |