diff options
author | Jakub Pawlowski <jpawlowski@google.com> | 2017-01-10 06:15:54 -0800 |
---|---|---|
committer | Jakub Pawlowski <jpawlowski@google.com> | 2017-03-08 19:04:49 +0000 |
commit | a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9 (patch) | |
tree | 3bd35731d8a36b738fb06452c160842458e576e7 | |
parent | 104eeedb42d8de557056c0f70018c5d4fa8f6540 (diff) | |
download | base-a9d1a32e5e51ebc3c141370c9d5045c6c938aaf9.tar.gz |
Bluetooth 5 Advertising API
Test: manual
Bug: 30622771
Change-Id: Id6856e6110872ec50ff1af54ddc75c0104a6459c
(cherry picked from commit 5324a14cf490656269ef862d7f8f6b139a21c0e6)
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | api/current.txt | 92 | ||||
-rw-r--r-- | api/system-current.txt | 92 | ||||
-rw-r--r-- | api/test-current.txt | 92 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetoothGatt.aidl | 17 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/AdvertisingSet.java | 162 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/AdvertisingSetCallback.java | 144 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/AdvertisingSetParameters.aidl | 19 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/AdvertisingSetParameters.java | 409 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/BluetoothLeAdvertiser.java | 194 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl | 32 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/PeriodicAdvertisingParameters.aidl | 19 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java | 134 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/ScanResult.java | 2 |
14 files changed, 1408 insertions, 1 deletions
diff --git a/Android.mk b/Android.mk index f7e8310fc0fa..a07fd016eab8 100644 --- a/Android.mk +++ b/Android.mk @@ -131,6 +131,7 @@ LOCAL_SRC_FILES += \ core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl \ core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl \ core/java/android/bluetooth/le/IAdvertiserCallback.aidl \ + core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl \ core/java/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl \ core/java/android/bluetooth/le/IScannerCallback.aidl \ core/java/android/content/IClipboard.aidl \ diff --git a/api/current.txt b/api/current.txt index c8917ae2376e..b69cf01fb8ba 100644 --- a/api/current.txt +++ b/api/current.txt @@ -7504,10 +7504,85 @@ package android.bluetooth.le { method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int); } + public final class AdvertisingSet { + method public void enableAdvertising(boolean); + method public void periodicAdvertisingEnable(boolean); + method public void setAdvertisingData(android.bluetooth.le.AdvertiseData); + method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters); + method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData); + method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters); + method public void setScanResponseData(android.bluetooth.le.AdvertiseData); + } + + public abstract class AdvertisingSetCallback { + ctor public AdvertisingSetCallback(); + method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int); + method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet); + method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); + method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int); + method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int); + method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int); + field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3 + field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1 + field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5 + field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4 + field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2 + field public static final int ADVERTISE_SUCCESS = 0; // 0x0 + } + + public final class AdvertisingSetParameters implements android.os.Parcelable { + method public int describeContents(); + method public int getInterval(); + method public int getPrimaryPhy(); + method public int getSecondaryPhy(); + method public int getTimeout(); + method public int getTxPowerLevel(); + method public boolean includeTxPower(); + method public boolean isAnonymous(); + method public boolean isConnectable(); + method public boolean isLegacy(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR; + field public static final int INTERVAL_HIGH = 160; // 0xa0 + field public static final int INTERVAL_LOW = 1600; // 0x640 + field public static final int INTERVAL_MAX = 16777215; // 0xffffff + field public static final int INTERVAL_MEDIUM = 400; // 0x190 + field public static final int INTERVAL_MIN = 160; // 0xa0 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_2M = 2; // 0x2 + field public static final int PHY_LE_CODED = 3; // 0x3 + field public static final int TX_POWER_HIGH = 1; // 0x1 + field public static final int TX_POWER_LOW = -15; // 0xfffffff1 + field public static final int TX_POWER_MAX = 1; // 0x1 + field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9 + field public static final int TX_POWER_MIN = -127; // 0xffffff81 + field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb + } + + public static final class AdvertisingSetParameters.Builder { + ctor public AdvertisingSetParameters.Builder(); + method public android.bluetooth.le.AdvertisingSetParameters build(); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int); + } + public final class BluetoothLeAdvertiser { method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); + method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback); + method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler); method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback); + method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback); } public final class BluetoothLeScanner { @@ -7532,6 +7607,23 @@ package android.bluetooth.le { method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback); } + public final class PeriodicAdvertisingParameters implements android.os.Parcelable { + method public int describeContents(); + method public boolean getEnable(); + method public boolean getIncludeTxPower(); + method public int getInterval(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR; + } + + public static final class PeriodicAdvertisingParameters.Builder { + ctor public PeriodicAdvertisingParameters.Builder(); + method public android.bluetooth.le.PeriodicAdvertisingParameters build(); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int); + } + public final class PeriodicAdvertisingReport implements android.os.Parcelable { ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord); method public int describeContents(); diff --git a/api/system-current.txt b/api/system-current.txt index 28dfbe8a109d..914cda1a68d4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -7808,10 +7808,85 @@ package android.bluetooth.le { method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int); } + public final class AdvertisingSet { + method public void enableAdvertising(boolean); + method public void periodicAdvertisingEnable(boolean); + method public void setAdvertisingData(android.bluetooth.le.AdvertiseData); + method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters); + method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData); + method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters); + method public void setScanResponseData(android.bluetooth.le.AdvertiseData); + } + + public abstract class AdvertisingSetCallback { + ctor public AdvertisingSetCallback(); + method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int); + method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet); + method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); + method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int); + method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int); + method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int); + field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3 + field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1 + field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5 + field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4 + field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2 + field public static final int ADVERTISE_SUCCESS = 0; // 0x0 + } + + public final class AdvertisingSetParameters implements android.os.Parcelable { + method public int describeContents(); + method public int getInterval(); + method public int getPrimaryPhy(); + method public int getSecondaryPhy(); + method public int getTimeout(); + method public int getTxPowerLevel(); + method public boolean includeTxPower(); + method public boolean isAnonymous(); + method public boolean isConnectable(); + method public boolean isLegacy(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR; + field public static final int INTERVAL_HIGH = 160; // 0xa0 + field public static final int INTERVAL_LOW = 1600; // 0x640 + field public static final int INTERVAL_MAX = 16777215; // 0xffffff + field public static final int INTERVAL_MEDIUM = 400; // 0x190 + field public static final int INTERVAL_MIN = 160; // 0xa0 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_2M = 2; // 0x2 + field public static final int PHY_LE_CODED = 3; // 0x3 + field public static final int TX_POWER_HIGH = 1; // 0x1 + field public static final int TX_POWER_LOW = -15; // 0xfffffff1 + field public static final int TX_POWER_MAX = 1; // 0x1 + field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9 + field public static final int TX_POWER_MIN = -127; // 0xffffff81 + field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb + } + + public static final class AdvertisingSetParameters.Builder { + ctor public AdvertisingSetParameters.Builder(); + method public android.bluetooth.le.AdvertisingSetParameters build(); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int); + } + public final class BluetoothLeAdvertiser { method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); + method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback); + method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler); method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback); + method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback); } public final class BluetoothLeScanner { @@ -7839,6 +7914,23 @@ package android.bluetooth.le { method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback); } + public final class PeriodicAdvertisingParameters implements android.os.Parcelable { + method public int describeContents(); + method public boolean getEnable(); + method public boolean getIncludeTxPower(); + method public int getInterval(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR; + } + + public static final class PeriodicAdvertisingParameters.Builder { + ctor public PeriodicAdvertisingParameters.Builder(); + method public android.bluetooth.le.PeriodicAdvertisingParameters build(); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int); + } + public final class PeriodicAdvertisingReport implements android.os.Parcelable { ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord); method public int describeContents(); diff --git a/api/test-current.txt b/api/test-current.txt index cfdbf370de4d..317328d6e57d 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -7513,10 +7513,85 @@ package android.bluetooth.le { method public android.bluetooth.le.AdvertiseSettings.Builder setTxPowerLevel(int); } + public final class AdvertisingSet { + method public void enableAdvertising(boolean); + method public void periodicAdvertisingEnable(boolean); + method public void setAdvertisingData(android.bluetooth.le.AdvertiseData); + method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters); + method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData); + method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters); + method public void setScanResponseData(android.bluetooth.le.AdvertiseData); + } + + public abstract class AdvertisingSetCallback { + ctor public AdvertisingSetCallback(); + method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int); + method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int); + method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet); + method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int); + method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int); + method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int); + method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int); + field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3 + field public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; // 0x1 + field public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; // 0x5 + field public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; // 0x4 + field public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; // 0x2 + field public static final int ADVERTISE_SUCCESS = 0; // 0x0 + } + + public final class AdvertisingSetParameters implements android.os.Parcelable { + method public int describeContents(); + method public int getInterval(); + method public int getPrimaryPhy(); + method public int getSecondaryPhy(); + method public int getTimeout(); + method public int getTxPowerLevel(); + method public boolean includeTxPower(); + method public boolean isAnonymous(); + method public boolean isConnectable(); + method public boolean isLegacy(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR; + field public static final int INTERVAL_HIGH = 160; // 0xa0 + field public static final int INTERVAL_LOW = 1600; // 0x640 + field public static final int INTERVAL_MAX = 16777215; // 0xffffff + field public static final int INTERVAL_MEDIUM = 400; // 0x190 + field public static final int INTERVAL_MIN = 160; // 0xa0 + field public static final int PHY_LE_1M = 1; // 0x1 + field public static final int PHY_LE_2M = 2; // 0x2 + field public static final int PHY_LE_CODED = 3; // 0x3 + field public static final int TX_POWER_HIGH = 1; // 0x1 + field public static final int TX_POWER_LOW = -15; // 0xfffffff1 + field public static final int TX_POWER_MAX = 1; // 0x1 + field public static final int TX_POWER_MEDIUM = -7; // 0xfffffff9 + field public static final int TX_POWER_MIN = -127; // 0xffffff81 + field public static final int TX_POWER_ULTRA_LOW = -21; // 0xffffffeb + } + + public static final class AdvertisingSetParameters.Builder { + ctor public AdvertisingSetParameters.Builder(); + method public android.bluetooth.le.AdvertisingSetParameters build(); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int); + method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int); + } + public final class BluetoothLeAdvertiser { method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback); + method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback); + method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler); method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback); + method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback); } public final class BluetoothLeScanner { @@ -7541,6 +7616,23 @@ package android.bluetooth.le { method public void unregisterSync(android.bluetooth.le.PeriodicAdvertisingCallback); } + public final class PeriodicAdvertisingParameters implements android.os.Parcelable { + method public int describeContents(); + method public boolean getEnable(); + method public boolean getIncludeTxPower(); + method public int getInterval(); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator<android.bluetooth.le.PeriodicAdvertisingParameters> CREATOR; + } + + public static final class PeriodicAdvertisingParameters.Builder { + ctor public PeriodicAdvertisingParameters.Builder(); + method public android.bluetooth.le.PeriodicAdvertisingParameters build(); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setEnable(boolean); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setIncludeTxPower(boolean); + method public android.bluetooth.le.PeriodicAdvertisingParameters.Builder setInterval(int); + } + public final class PeriodicAdvertisingReport implements android.os.Parcelable { ctor public PeriodicAdvertisingReport(int, int, int, int, android.bluetooth.le.ScanRecord); method public int describeContents(); diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index 5282e9fceba5..33fedc718980 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -20,6 +20,8 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGattService; import android.bluetooth.le.AdvertiseSettings; import android.bluetooth.le.AdvertiseData; +import android.bluetooth.le.AdvertisingSetParameters; +import android.bluetooth.le.PeriodicAdvertisingParameters; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; @@ -30,6 +32,7 @@ import android.os.WorkSource; import android.bluetooth.IBluetoothGattCallbackExt; import android.bluetooth.IBluetoothGattServerCallbackExt; import android.bluetooth.le.IAdvertiserCallback; +import android.bluetooth.le.IAdvertisingSetCallback; import android.bluetooth.le.IPeriodicAdvertisingCallback; import android.bluetooth.le.IScannerCallback; @@ -55,10 +58,24 @@ interface IBluetoothGatt { in AdvertiseSettings settings); void stopMultiAdvertising(in int advertiserId); + void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData, + in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters, + in AdvertiseData periodicData, in IAdvertisingSetCallback callback); + void stopAdvertisingSet(in IAdvertisingSetCallback callback); + + void enableAdverisingSet(in int advertiserId, in boolean enable); + void setAdvertisingData(in int advertiserId, in AdvertiseData data); + void setScanResponseData(in int advertiserId, in AdvertiseData data); + void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters); + void setPeriodicAdvertisingParameters(in int advertiserId, in PeriodicAdvertisingParameters parameters); + void setPeriodicAdvertisingData(in int advertiserId, in AdvertiseData data); + void periodicAdvertisingEnable(in int advertiserId, in boolean enable); + void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback); void unregisterSync(in IPeriodicAdvertisingCallback callback); void registerClient(in ParcelUuid appId, in IBluetoothGattCallbackExt callback); + void unregisterClient(in int clientIf); void clientConnect(in int clientIf, in String address, in boolean isDirect, in int transport, in int phy); void clientDisconnect(in int clientIf, in String address); diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java new file mode 100644 index 000000000000..1524022b1f0f --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertisingSet.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2017 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.bluetooth.IBluetoothGatt; +import android.bluetooth.IBluetoothManager; +import android.bluetooth.le.IAdvertisingSetCallback; +import android.os.RemoteException; +import android.util.Log; + +/** + * This class provides a way to control single Bluetooth LE advertising instance. + * <p> + * To get an instance of {@link AdvertisingSet}, call the + * {@link BluetoothLeAdvertiser#startAdvertisingSet} method. + * <p> + * <b>Note:</b> Most of the methods here require {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * permission. + * + * @see AdvertiseData + */ +public final class AdvertisingSet { + private static final String TAG = "AdvertisingSet"; + + private final IBluetoothGatt gatt; + private int advertiserId; + + /* package */ AdvertisingSet(int advertiserId, + IBluetoothManager bluetoothManager) { + this.advertiserId = advertiserId; + + try { + this.gatt = bluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + throw new IllegalStateException("Failed to get Bluetooth"); + } + } + + /* package */ void setAdvertiserId(int advertiserId) { + this.advertiserId = advertiserId; + } + + /** + * Enables Advertising. This method returns immediately, the operation status is + * delivered + * through {@code callback.onAdvertisingEnabled()}. + * <p> + * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} + * + */ + public void enableAdvertising(boolean enable) { + try { + gatt.enableAdverisingSet(this.advertiserId, enable); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * Set/update data being Advertised. 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.onAdvertisingDataSet()}. + * <p> + * Advertising data must be empty if non-legacy scannable advertising is used. + */ + public void setAdvertisingData(AdvertiseData data) { + try { + gatt.setAdvertisingData(this.advertiserId, data); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * 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()}. + */ + public void setScanResponseData(AdvertiseData data) { + try { + gatt.setScanResponseData(this.advertiserId, data); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * 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}. + */ + public void setAdvertisingParameters(AdvertisingSetParameters parameters) { + try { + gatt.setAdvertisingParameters(this.advertiserId, parameters); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * Update periodic advertising parameters associated with this set. Must be called when + * periodic advertising is not enabled. This method returns immediately, the operation + * status is delivered through {@code callback.onPeriodicAdvertisingParametersUpdated()}. + */ + public void setPeriodicAdvertisingParameters(PeriodicAdvertisingParameters parameters) { + try { + gatt.setPeriodicAdvertisingParameters(this.advertiserId, parameters); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * Used to set periodic advertising data, must be called after setPeriodicAdvertisingParameters, + * or after advertising was started with periodic advertising data set. This method returns + * immediately, the operation status is delivered through + * {@code callback.onPeriodicAdvertisingDataSet()}. + */ + public void setPeriodicAdvertisingData(AdvertiseData data) { + try { + gatt.setPeriodicAdvertisingData(this.advertiserId, data); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * Used to enable/disable periodic advertising. This method returns immediately, the operation + * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}. + */ + public void periodicAdvertisingEnable(boolean enable) { + try { + gatt.periodicAdvertisingEnable(this.advertiserId, enable); + } catch (RemoteException e) { + Log.e(TAG, "remote exception - ", e); + } + } + + /** + * Returns advertiserId associated with thsi advertising set. + * + * @hide + */ + public int getAdvertiserId(){ + return advertiserId; + } +}
\ No newline at end of file diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java new file mode 100644 index 000000000000..ceed8d9e3c60 --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2017 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.bluetooth.BluetoothDevice; + +/** + * Bluetooth LE advertising set callbacks, used to deliver advertising operation + * status. + */ +public abstract class AdvertisingSetCallback { + + /** + * The requested operation was successful. + */ + public static final int ADVERTISE_SUCCESS = 0; + + /** + * Failed to start advertising as the advertise data to be broadcasted is too + * large. + */ + public static final int ADVERTISE_FAILED_DATA_TOO_LARGE = 1; + + /** + * Failed to start advertising because no advertising instance is available. + */ + public static final int ADVERTISE_FAILED_TOO_MANY_ADVERTISERS = 2; + + /** + * Failed to start advertising as the advertising is already started. + */ + public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; + + /** + * Operation failed due to an internal error. + */ + public static final int ADVERTISE_FAILED_INTERNAL_ERROR = 4; + + /** + * This feature is not supported on this platform. + */ + public static final int ADVERTISE_FAILED_FEATURE_UNSUPPORTED = 5; + + /** + * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet} + * indicating result of the operation. If status is ADVERTISE_SUCCESS, then advertisingSet + * contains the started set and it is advertising. If error occured, advertisingSet is + * null, and status will be set to proper error code. + * + * @param advertisingSet The advertising set that was started or null if error. + * @param status Status of the operation. + */ + public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int status) {} + + /** + * Callback triggered in response to {@link BluetoothLeAdvertiser#stopAdvertisingSet} + * indicating advertising set is stopped. + * + * @param advertisingSet The advertising set. + */ + public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {} + + /** + * Callback triggered in response to {@link BluetoothLeAdvertiser#startAdvertisingSet} indicating + * result of the operation. If status is ADVERTISE_SUCCESS, then advertising set is advertising. + * + * @param advertisingSet The advertising set. + * @param status Status of the operation. + */ + public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable, int status) {} + + /** + * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating + * result of the operation. If status is ADVERTISE_SUCCESS, then data was changed. + * + * @param advertisingSet The advertising set. + * @param status Status of the operation. + */ + public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {} + + /** + * Callback triggered in response to {@link AdvertisingSet#setAdvertisingData} indicating + * result of the operation. + * + * @param advertisingSet The advertising set. + * @param status Status of the operation. + */ + public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {} + + /** + * Callback triggered in response to {@link AdvertisingSet#setAdvertisingParameters} + * indicating result of the operation. + * + * @param advertisingSet The advertising set. + * @param status Status of the operation. + */ + public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet, + int status) {} + + /** + * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingParameters} + * indicating result of the operation. + * + * @param advertisingSet The advertising set. + * @param status Status of the operation. + */ + public void + onPeriodicAdvertisingParametersUpdated(AdvertisingSet advertisingSet, + int status) {} + + /** + * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingData} + * indicating result of the operation. + * + * @param advertisingSet The advertising set. + * @param status Status of the operation. + */ + public void onPeriodicAdvertisingDataSet(AdvertisingSet advertisingSet, + int status) {} + + /** + * Callback triggered in response to {@link AdvertisingSet#periodicAdvertisingEnable} + * indicating result of the operation. + * + * @param advertisingSet The advertising set. + * @param status Status of the operation. + */ + public void onPeriodicAdvertisingEnable(AdvertisingSet advertisingSet, boolean enable, + int status) {} +}
\ No newline at end of file diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.aidl b/core/java/android/bluetooth/le/AdvertisingSetParameters.aidl new file mode 100644 index 000000000000..39034a001faa --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 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; + +parcelable AdvertisingSetParameters; diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java new file mode 100644 index 000000000000..03a01e171ba4 --- /dev/null +++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java @@ -0,0 +1,409 @@ +/* + * Copyright (C) 2017 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.os.Parcel; +import android.os.Parcelable; + +/** + * The {@link AdvertisingSetParameters} provide a way to adjust advertising + * preferences for each + * Bluetooth LE advertising set. Use {@link AdvertisingSetParameters.Builder} to + * create an + * instance of this class. + */ +public final class AdvertisingSetParameters implements Parcelable { + + /** + * 1M advertiser PHY. + */ + public static final int PHY_LE_1M = 1; + + /** + * 2M advertiser PHY. + */ + public static final int PHY_LE_2M = 2; + + /** + * LE Coded advertiser PHY. + */ + public static final int PHY_LE_CODED = 3; + + /** + * Advertise on low frequency, around every 1000ms. This is the default and + * preferred advertising mode as it consumes the least power. + */ + public static final int INTERVAL_LOW = 1600; + + /** + * Advertise on medium frequency, around every 250ms. This is balanced + * between advertising frequency and power consumption. + */ + public static final int INTERVAL_MEDIUM = 400; + + /** + * Perform high frequency, low latency advertising, around every 100ms. This + * has the highest power consumption and should not be used for continuous + * background advertising. + */ + public static final int INTERVAL_HIGH = 160; + + /** + * Minimum value for advertising interval. + */ + public static final int INTERVAL_MIN = 160; + + /** + * Maximum value for advertising interval. + */ + public static final int INTERVAL_MAX = 16777215; + + /** + * Advertise using the lowest transmission (TX) power level. Low transmission + * power can be used to restrict the visibility range of advertising packets. + */ + public static final int TX_POWER_ULTRA_LOW = -21; + + /** + * Advertise using low TX power level. + */ + public static final int TX_POWER_LOW = -15; + + /** + * Advertise using medium TX power level. + */ + public static final int TX_POWER_MEDIUM = -7; + + /** + * Advertise using high TX power level. This corresponds to largest visibility + * range of the advertising packet. + */ + public static final int TX_POWER_HIGH = 1; + + /** + * Minimum value for TX power. + */ + public static final int TX_POWER_MIN = -127; + + /** + * Maximum value for TX power. + */ + public static final int TX_POWER_MAX = 1; + + /** + * The maximum limited advertisement duration as specified by the Bluetooth + * SIG + */ + private static final int LIMITED_ADVERTISING_MAX_MILLIS = 180 * 1000; + + private final boolean isLegacy; + private final boolean isAnonymous; + private final boolean includeTxPower; + private final int primaryPhy; + private final int secondaryPhy; + private final boolean connectable; + private final int interval; + private final int txPowerLevel; + private final int timeoutMillis; + + private AdvertisingSetParameters(boolean connectable, boolean isLegacy, + boolean isAnonymous, boolean includeTxPower, + int primaryPhy, int secondaryPhy, + int interval, int txPowerLevel, + int timeoutMillis) { + this.connectable = connectable; + this.isLegacy = isLegacy; + this.isAnonymous = isAnonymous; + this.includeTxPower = includeTxPower; + this.primaryPhy = primaryPhy; + this.secondaryPhy = secondaryPhy; + this.interval = interval; + this.txPowerLevel = txPowerLevel; + this.timeoutMillis = timeoutMillis; + } + + private AdvertisingSetParameters(Parcel in) { + connectable = in.readInt() != 0 ? true : false; + isLegacy = in.readInt() != 0 ? true : false; + isAnonymous = in.readInt() != 0 ? true : false; + includeTxPower = in.readInt() != 0 ? true : false; + primaryPhy = in.readInt(); + secondaryPhy = in.readInt(); + interval = in.readInt(); + txPowerLevel = in.readInt(); + timeoutMillis = in.readInt(); + } + + /** + * Returns whether the advertisement will be connectable. + */ + public boolean isConnectable() { return connectable; } + + /** + * Returns whether the legacy advertisement will be used. + */ + public boolean isLegacy() { return isLegacy; } + + /** + * Returns whether the advertisement will be anonymous. + */ + public boolean isAnonymous() { return isAnonymous; } + + /** + * Returns whether the TX Power will be included. + */ + public boolean includeTxPower() { return includeTxPower; } + + /** + * Returns the primary advertising phy. + */ + public int getPrimaryPhy() { return primaryPhy; } + + /** + * Returns the secondary advertising phy. + */ + public int getSecondaryPhy() { return secondaryPhy; } + + /** + * Returns the advertising interval. + */ + public int getInterval() { return interval; } + + /** + * Returns the TX power level for advertising. + */ + public int getTxPowerLevel() { return txPowerLevel; } + + /** + * Returns the advertising time limit in milliseconds. + */ + public int getTimeout() { return timeoutMillis; } + + @Override + public String toString() { + return "AdvertisingSetParameters [connectable=" + connectable + + ", isLegacy=" + isLegacy + + ", isAnonymous=" + isAnonymous + + ", includeTxPower=" + includeTxPower + + ", primaryPhy=" + primaryPhy + + ", secondaryPhy=" + secondaryPhy + + ", interval=" + interval + + ", txPowerLevel=" + txPowerLevel + + ", timeoutMillis=" + timeoutMillis + "]"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(connectable ? 1 : 0); + dest.writeInt(isLegacy ? 1 : 0); + dest.writeInt(isAnonymous ? 1 : 0); + dest.writeInt(includeTxPower ? 1 : 0); + dest.writeInt(primaryPhy); + dest.writeInt(secondaryPhy); + dest.writeInt(interval); + dest.writeInt(txPowerLevel); + dest.writeInt(timeoutMillis); + } + + public static final Parcelable.Creator<AdvertisingSetParameters> CREATOR = + new Creator<AdvertisingSetParameters>() { + @Override + public AdvertisingSetParameters[] newArray(int size) { + return new AdvertisingSetParameters[size]; + } + + @Override + public AdvertisingSetParameters createFromParcel(Parcel in) { + return new AdvertisingSetParameters(in); + } + }; + + /** + * Builder class for {@link AdvertisingSetParameters}. + */ + public static final class Builder { + + private boolean connectable = true; + private boolean isLegacy = false; + private boolean isAnonymous = false; + private boolean includeTxPower = false; + private int primaryPhy = PHY_LE_1M; + private int secondaryPhy = PHY_LE_1M; + private int interval = INTERVAL_LOW; + private int txPowerLevel = TX_POWER_MEDIUM; + private int timeoutMillis = 0; + + /** + * Set whether the advertisement type should be connectable or + * non-connectable. + * Legacy advertisements can be both connectable and scannable. Other + * advertisements can be connectable only if not scannable. + * @param connectable Controls whether the advertisment type will be + * connectable (true) or non-connectable (false). + */ + public Builder setConnectable(boolean connectable) { + this.connectable = connectable; + return this; + } + + /** + * When set to true, advertising set will advertise 4.x Spec compliant + * advertisements. + * + * @param isLegacy wether legacy advertising mode should be used. + */ + public Builder setLegacyMode(boolean isLegacy) { + this.isLegacy = isLegacy; + return this; + } + + /** + * Set wether advertiser address should be ommited from all packets. If this + * mode is used, periodic advertising can't be enabled for this set. + * + * This is used only if legacy mode is not used. + * + * @param isAnonymous wether anonymous advertising should be used. + */ + public Builder setAnonymouus(boolean isAnonymous) { + this.isAnonymous = isAnonymous; + return this; + } + + /** + * Set wether TX power should be included in the extended header. + * + * This is used only if legacy mode is not used. + * + * @param includeTxPower wether TX power should be included in extended + * header + */ + public Builder setIncludeTxPower(boolean includeTxPower) { + this.includeTxPower = includeTxPower; + return this; + } + + /** + * Set the primary physical channel used for this advertising set. + * + * This is used only if legacy mode is not used. + * + * @param primaryPhy Primary advertising physical channel, can only be + * {@link AdvertisingSetParameters#PHY_LE_1M} or + * {@link AdvertisingSetParameters#PHY_LE_CODED}. + * @throws IllegalArgumentException If the primaryPhy is invalid. + */ + public Builder setPrimaryPhy(int primaryPhy) { + if (primaryPhy != PHY_LE_1M && primaryPhy != PHY_LE_CODED) { + throw new IllegalArgumentException("bad primaryPhy " + primaryPhy); + } + this.primaryPhy = primaryPhy; + return this; + } + + /** + * Set the secondary physical channel used for this advertising set. + * + * This is used only if legacy mode is not used. + * + * @param secondaryPhy Secondary advertising physical channel, can only be + * one of {@link AdvertisingSetParameters#PHY_LE_1M}, + * {@link AdvertisingSetParameters#PHY_LE_2M} or + * {@link AdvertisingSetParameters#PHY_LE_CODED}. + * @throws IllegalArgumentException If the secondaryPhy is invalid. + */ + public Builder setSecondaryPhy(int secondaryPhy) { + if (secondaryPhy != PHY_LE_1M && secondaryPhy !=PHY_LE_2M && + secondaryPhy != PHY_LE_CODED) { + throw new IllegalArgumentException("bad secondaryPhy " + secondaryPhy); + } + this.secondaryPhy = secondaryPhy; + return this; + } + + /** + * Set advertising interval. + * + * @param interval Bluetooth LE Advertising interval, in 0.625ms unit. Valid + * range is from 160 (100ms) to 16777215 (10,485.759375 s). + * Recommended values are: + * {@link AdvertisingSetParameters#INTERVAL_LOW}, + * {@link AdvertisingSetParameters#INTERVAL_MEDIUM}, or + * {@link AdvertisingSetParameters#INTERVAL_HIGH}. + * @throws IllegalArgumentException If the interval is invalid. + */ + public Builder setInterval(int interval) { + if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { + throw new IllegalArgumentException("unknown interval " + interval); + } + this.interval = interval; + return this; + } + + /** + * Set the transmission power level for the advertising. + * @param txPowerLevel Transmission power of Bluetooth LE Advertising, in + * dBm. The valid range is [-127, 1] Recommended values are: + * {@link AdvertisingSetParameters#TX_POWER_ULTRA_LOW}, + * {@link AdvertisingSetParameters#TX_POWER_LOW}, + * {@link AdvertisingSetParameters#TX_POWER_MEDIUM}, or + * {@link AdvertisingSetParameters#TX_POWER_HIGH}. + * + * @throws IllegalArgumentException If the {@code txPowerLevel} is invalid. + */ + public Builder setTxPowerLevel(int txPowerLevel) { + if (txPowerLevel < TX_POWER_MIN || txPowerLevel > TX_POWER_MAX) { + throw new IllegalArgumentException("unknown txPowerLevel " + + txPowerLevel); + } + this.txPowerLevel = txPowerLevel; + return this; + } + + /** + * Limit advertising to a given amount of time. + * @param timeoutMillis Advertising time limit. May not exceed 180000 + * milliseconds. A value of 0 will disable the time limit. + * @throws IllegalArgumentException If the provided timeout is over 180000 + * ms. + */ + public Builder setTimeout(int timeoutMillis) { + if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) { + throw new IllegalArgumentException("timeoutMillis invalid (must be 0-" + + LIMITED_ADVERTISING_MAX_MILLIS + + " milliseconds)"); + } + this.timeoutMillis = timeoutMillis; + return this; + } + + /** + * Build the {@link AdvertisingSetParameters} object. + */ + public AdvertisingSetParameters build() { + return new AdvertisingSetParameters(connectable, isLegacy, isAnonymous, + includeTxPower, primaryPhy, + secondaryPhy, interval, txPowerLevel, + timeoutMillis); + } + } +}
\ No newline at end of file diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index 94d03e533dff..e03c9477a6a3 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -62,6 +62,9 @@ public final class BluetoothLeAdvertiser { private BluetoothAdapter mBluetoothAdapter; private final Map<AdvertiseCallback, AdvertiseCallbackWrapper> mLeAdvertisers = new HashMap<AdvertiseCallback, AdvertiseCallbackWrapper>(); + private final Map<AdvertisingSetCallback, IAdvertisingSetCallback> + advertisingSetCallbackWrappers = new HashMap<>(); + private final Map<Integer, AdvertisingSet> advertisingSets = new HashMap<>(); /** * Use BluetoothAdapter.getLeAdvertiser() instead. @@ -156,6 +159,93 @@ 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.onNewAdvertisingSet()}. + * <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. + */ + public void startAdvertisingSet(AdvertisingSetParameters parameters, + AdvertiseData advertiseData, AdvertiseData scanResponse, + PeriodicAdvertisingParameters periodicParameters, + AdvertiseData periodicData, AdvertisingSetCallback callback) { + startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, + periodicData, callback, new Handler(Looper.getMainLooper())); + } + + /** + * Creates a new advertising set. If operation succeed, device will start advertising. This + * method returns immediately, the operation status is delivered through + * {@code callback.onNewAdvertisingSet()}. + * <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. + */ + public void startAdvertisingSet(AdvertisingSetParameters parameters, + AdvertiseData advertiseData, AdvertiseData scanResponse, + PeriodicAdvertisingParameters periodicParameters, + AdvertiseData periodicData, AdvertisingSetCallback callback, + Handler handler) { + BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter); + + if (callback == null) { + throw new IllegalArgumentException("callback cannot be null"); + } + + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get Bluetooth gatt - ", e); + throw new IllegalStateException("Failed to get Bluetooth"); + } + + IAdvertisingSetCallback wrapped = wrap(callback, handler); + advertisingSetCallbackWrappers.put(callback, wrapped); + + try { + gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters, + periodicData, wrapped); + } catch (RemoteException e) { + Log.e(TAG, "Failed to start advertising set - ", e); + throw new IllegalStateException("Failed to start advertising set"); + } + } + + /** + * Used to dispose of a {@link AdvertisingSet} object, obtained with {@link + * BluetoothLeAdvertiser#startAdvertisingSet}. + */ + public void stopAdvertisingSet(AdvertisingSetCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("callback cannot be null"); + } + + IAdvertisingSetCallback wrapped = advertisingSetCallbackWrappers.remove(callback); + if (wrapped == null) { + throw new IllegalArgumentException( + "callback does not represent valid registered callback."); + } + + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + gatt.stopAdvertisingSet(wrapped); + } catch (RemoteException e) { + Log.e(TAG, "Failed to stop advertising - ", e); + throw new IllegalStateException("Failed to stop advertising"); + } + } + + /** * Cleans up advertisers. Should be called when bluetooth is down. * * @hide @@ -219,6 +309,110 @@ public final class BluetoothLeAdvertiser { return array == null ? 0 : array.length; } + IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) { + return new IAdvertisingSetCallback.Stub() { + public void onAdvertisingSetStarted(int advertiserId, int status) { + handler.post(new Runnable() { + @Override + public void run() { + if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) { + callback.onAdvertisingSetStarted(null, status); + advertisingSetCallbackWrappers.remove(callback); + return; + } + + AdvertisingSet advertisingSet = + new AdvertisingSet(advertiserId, mBluetoothManager); + advertisingSets.put(advertiserId, advertisingSet); + callback.onAdvertisingSetStarted(advertisingSet, status); + } + }); + } + + public void onAdvertisingSetStopped(int advertiserId) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onAdvertisingSetStopped(advertisingSet); + advertisingSets.remove(advertiserId); + advertisingSetCallbackWrappers.remove(callback); + } + }); + } + + public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onAdvertisingEnabled(advertisingSet, enabled, status); + } + }); + } + + public void onAdvertisingDataSet(int advertiserId, int status) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onAdvertisingDataSet(advertisingSet, status); + } + }); + } + + public void onScanResponseDataSet(int advertiserId, int status) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onScanResponseDataSet(advertisingSet, status); + } + }); + } + + public void onAdvertisingParametersUpdated(int advertiserId, int status) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onAdvertisingParametersUpdated(advertisingSet, status); + } + }); + } + + public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status); + } + }); + } + + public void onPeriodicAdvertisingDataSet(int advertiserId, int status) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onPeriodicAdvertisingDataSet(advertisingSet, status); + } + }); + } + + public void onPeriodicAdvertisingEnable(int advertiserId, boolean enable, int status) { + handler.post(new Runnable() { + @Override + public void run() { + AdvertisingSet advertisingSet = advertisingSets.get(advertiserId); + callback.onPeriodicAdvertisingEnable(advertisingSet, enable, status); + } + }); + } + }; + } + /** * Bluetooth GATT interface callbacks for advertising. */ diff --git a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl new file mode 100644 index 000000000000..4b0a111fa3d8 --- /dev/null +++ b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2017 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; + +/** + * Callback definitions for interacting with Advertiser + * @hide + */ +oneway interface IAdvertisingSetCallback { + void onAdvertisingSetStarted(in int advertiserId, in int status); + void onAdvertisingSetStopped(in int advertiserId); + void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status); + void onAdvertisingDataSet(in int advertiserId, in int status); + void onScanResponseDataSet(in int advertiserId, in int status); + void onAdvertisingParametersUpdated(in int advertiserId, in int status); + void onPeriodicAdvertisingParametersUpdated(in int advertiserId, in int status); + void onPeriodicAdvertisingDataSet(in int advertiserId, in int status); + void onPeriodicAdvertisingEnable(in int advertiserId, in boolean enable, in int status); +} diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.aidl b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.aidl new file mode 100644 index 000000000000..f4bea22a12f2 --- /dev/null +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 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; + +parcelable PeriodicAdvertisingParameters; diff --git a/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java new file mode 100644 index 000000000000..ebc92bd0bcf8 --- /dev/null +++ b/core/java/android/bluetooth/le/PeriodicAdvertisingParameters.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2017 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.os.Parcel; +import android.os.Parcelable; + +/** + * The {@link PeriodicAdvertisingParameters} provide a way to adjust periodic + * advertising preferences for each Bluetooth LE advertising set. Use {@link + * AdvertisingSetParameters.Builder} to create an instance of this class. + */ +public final class PeriodicAdvertisingParameters implements Parcelable { + + private static final int INTERVAL_MAX = 80; + private static final int INTERVAL_MIN = 65519; + + private final boolean enable; + private final boolean includeTxPower; + private final int interval; + + private PeriodicAdvertisingParameters(boolean enable, boolean includeTxPower, int interval) { + this.enable = enable; + this.includeTxPower = includeTxPower; + this.interval = interval; + } + + private PeriodicAdvertisingParameters(Parcel in) { + enable = in.readInt() != 0 ? true : false; + includeTxPower = in.readInt() != 0 ? true : false; + interval = in.readInt(); + } + + /** + * Returns whether the periodic advertising shall be enabled. + */ + public boolean getEnable() { return enable; } + + /** + * Returns whether the TX Power will be included. + */ + public boolean getIncludeTxPower() { return includeTxPower; } + + /** + * Returns the periodic advertising interval, in 1.25ms unit. + * Valid values are from 80 (100ms) to 65519 (81.89875s). + */ + public int getInterval() { return interval; } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(enable ? 1 : 0); + dest.writeInt(includeTxPower ? 1 : 0); + dest.writeInt(interval); + } + + public static final Parcelable + .Creator<PeriodicAdvertisingParameters> CREATOR = + new Creator<PeriodicAdvertisingParameters>() { + @Override + public PeriodicAdvertisingParameters[] newArray(int size) { + return new PeriodicAdvertisingParameters[size]; + } + + @Override + public PeriodicAdvertisingParameters createFromParcel(Parcel in) { + return new PeriodicAdvertisingParameters(in); + } + }; + + public static final class Builder { + private boolean includeTxPower = false; + private boolean enable = false; + private int interval = INTERVAL_MAX; + + /** + * Set wether the Periodic Advertising should be enabled for this set. + */ + public Builder setEnable(boolean enable) { + this.enable = enable; + return this; + } + + /** + * Whether the transmission power level should be included in the periodic + * packet. + */ + public Builder setIncludeTxPower(boolean includeTxPower) { + this.includeTxPower = includeTxPower; + return this; + } + + /** + * Set advertising interval for periodic advertising, in 1.25ms unit. + * Valid values are from 80 (100ms) to 65519 (81.89875s). + * Value from range [interval, interval+20ms] will be picked as the actual value. + * @throws IllegalArgumentException If the interval is invalid. + */ + public Builder setInterval(int interval) { + if (interval < INTERVAL_MIN || interval > INTERVAL_MAX) { + throw new IllegalArgumentException("Invalid interval (must be " + INTERVAL_MIN + + "-" + INTERVAL_MAX + ")"); + } + this.interval = interval; + return this; + } + + /** + * Build the {@link AdvertisingSetParameters} object. + */ + public PeriodicAdvertisingParameters build() { + return new PeriodicAdvertisingParameters(enable, includeTxPower, interval); + } + } +} diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java index f92357b59c7d..583ddd20fd7f 100644 --- a/core/java/android/bluetooth/le/ScanResult.java +++ b/core/java/android/bluetooth/le/ScanResult.java @@ -214,7 +214,7 @@ public final class ScanResult implements Parcelable { } /** - * Returns the received signal strength in dBm. The valid range is [-127, 127]. + * Returns the received signal strength in dBm. The valid range is [-127, 126]. */ public int getRssi() { return mRssi; |