Merge "BLE scan API using PendingIntent" into oc-dev

This commit is contained in:
TreeHugger Robot
2017-04-15 01:34:03 +00:00
committed by Android (Google) Code Review
6 changed files with 120 additions and 25 deletions

View File

@@ -8078,7 +8078,12 @@ package android.bluetooth.le {
method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
method public void startScan(android.bluetooth.le.ScanCallback);
method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
method public void stopScan(android.bluetooth.le.ScanCallback);
method public void stopScan(android.app.PendingIntent);
field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
}
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {

View File

@@ -8550,10 +8550,15 @@ package android.bluetooth.le {
method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
method public void startScan(android.bluetooth.le.ScanCallback);
method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
method public void startScanFromSource(android.os.WorkSource, android.bluetooth.le.ScanCallback);
method public void startScanFromSource(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.os.WorkSource, android.bluetooth.le.ScanCallback);
method public void startTruncatedScan(java.util.List<android.bluetooth.le.TruncatedFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
method public void stopScan(android.bluetooth.le.ScanCallback);
method public void stopScan(android.app.PendingIntent);
field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
}
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {

View File

@@ -8109,7 +8109,12 @@ package android.bluetooth.le {
method public void flushPendingScanResults(android.bluetooth.le.ScanCallback);
method public void startScan(android.bluetooth.le.ScanCallback);
method public void startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.bluetooth.le.ScanCallback);
method public int startScan(java.util.List<android.bluetooth.le.ScanFilter>, android.bluetooth.le.ScanSettings, android.app.PendingIntent);
method public void stopScan(android.bluetooth.le.ScanCallback);
method public void stopScan(android.app.PendingIntent);
field public static final java.lang.String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
field public static final java.lang.String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
field public static final java.lang.String EXTRA_LIST_SCAN_RESULT = "android.bluetooth.le.extra.LIST_SCAN_RESULT";
}
public final class PeriodicAdvertisingParameters implements android.os.Parcelable {

View File

@@ -16,6 +16,7 @@
package android.bluetooth;
import android.app.PendingIntent;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.le.AdvertiseSettings;
@@ -47,6 +48,9 @@ interface IBluetoothGatt {
void unregisterScanner(in int scannerId);
void startScan(in int scannerId, in ScanSettings settings, in List<ScanFilter> filters,
in WorkSource workSource, in List scanStorages, in String callingPackage);
void startScanForIntent(in PendingIntent intent, in ScanSettings settings, in List<ScanFilter> filters,
in String callingPackage);
void stopScanForIntent(in PendingIntent intent, in String callingPackage);
void stopScan(in int scannerId);
void flushPendingBatchResults(in int scannerId);

View File

@@ -17,17 +17,18 @@
package android.bluetooth.le;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManager;
import android.bluetooth.le.IScannerCallback;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.WorkSource;
import android.util.Log;
@@ -36,7 +37,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* This class provides methods to perform scan related operations for Bluetooth LE devices. An
@@ -57,6 +57,27 @@ public final class BluetoothLeScanner {
private static final boolean DBG = true;
private static final boolean VDBG = false;
/**
* Extra containing a list of ScanResults. It can have one or more results if there was no
* error. In case of error, {@link #EXTRA_ERROR_CODE} will contain the error code and this
* extra will not be available.
*/
public static final String EXTRA_LIST_SCAN_RESULT
= "android.bluetooth.le.extra.LIST_SCAN_RESULT";
/**
* Optional extra indicating the error code, if any. The error code will be one of the
* SCAN_FAILED_* codes in {@link ScanCallback}.
*/
public static final String EXTRA_ERROR_CODE = "android.bluetooth.le.extra.ERROR_CODE";
/**
* Optional extra indicating the callback type, which will be one of
* ScanSettings.CALLBACK_TYPE_*.
* @see ScanCallback#onScanResult(int, ScanResult)
*/
public static final String EXTRA_CALLBACK_TYPE = "android.bluetooth.le.extra.CALLBACK_TYPE";
private final IBluetoothManager mBluetoothManager;
private final Handler mHandler;
private BluetoothAdapter mBluetoothAdapter;
@@ -110,7 +131,27 @@ public final class BluetoothLeScanner {
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void startScan(List<ScanFilter> filters, ScanSettings settings,
final ScanCallback callback) {
startScan(filters, settings, null, callback, null);
startScan(filters, settings, null, callback, /*callbackIntent=*/ null, null);
}
/**
* Start Bluetooth LE scan using a {@link PendingIntent}. The scan results will be delivered via
* the PendingIntent. Use this method of scanning if your process is not always running and it
* should be started when scan results are available.
*
* @param filters Optional list of ScanFilters for finding exact BLE devices.
* @param settings Optional settings for the scan.
* @param callbackIntent The PendingIntent to deliver the result to.
* @return Returns 0 for success or an error code from {@link ScanCallback} if the scan request
* could not be sent.
* @see #stopScan(PendingIntent)
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public int startScan(@Nullable List<ScanFilter> filters, @Nullable ScanSettings settings,
@NonNull PendingIntent callbackIntent) {
return startScan(filters,
settings != null ? settings : new ScanSettings.Builder().build(),
null, null, callbackIntent, null);
}
/**
@@ -145,23 +186,23 @@ public final class BluetoothLeScanner {
Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.UPDATE_DEVICE_STATS })
public void startScanFromSource(List<ScanFilter> filters, ScanSettings settings,
final WorkSource workSource, final ScanCallback callback) {
startScan(filters, settings, workSource, callback, null);
startScan(filters, settings, workSource, callback, null, null);
}
private void startScan(List<ScanFilter> filters, ScanSettings settings,
private int startScan(List<ScanFilter> filters, ScanSettings settings,
final WorkSource workSource, final ScanCallback callback,
final PendingIntent callbackIntent,
List<List<ResultStorageDescriptor>> resultStorages) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
if (callback == null) {
if (callback == null && callbackIntent == null) {
throw new IllegalArgumentException("callback is null");
}
if (settings == null) {
throw new IllegalArgumentException("settings is null");
}
synchronized (mLeScanClients) {
if (mLeScanClients.containsKey(callback)) {
if (callback != null && mLeScanClients.containsKey(callback)) {
postCallbackError(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED);
return;
}
IBluetoothGatt gatt;
try {
@@ -170,28 +211,34 @@ public final class BluetoothLeScanner {
gatt = null;
}
if (gatt == null) {
postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
return;
return postCallbackErrorOrReturn(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
}
if (!isSettingsConfigAllowedForScan(settings)) {
postCallbackError(callback,
ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
return;
return postCallbackErrorOrReturn(callback,
ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
}
if (!isHardwareResourcesAvailableForScan(settings)) {
postCallbackError(callback,
ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
return;
return postCallbackErrorOrReturn(callback,
ScanCallback.SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES);
}
if (!isSettingsAndFilterComboAllowed(settings, filters)) {
postCallbackError(callback,
return postCallbackErrorOrReturn(callback,
ScanCallback.SCAN_FAILED_FEATURE_UNSUPPORTED);
return;
}
BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
settings, workSource, callback, resultStorages);
wrapper.startRegisteration();
if (callback != null) {
BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
settings, workSource, callback, resultStorages);
wrapper.startRegistration();
} else {
try {
gatt.startScanForIntent(callbackIntent, settings, filters,
ActivityThread.currentOpPackageName());
} catch (RemoteException e) {
return ScanCallback.SCAN_FAILED_INTERNAL_ERROR;
}
}
}
return ScanCallback.NO_ERROR;
}
/**
@@ -214,6 +261,25 @@ public final class BluetoothLeScanner {
}
}
/**
* Stops an ongoing Bluetooth LE scan started using a PendingIntent.
* <p>
* Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN} permission.
*
* @param callbackIntent The PendingIntent that was used to start the scan.
* @see #startScan(List, ScanSettings, PendingIntent)
*/
@RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
public void stopScan(PendingIntent callbackIntent) {
BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
IBluetoothGatt gatt;
try {
gatt = mBluetoothManager.getBluetoothGatt();
gatt.stopScanForIntent(callbackIntent, ActivityThread.currentOpPackageName());
} catch (RemoteException e) {
}
}
/**
* Flush pending batch scan results stored in Bluetooth controller. This will return Bluetooth
* LE scan results batched on bluetooth controller. Returns immediately, batch scan results data
@@ -252,7 +318,7 @@ public final class BluetoothLeScanner {
scanFilters.add(filter.getFilter());
scanStorages.add(filter.getStorageDescriptors());
}
startScan(scanFilters, settings, null, callback, scanStorages);
startScan(scanFilters, settings, null, callback, null, scanStorages);
}
/**
@@ -295,7 +361,7 @@ public final class BluetoothLeScanner {
mResultStorages = resultStorages;
}
public void startRegisteration() {
public void startRegistration() {
synchronized (this) {
// Scan stopped.
if (mScannerId == -1) return;
@@ -399,7 +465,6 @@ public final class BluetoothLeScanner {
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
}
});
}
@Override
@@ -453,6 +518,15 @@ public final class BluetoothLeScanner {
}
}
private int postCallbackErrorOrReturn(final ScanCallback callback, final int errorCode) {
if (callback == null) {
return errorCode;
} else {
postCallbackError(callback, errorCode);
return ScanCallback.NO_ERROR;
}
}
private void postCallbackError(final ScanCallback callback, final int errorCode) {
mHandler.post(new Runnable() {
@Override

View File

@@ -50,6 +50,8 @@ public abstract class ScanCallback {
*/
public static final int SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES = 5;
static final int NO_ERROR = 0;
/**
* Callback when a BLE advertisement has been found.
*