Onfound onlost feature.
Change-Id: I5475cb21183abab8cf04af486ff7692396801b92 Signed-off-by: Prerepa Viswanadham <dham@google.com>
This commit is contained in:
@ -997,6 +997,24 @@ public final class BluetoothAdapter {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* Return the record of {@link BluetoothActivityEnergyInfo} object that
|
||||||
* has the activity and energy info. This can be used to ascertain what
|
* has the activity and energy info. This can be used to ascertain what
|
||||||
|
@ -98,6 +98,7 @@ interface IBluetooth
|
|||||||
boolean isActivityAndEnergyReportingSupported();
|
boolean isActivityAndEnergyReportingSupported();
|
||||||
void getActivityEnergyInfoFromController();
|
void getActivityEnergyInfoFromController();
|
||||||
BluetoothActivityEnergyInfo reportActivityInfo();
|
BluetoothActivityEnergyInfo reportActivityInfo();
|
||||||
|
int numOfHwTrackFiltersAvailable();
|
||||||
|
|
||||||
// for dumpsys support
|
// for dumpsys support
|
||||||
String dump();
|
String dump();
|
||||||
|
@ -128,6 +128,16 @@ public final class BluetoothLeScanner {
|
|||||||
ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
|
ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
|
||||||
return;
|
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,
|
BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
|
||||||
settings, callback, resultStorages);
|
settings, callback, resultStorages);
|
||||||
wrapper.startRegisteration();
|
wrapper.startRegisteration();
|
||||||
@ -394,4 +404,33 @@ public final class BluetoothLeScanner {
|
|||||||
}
|
}
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,17 @@ public abstract class ScanCallback {
|
|||||||
*/
|
*/
|
||||||
public static final int SCAN_FAILED_FEATURE_UNSUPPORTED = 4;
|
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.
|
* Callback when a BLE advertisement has been found.
|
||||||
*
|
*
|
||||||
* @param callbackType Determines how this callback was triggered. Currently could only be
|
* @param callbackType Determines how this callback was triggered. Could be of
|
||||||
* {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}.
|
* {@link ScanSettings#CALLBACK_TYPE_ALL_MATCHES}
|
||||||
* @param result A Bluetooth LE scan result.
|
* @param result A Bluetooth LE scan result.
|
||||||
*/
|
*/
|
||||||
public void onScanResult(int callbackType, ScanResult result) {
|
public void onScanResult(int callbackType, ScanResult result) {
|
||||||
|
@ -67,6 +67,8 @@ public final class ScanFilter implements Parcelable {
|
|||||||
private final byte[] mManufacturerData;
|
private final byte[] mManufacturerData;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final byte[] mManufacturerDataMask;
|
private final byte[] mManufacturerDataMask;
|
||||||
|
private static final ScanFilter EMPTY = new ScanFilter.Builder().build() ;
|
||||||
|
|
||||||
|
|
||||||
private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
|
private ScanFilter(String name, String deviceAddress, ParcelUuid uuid,
|
||||||
ParcelUuid uuidMask, ParcelUuid serviceDataUuid,
|
ParcelUuid uuidMask, ParcelUuid serviceDataUuid,
|
||||||
@ -409,6 +411,14 @@ public final class ScanFilter implements Parcelable {
|
|||||||
Objects.equals(mServiceUuidMask, other.mServiceUuidMask);
|
Objects.equals(mServiceUuidMask, other.mServiceUuidMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the scanfilter is empty
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public boolean isAllFieldsEmpty() {
|
||||||
|
return EMPTY.equals(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builder class for {@link ScanFilter}.
|
* Builder class for {@link ScanFilter}.
|
||||||
*/
|
*/
|
||||||
|
@ -59,7 +59,6 @@ public final class ScanSettings implements Parcelable {
|
|||||||
/**
|
/**
|
||||||
* A result callback is only triggered for the first advertisement packet received that matches
|
* A result callback is only triggered for the first advertisement packet received that matches
|
||||||
* the filter criteria.
|
* the filter criteria.
|
||||||
*
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@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
|
* Receive a callback when advertisements are no longer received from a device that has been
|
||||||
* previously reported by a first match callback.
|
* previously reported by a first match callback.
|
||||||
*
|
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@SystemApi
|
@SystemApi
|
||||||
public static final int CALLBACK_TYPE_MATCH_LOST = 4;
|
public static final int CALLBACK_TYPE_MATCH_LOST = 4;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request full scan results which contain the device, rssi, advertising data, scan response as
|
* Determines how many advertisements to match per filter, as this is scarce hw resource
|
||||||
* well as the scan timestamp.
|
*/
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* @hide
|
||||||
*/
|
*/
|
||||||
@ -106,6 +143,10 @@ public final class ScanSettings implements Parcelable {
|
|||||||
// Time of delay for reporting the scan result
|
// Time of delay for reporting the scan result
|
||||||
private long mReportDelayMillis;
|
private long mReportDelayMillis;
|
||||||
|
|
||||||
|
private int mMatchMode;
|
||||||
|
|
||||||
|
private int mNumOfMatchesPerFilter;
|
||||||
|
|
||||||
public int getScanMode() {
|
public int getScanMode() {
|
||||||
return mScanMode;
|
return mScanMode;
|
||||||
}
|
}
|
||||||
@ -118,6 +159,20 @@ public final class ScanSettings implements Parcelable {
|
|||||||
return mScanResultType;
|
return mScanResultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public int getMatchMode() {
|
||||||
|
return mMatchMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public int getNumOfMatches() {
|
||||||
|
return mNumOfMatchesPerFilter;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns report delay timestamp based on the device clock.
|
* Returns report delay timestamp based on the device clock.
|
||||||
*/
|
*/
|
||||||
@ -126,11 +181,13 @@ public final class ScanSettings implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ScanSettings(int scanMode, int callbackType, int scanResultType,
|
private ScanSettings(int scanMode, int callbackType, int scanResultType,
|
||||||
long reportDelayMillis) {
|
long reportDelayMillis, int matchMode, int numOfMatchesPerFilter) {
|
||||||
mScanMode = scanMode;
|
mScanMode = scanMode;
|
||||||
mCallbackType = callbackType;
|
mCallbackType = callbackType;
|
||||||
mScanResultType = scanResultType;
|
mScanResultType = scanResultType;
|
||||||
mReportDelayMillis = reportDelayMillis;
|
mReportDelayMillis = reportDelayMillis;
|
||||||
|
mNumOfMatchesPerFilter = numOfMatchesPerFilter;
|
||||||
|
mMatchMode = numOfMatchesPerFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ScanSettings(Parcel in) {
|
private ScanSettings(Parcel in) {
|
||||||
@ -138,6 +195,8 @@ public final class ScanSettings implements Parcelable {
|
|||||||
mCallbackType = in.readInt();
|
mCallbackType = in.readInt();
|
||||||
mScanResultType = in.readInt();
|
mScanResultType = in.readInt();
|
||||||
mReportDelayMillis = in.readLong();
|
mReportDelayMillis = in.readLong();
|
||||||
|
mMatchMode = in.readInt();
|
||||||
|
mNumOfMatchesPerFilter = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -146,6 +205,8 @@ public final class ScanSettings implements Parcelable {
|
|||||||
dest.writeInt(mCallbackType);
|
dest.writeInt(mCallbackType);
|
||||||
dest.writeInt(mScanResultType);
|
dest.writeInt(mScanResultType);
|
||||||
dest.writeLong(mReportDelayMillis);
|
dest.writeLong(mReportDelayMillis);
|
||||||
|
dest.writeInt(mMatchMode);
|
||||||
|
dest.writeInt(mNumOfMatchesPerFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -174,7 +235,8 @@ public final class ScanSettings implements Parcelable {
|
|||||||
private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
|
private int mCallbackType = CALLBACK_TYPE_ALL_MATCHES;
|
||||||
private int mScanResultType = SCAN_RESULT_TYPE_FULL;
|
private int mScanResultType = SCAN_RESULT_TYPE_FULL;
|
||||||
private long mReportDelayMillis = 0;
|
private long mReportDelayMillis = 0;
|
||||||
|
private int mMatchMode = MATCH_MODE_AGGRESSIVE;
|
||||||
|
private int mNumOfMatchesPerFilter = MATCH_NUM_ONE_ADVERTISEMENT;
|
||||||
/**
|
/**
|
||||||
* Set scan mode for Bluetooth LE scan.
|
* Set scan mode for Bluetooth LE scan.
|
||||||
*
|
*
|
||||||
@ -254,12 +316,49 @@ public final class ScanSettings implements Parcelable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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}.
|
* Build {@link ScanSettings}.
|
||||||
*/
|
*/
|
||||||
public ScanSettings build() {
|
public ScanSettings build() {
|
||||||
return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
|
return new ScanSettings(mScanMode, mCallbackType, mScanResultType,
|
||||||
mReportDelayMillis);
|
mReportDelayMillis, mMatchMode, mNumOfMatchesPerFilter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user