Bluetooth LE Advertising minor improvements
This patch adds some additional error checking for the advertising set parameters, and some more comments. Test: manual Bug: 30622771 Change-Id: I87bd44f4179ef63694ad3ed656dc2acc52e40f1e
This commit is contained in:
@ -16,6 +16,7 @@
|
||||
|
||||
package android.bluetooth.le;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.IBluetoothGatt;
|
||||
import android.bluetooth.IBluetoothManager;
|
||||
import android.bluetooth.le.IAdvertisingSetCallback;
|
||||
@ -57,11 +58,12 @@ public final class AdvertisingSet {
|
||||
|
||||
/**
|
||||
* Enables Advertising. This method returns immediately, the operation status is
|
||||
* delivered
|
||||
* through {@code callback.onAdvertisingEnabled()}.
|
||||
* delivered through {@code callback.onAdvertisingEnabled()}.
|
||||
* <p>
|
||||
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
|
||||
*
|
||||
* @param enable whether the advertising should be enabled (true), or disabled (false)
|
||||
* @param timeoutMillis duration for which that advertising set is enabled.
|
||||
*/
|
||||
public void enableAdvertising(boolean enable, int timeout) {
|
||||
try {
|
||||
@ -77,10 +79,16 @@ public final class AdvertisingSet {
|
||||
* delivered through {@code callback.onAdvertisingDataSet()}.
|
||||
* <p>
|
||||
* Advertising data must be empty if non-legacy scannable advertising is used.
|
||||
*
|
||||
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
|
||||
* advertisement is connectable, three bytes will be added for flags. If the
|
||||
* update takes place when the advertising set is enabled, the data can be
|
||||
* maximum 251 bytes long.
|
||||
*/
|
||||
public void setAdvertisingData(AdvertiseData data) {
|
||||
public void setAdvertisingData(AdvertiseData advertiseData) {
|
||||
try {
|
||||
gatt.setAdvertisingData(this.advertiserId, data);
|
||||
gatt.setAdvertisingData(this.advertiserId, advertiseData);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "remote exception - ", e);
|
||||
}
|
||||
@ -90,10 +98,15 @@ public final class AdvertisingSet {
|
||||
* Set/update scan response data. Make sure that data doesn't exceed the size limit for
|
||||
* specified AdvertisingSetParameters. This method returns immediately, the operation status
|
||||
* is delivered through {@code callback.onScanResponseDataSet()}.
|
||||
*
|
||||
* @param scanResponse Scan response associated with the advertisement data. Size must not
|
||||
* exceed {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
|
||||
* update takes place when the advertising set is enabled, the data can be
|
||||
* maximum 251 bytes long.
|
||||
*/
|
||||
public void setScanResponseData(AdvertiseData data) {
|
||||
public void setScanResponseData(AdvertiseData scanResponse) {
|
||||
try {
|
||||
gatt.setScanResponseData(this.advertiserId, data);
|
||||
gatt.setScanResponseData(this.advertiserId, scanResponse);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "remote exception - ", e);
|
||||
}
|
||||
@ -103,6 +116,8 @@ public final class AdvertisingSet {
|
||||
* Update advertising parameters associated with this AdvertisingSet. Must be called when
|
||||
* advertising is not active. This method returns immediately, the operation status is delivered
|
||||
* through {@code callback.onAdvertisingParametersUpdated}.
|
||||
*
|
||||
* @param parameters advertising set parameters.
|
||||
*/
|
||||
public void setAdvertisingParameters(AdvertisingSetParameters parameters) {
|
||||
try {
|
||||
@ -130,10 +145,15 @@ public final class AdvertisingSet {
|
||||
* or after advertising was started with periodic advertising data set. This method returns
|
||||
* immediately, the operation status is delivered through
|
||||
* {@code callback.onPeriodicAdvertisingDataSet()}.
|
||||
*
|
||||
* @param periodicData Periodic advertising data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
|
||||
* update takes place when the periodic advertising is enabled for this set,
|
||||
* the data can be maximum 251 bytes long.
|
||||
*/
|
||||
public void setPeriodicAdvertisingData(AdvertiseData data) {
|
||||
public void setPeriodicAdvertisingData(AdvertiseData periodicData) {
|
||||
try {
|
||||
gatt.setPeriodicAdvertisingData(this.advertiserId, data);
|
||||
gatt.setPeriodicAdvertisingData(this.advertiserId, periodicData);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "remote exception - ", e);
|
||||
}
|
||||
@ -142,6 +162,8 @@ public final class AdvertisingSet {
|
||||
/**
|
||||
* Used to enable/disable periodic advertising. This method returns immediately, the operation
|
||||
* status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
|
||||
*
|
||||
* @param enable whether the periodic advertising should be enabled (true), or disabled (false).
|
||||
*/
|
||||
public void setPeriodicAdvertisingEnable(boolean enable) {
|
||||
try {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package android.bluetooth.le;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
@ -305,7 +306,7 @@ public final class AdvertisingSetParameters implements Parcelable {
|
||||
* This is used only if legacy mode is not used.
|
||||
*
|
||||
* @param includeTxPower whether TX power should be included in extended
|
||||
* header
|
||||
* header
|
||||
*/
|
||||
public Builder setIncludeTxPower(boolean includeTxPower) {
|
||||
this.includeTxPower = includeTxPower;
|
||||
@ -317,6 +318,8 @@ public final class AdvertisingSetParameters implements Parcelable {
|
||||
*
|
||||
* This is used only if legacy mode is not used.
|
||||
*
|
||||
* Use {@link BluetoothAdapter#isLeCodedPhySupported} to determine if LE Coded PHY is
|
||||
* supported on this device.
|
||||
* @param primaryPhy Primary advertising physical channel, can only be
|
||||
* {@link AdvertisingSetParameters#PHY_LE_1M} or
|
||||
* {@link AdvertisingSetParameters#PHY_LE_CODED}.
|
||||
@ -335,6 +338,10 @@ public final class AdvertisingSetParameters implements Parcelable {
|
||||
*
|
||||
* This is used only if legacy mode is not used.
|
||||
*
|
||||
* Use {@link BluetoothAdapter#isLeCodedPhySupported} and
|
||||
* {@link BluetoothAdapter#isLe2MPhySupported} to determine if LE Coded PHY or 2M PHY is
|
||||
* supported on this device.
|
||||
*
|
||||
* @param secondaryPhy Secondary advertising physical channel, can only be
|
||||
* one of {@link AdvertisingSetParameters#PHY_LE_1M},
|
||||
* {@link AdvertisingSetParameters#PHY_LE_2M} or
|
||||
@ -393,6 +400,32 @@ public final class AdvertisingSetParameters implements Parcelable {
|
||||
* Build the {@link AdvertisingSetParameters} object.
|
||||
*/
|
||||
public AdvertisingSetParameters build() {
|
||||
if (isLegacy) {
|
||||
if (isAnonymous) {
|
||||
throw new IllegalArgumentException("Legacy advertising can't be anonymous");
|
||||
}
|
||||
|
||||
if (connectable == true && scannable == false) {
|
||||
throw new IllegalArgumentException(
|
||||
"Legacy advertisement can't be connectable and non-scannable");
|
||||
}
|
||||
|
||||
if (includeTxPower) {
|
||||
throw new IllegalArgumentException(
|
||||
"Legacy advertising can't include TX power level in header");
|
||||
}
|
||||
} else {
|
||||
if (connectable && scannable) {
|
||||
throw new IllegalArgumentException(
|
||||
"Advertising can't be both connectable and scannable");
|
||||
}
|
||||
|
||||
if (isAnonymous && connectable) {
|
||||
throw new IllegalArgumentException(
|
||||
"Advertising can't be both connectable and anonymous");
|
||||
}
|
||||
}
|
||||
|
||||
return new AdvertisingSetParameters(connectable, scannable, isLegacy, isAnonymous,
|
||||
includeTxPower, primaryPhy,
|
||||
secondaryPhy, interval, txPowerLevel);
|
||||
|
@ -50,7 +50,8 @@ public final class BluetoothLeAdvertiser {
|
||||
|
||||
private static final String TAG = "BluetoothLeAdvertiser";
|
||||
|
||||
private static final int MAX_ADVERTISING_DATA_BYTES = 31;
|
||||
private static final int MAX_ADVERTISING_DATA_BYTES = 1650;
|
||||
private static final int MAX_LEGACY_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.
|
||||
@ -116,8 +117,8 @@ public final class BluetoothLeAdvertiser {
|
||||
throw new IllegalArgumentException("callback cannot be null");
|
||||
}
|
||||
boolean isConnectable = settings.isConnectable();
|
||||
if (totalBytes(advertiseData, isConnectable) > MAX_ADVERTISING_DATA_BYTES ||
|
||||
totalBytes(scanResponse, false) > MAX_ADVERTISING_DATA_BYTES) {
|
||||
if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES ||
|
||||
totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
|
||||
postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
|
||||
return;
|
||||
}
|
||||
@ -205,16 +206,26 @@ public final class BluetoothLeAdvertiser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted.
|
||||
* @param scanResponse Scan response associated with the advertisement data.
|
||||
* @param periodicData Periodic advertising data.
|
||||
* @param callback Callback for advertising set.
|
||||
*/
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
|
||||
* advertisement is connectable, three bytes will be added for flags.
|
||||
* @param scanResponse Scan response associated with the advertisement data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
|
||||
* @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
|
||||
* not be started.
|
||||
* @param periodicData Periodic advertising data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
|
||||
* @param callback Callback for advertising set.
|
||||
* @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
|
||||
* size, or unsupported advertising PHY is selected, or when attempt to use
|
||||
* Periodic Advertising feature is made when it's not supported by the
|
||||
* controller.
|
||||
*/
|
||||
public void startAdvertisingSet(AdvertisingSetParameters parameters,
|
||||
AdvertiseData advertiseData, AdvertiseData scanResponse,
|
||||
PeriodicAdvertisingParameters periodicParameters,
|
||||
@ -224,17 +235,27 @@ public final class BluetoothLeAdvertiser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted.
|
||||
* @param scanResponse Scan response associated with the advertisement data.
|
||||
* @param periodicData Periodic advertising data.
|
||||
* @param callback Callback for advertising set.
|
||||
* @param handler thread upon which the callbacks will be invoked.
|
||||
*/
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
|
||||
* advertisement is connectable, three bytes will be added for flags.
|
||||
* @param scanResponse Scan response associated with the advertisement data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
|
||||
* @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
|
||||
* not be started.
|
||||
* @param periodicData Periodic advertising data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
|
||||
* @param callback Callback for advertising set.
|
||||
* @param handler thread upon which the callbacks will be invoked.
|
||||
* @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
|
||||
* size, or unsupported advertising PHY is selected, or when attempt to use
|
||||
* Periodic Advertising feature is made when it's not supported by the
|
||||
* controller.
|
||||
*/
|
||||
public void startAdvertisingSet(AdvertisingSetParameters parameters,
|
||||
AdvertiseData advertiseData, AdvertiseData scanResponse,
|
||||
PeriodicAdvertisingParameters periodicParameters,
|
||||
@ -245,17 +266,27 @@ public final class BluetoothLeAdvertiser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted.
|
||||
* @param scanResponse Scan response associated with the advertisement data.
|
||||
* @param periodicData Periodic advertising data.
|
||||
* @param timeoutMillis Advertising time limit. May not exceed 180000
|
||||
* @param callback Callback for advertising set.
|
||||
*/
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
|
||||
* advertisement is connectable, three bytes will be added for flags.
|
||||
* @param scanResponse Scan response associated with the advertisement data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
|
||||
* @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
|
||||
* not be started.
|
||||
* @param periodicData Periodic advertising data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}.
|
||||
* @param timeoutMillis Advertising time limit. May not exceed 180000
|
||||
* @param callback Callback for advertising set.
|
||||
* @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
|
||||
* size, or unsupported advertising PHY is selected, or when attempt to use
|
||||
* Periodic Advertising feature is made when it's not supported by the
|
||||
* controller.
|
||||
*/
|
||||
public void startAdvertisingSet(AdvertisingSetParameters parameters,
|
||||
AdvertiseData advertiseData, AdvertiseData scanResponse,
|
||||
PeriodicAdvertisingParameters periodicParameters,
|
||||
@ -266,29 +297,81 @@ public final class BluetoothLeAdvertiser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted.
|
||||
* @param scanResponse Scan response associated with the advertisement data.
|
||||
* @param periodicData Periodic advertising data.
|
||||
* @param timeoutMillis Advertising time limit. May not exceed 180000
|
||||
* @param callback Callback for advertising set.
|
||||
* @param handler thread upon which the callbacks will be invoked.
|
||||
*/
|
||||
* Creates a new advertising set. If operation succeed, device will start advertising. This
|
||||
* method returns immediately, the operation status is delivered through
|
||||
* {@code callback.onAdvertisingSetStarted()}.
|
||||
* <p>
|
||||
* @param parameters advertising set parameters.
|
||||
* @param advertiseData Advertisement data to be broadcasted. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}. If the
|
||||
* advertisement is connectable, three bytes will be added for flags.
|
||||
* @param scanResponse Scan response associated with the advertisement data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
|
||||
* @param periodicParameters periodic advertisng parameters. If null, periodic advertising will
|
||||
* not be started.
|
||||
* @param periodicData Periodic advertising data. Size must not exceed
|
||||
* {@link BluetoothAdapter#getLeMaximumAdvertisingDataLength}
|
||||
* @param timeoutMillis Advertising time limit. May not exceed 180000
|
||||
* @param callback Callback for advertising set.
|
||||
* @param handler thread upon which the callbacks will be invoked.
|
||||
* @throws IllegalArgumentException when any of the data parameter exceed the maximum allowable
|
||||
* size, or unsupported advertising PHY is selected, or when attempt to use
|
||||
* Periodic Advertising feature is made when it's not supported by the
|
||||
* controller.
|
||||
*/
|
||||
public void startAdvertisingSet(AdvertisingSetParameters parameters,
|
||||
AdvertiseData advertiseData, AdvertiseData scanResponse,
|
||||
PeriodicAdvertisingParameters periodicParameters,
|
||||
AdvertiseData periodicData, int timeoutMillis,
|
||||
AdvertisingSetCallback callback, Handler handler) {
|
||||
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
|
||||
|
||||
if (callback == null) {
|
||||
throw new IllegalArgumentException("callback cannot be null");
|
||||
}
|
||||
|
||||
boolean isConnectable = parameters.isConnectable();
|
||||
if (parameters.isLegacy()) {
|
||||
if (totalBytes(advertiseData, isConnectable) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
|
||||
throw new IllegalArgumentException("Legacy advertising data too big");
|
||||
}
|
||||
|
||||
if (totalBytes(scanResponse, false) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
|
||||
throw new IllegalArgumentException("Legacy scan response data too big");
|
||||
}
|
||||
} else {
|
||||
boolean supportCodedPhy = mBluetoothAdapter.isLeCodedPhySupported();
|
||||
boolean support2MPhy = mBluetoothAdapter.isLe2MPhySupported();
|
||||
int pphy = parameters.getPrimaryPhy();
|
||||
int sphy = parameters.getSecondaryPhy();
|
||||
if (pphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy) {
|
||||
throw new IllegalArgumentException("Unsupported primary PHY selected");
|
||||
}
|
||||
|
||||
if ((sphy == AdvertisingSetParameters.PHY_LE_CODED && !supportCodedPhy)
|
||||
|| (sphy == AdvertisingSetParameters.PHY_LE_2M && !support2MPhy)) {
|
||||
throw new IllegalArgumentException("Unsupported secondary PHY selected");
|
||||
}
|
||||
|
||||
int maxData = mBluetoothAdapter.getLeMaximumAdvertisingDataLength();
|
||||
if (totalBytes(advertiseData, isConnectable) > maxData) {
|
||||
throw new IllegalArgumentException("Advertising data too big");
|
||||
}
|
||||
|
||||
if (totalBytes(scanResponse, false) > maxData) {
|
||||
throw new IllegalArgumentException("Scan response data too big");
|
||||
}
|
||||
|
||||
if (totalBytes(periodicData, false) > maxData) {
|
||||
throw new IllegalArgumentException("Periodic advertising data too big");
|
||||
}
|
||||
|
||||
boolean supportPeriodic = mBluetoothAdapter.isLePeriodicAdvertisingSupported();
|
||||
if (periodicParameters != null && periodicParameters.getEnable() && !supportPeriodic) {
|
||||
throw new IllegalArgumentException(
|
||||
"Controller does not support LE Periodic Advertising");
|
||||
}
|
||||
}
|
||||
|
||||
IBluetoothGatt gatt;
|
||||
try {
|
||||
gatt = mBluetoothManager.getBluetoothGatt();
|
||||
|
Reference in New Issue
Block a user