diff options
Diffstat (limited to 'framework/java/android/bluetooth/le/BluetoothLeScanner.java')
-rw-r--r-- | framework/java/android/bluetooth/le/BluetoothLeScanner.java | 124 |
1 files changed, 99 insertions, 25 deletions
diff --git a/framework/java/android/bluetooth/le/BluetoothLeScanner.java b/framework/java/android/bluetooth/le/BluetoothLeScanner.java index b63c614711..b65a7ad0c0 100644 --- a/framework/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/framework/java/android/bluetooth/le/BluetoothLeScanner.java @@ -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; } /** @@ -215,6 +262,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 * will be delivered through the {@code callback}. @@ -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 |