diff options
Diffstat (limited to 'core/java/android/bluetooth')
-rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 18 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetooth.aidl | 1 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/BluetoothLeScanner.java | 39 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/ScanCallback.java | 10 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/ScanFilter.java | 10 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/ScanSettings.java | 113 |
6 files changed, 182 insertions, 9 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index edb768d..2b3cf34 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -995,6 +995,24 @@ public final class BluetoothAdapter { } /** + * Return true if hardware has entries available for matching beacons + * + * @return true if there are hw entries available for matching beacons + * @hide + */ + public boolean isHardwareTrackingFiltersAvailable() { + if (getState() != STATE_ON) return false; + try { + synchronized(mManagerCallback) { + if(mService != null) return (mService.numOfHwTrackFiltersAvailable() != 0); + } + } catch (RemoteException e) { + Log.e(TAG, "", e); + } + return false; + } + + /** * Return the record of {@link BluetoothActivityEnergyInfo} object that * has the activity and energy info. This can be used to ascertain what * the controller has been up to, since the last sample. diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index dabb1ce..299f4c8 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -98,6 +98,7 @@ interface IBluetooth boolean isActivityAndEnergyReportingSupported(); void getActivityEnergyInfoFromController(); BluetoothActivityEnergyInfo reportActivityInfo(); + int numOfHwTrackFiltersAvailable(); // for dumpsys support String dump(); diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index 93ea299..73a1907 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -128,6 +128,16 @@ public final class BluetoothLeScanner { ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); return; } + if (!isHardwareResourcesAvailableForScan(settings)) { + postCallbackError(callback, + ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES); + return; + } + if (!isSettingsAndFilterComboAllowed(settings, filters)) { + postCallbackError(callback, + ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED); + return; + } BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, settings, callback, resultStorages); wrapper.startRegisteration(); @@ -394,4 +404,33 @@ public final class BluetoothLeScanner { } return false; } + + private boolean isSettingsAndFilterComboAllowed(ScanSettings settings, + List <ScanFilter> filterList) { + final int callbackType = settings.getCallbackType(); + // If onlost/onfound is requested, a non-empty filter is expected + if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH + | ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) { + if (filterList == null) { + return false; + } + for (ScanFilter filter : filterList) { + if (filter.isAllFieldsEmpty()) { + return false; + } + } + } + return true; + } + + private boolean isHardwareResourcesAvailableForScan(ScanSettings settings) { + final int callbackType = settings.getCallbackType(); + if ((callbackType & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) != 0 + || (callbackType & ScanSettings.CALLBACK_TYPE_MATCH_LOST) != 0) { + // For onlost/onfound, we required hw support be available + return (mBluetoothAdapter.isOffloadedFilteringSupported() && + mBluetoothAdapter.isHardwareTrackingFiltersAvailable()); + } + return true; + } } diff --git a/core/java/android/bluetooth/le/ScanCallback.java b/core/java/android/bluetooth/le/ScanCallback.java index 05782a8..27b96bd 100644 --- a/core/java/android/bluetooth/le/ScanCallback.java +++ b/core/java/android/bluetooth/le/ScanCallback.java @@ -45,10 +45,16 @@ public abstract class ScanCallback { public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4; /** + * Fails to start scan as it is out of hardware resources. + * @hide + */ + public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5; + + /** * Callback when a BLE advertisement has been found. * - * @param callbackType Determines how this callback was triggered. Currently could only be - * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}. + * @param callbackType Determines how this callback was triggered. Could be of + * {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES} * @param result A Bluetooth LE scan result. */ public void onScanResult(int callbackType, ScanResult result) { diff --git a/core/java/android/bluetooth/le/ScanFilter.java b/core/java/android/bluetooth/le/ScanFilter.java index 5025218..92a3817 100644 --- a/core/java/android/bluetooth/le/ScanFilter.java +++ b/core/java/android/bluetooth/le/ScanFilter.java @@ -67,6 +67,8 @@ public final class ScanFilter implements Parcelable { private final byte[] mManufacturerData; @Nullable private final byte[] mManufacturerDataMask; + private static final ScanFilter EMPTY = new ScanFilter.Builder().build() ; + private ScanFilter(String name, String deviceAddress, ParcelUuid uuid, ParcelUuid uuidMask, ParcelUuid serviceDataUuid, @@ -410,6 +412,14 @@ public final class ScanFilter implements Parcelable { } /** + * Checks if the scanfilter is empty + * @hide + */ + public boolean isAllFieldsEmpty() { + return EMPTY.equals(this); + } + + /** * Builder class for {@link ScanFilter}. */ public static final class Builder { diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 0106686..f103cae 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -59,7 +59,6 @@ public final class ScanSettings implements Parcelable { /** * A result callback is only triggered for the first advertisement packet received that matches * the filter criteria. - * * @hide */ @SystemApi @@ -68,15 +67,53 @@ public final class ScanSettings implements Parcelable { /** * Receive a callback when advertisements are no longer received from a device that has been * previously reported by a first match callback. - * * @hide */ @SystemApi public static final int CALLBACK_TYPE_MATCH_LOST = 4; + + /** + * Determines how many advertisements to match per filter, as this is scarce hw resource + */ + /** + * Match one advertisement per filter + * @hide + */ + public static final int MATCH_NUM_ONE_ADVERTISEMENT = 1; + + /** + * Match few advertisement per filter, depends on current capability and availibility of + * the resources in hw + * @hide + */ + public static final int MATCH_NUM_FEW_ADVERTISEMENT = 2; + + /** + * Match as many advertisement per filter as hw could allow, depends on current + * capability and availibility of the resources in hw + * @hide + */ + public static final int MATCH_NUM_MAX_ADVERTISEMENT = 3; + + + /** + * In Aggressive mode, hw will determine a match sooner even with feeble signal strength + * and few number of sightings/match in a duration. + * @hide + */ + public static final int MATCH_MODE_AGGRESSIVE = 1; + /** - * Request full scan results which contain the device, rssi, advertising data, scan response as - * well as the scan timestamp. + * For sticky mode, higher threshold of signal strength and sightings is required + * before reporting by hw + * @hide + */ + public static final int MATCH_MODE_STICKY = 2; + + /** + * Request full scan results which contain the device, rssi, advertising data, scan response + * as well as the scan timestamp. * * @hide */ @@ -106,6 +143,10 @@ public final class ScanSettings implements Parcelable { // Time of delay for reporting the scan result private long mReportDelayMillis; + private int mMatchMode; + + private int mNumOfMatchesPerFilter; + public int getScanMode() { return mScanMode; } @@ -119,6 +160,20 @@ public final class ScanSettings implements Parcelable { } /** + * @hide + */ + public int getMatchMode() { + return mMatchMode; + } + + /** + * @hide + */ + public int getNumOfMatches() { + return mNumOfMatchesPerFilter; + } + + /** * Returns report delay timestamp based on the device clock. */ public long getReportDelayMillis() { @@ -126,11 +181,13 @@ public final class ScanSettings implements Parcelable { } private ScanSettings(int scanMode, int callbackType, int scanResultType, - long reportDelayMillis) { + long reportDelayMillis, int matchMode, int numOfMatchesPerFilter) { mScanMode = scanMode; mCallbackType = callbackType; mScanResultType = scanResultType; mReportDelayMillis = reportDelayMillis; + mNumOfMatchesPerFilter = numOfMatchesPerFilter; + mMatchMode = numOfMatchesPerFilter; } private ScanSettings(Parcel in) { @@ -138,6 +195,8 @@ public final class ScanSettings implements Parcelable { mCallbackType = in.readInt(); mScanResultType = in.readInt(); mReportDelayMillis = in.readLong(); + mMatchMode = in.readInt(); + mNumOfMatchesPerFilter = in.readInt(); } @Override @@ -146,6 +205,8 @@ public final class ScanSettings implements Parcelable { dest.writeInt(mCallbackType); dest.writeInt(mScanResultType); dest.writeLong(mReportDelayMillis); + dest.writeInt(mMatchMode); + dest.writeInt(mNumOfMatchesPerFilter); } @Override @@ -174,7 +235,8 @@ public final class ScanSettings implements Parcelable { private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES; private int mScanResultType = SCAN_RESULT_TYPE_FULL; private long mReportDelayMillis = 0; - + private int mMatchMode = MATCH_MODE_AGGRESSIVE; + private int mNumOfMatchesPerFilter = MATCH_NUM_ONE_ADVERTISEMENT; /** * Set scan mode for Bluetooth LE scan. * @@ -255,11 +317,48 @@ public final class ScanSettings implements Parcelable { } /** + * Set the number of matches for Bluetooth LE scan filters hardware match + * + * @param numOfMatches The num of matches can be one of + * {@link ScanSettings#MATCH_NUM_ONE_ADVERTISEMENT} or + * {@link ScanSettings#MATCH_NUM_FEW_ADVERTISEMENT} or + * {@link ScanSettings#MATCH_NUM_MAX_ADVERTISEMENT} + * @throws IllegalArgumentException If the {@code matchMode} is invalid. + * @hide + */ + public Builder setNumOfMatches(int numOfMatches) { + if (numOfMatches < MATCH_NUM_ONE_ADVERTISEMENT + || numOfMatches > MATCH_NUM_MAX_ADVERTISEMENT) { + throw new IllegalArgumentException("invalid numOfMatches " + numOfMatches); + } + mNumOfMatchesPerFilter = numOfMatches; + return this; + } + + /** + * Set match mode for Bluetooth LE scan filters hardware match + * + * @param matchMode The match mode can be one of + * {@link ScanSettings#MATCH_MODE_AGGRESSIVE} or + * {@link ScanSettings#MATCH_MODE_STICKY} + * @throws IllegalArgumentException If the {@code matchMode} is invalid. + * @hide + */ + public Builder setMatchMode(int matchMode) { + if (matchMode < MATCH_MODE_AGGRESSIVE + || matchMode > MATCH_MODE_STICKY) { + throw new IllegalArgumentException("invalid matchMode " + matchMode); + } + mMatchMode = matchMode; + return this; + } + + /** * Build {@link ScanSettings}. */ public ScanSettings build() { return new ScanSettings(mScanMode, mCallbackType, mScanResultType, - mReportDelayMillis); + mReportDelayMillis, mMatchMode, mNumOfMatchesPerFilter); } } } |