diff options
author | Wei Wang <weiwa@google.com> | 2014-07-01 15:10:06 -0700 |
---|---|---|
committer | Wei Wang <weiwa@google.com> | 2014-07-08 00:42:32 -0700 |
commit | 9fb1791e1a6859bfb14006a6d101cdecc88f3f95 (patch) | |
tree | 1ed816c3313b638d471e925d11622ceaaaab9c38 /core/java/android/bluetooth | |
parent | b93ccca6139a7ee2dba5c110e5f8213a2bd231e5 (diff) | |
download | frameworks_base-9fb1791e1a6859bfb14006a6d101cdecc88f3f95.zip frameworks_base-9fb1791e1a6859bfb14006a6d101cdecc88f3f95.tar.gz frameworks_base-9fb1791e1a6859bfb14006a6d101cdecc88f3f95.tar.bz2 |
Implement batch scan API
Change-Id: Ibb527280a221fbdd0fc6b805a7527c29079294b4
Diffstat (limited to 'core/java/android/bluetooth')
8 files changed, 121 insertions, 41 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index d75304f..35e5050 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -20,6 +20,7 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.bluetooth.le.BluetoothLeAdvertiser; import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.ScanResult; import android.content.Context; import android.os.Handler; import android.os.IBinder; @@ -37,6 +38,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -504,13 +506,7 @@ public final class BluetoothAdapter { */ public BluetoothLeAdvertiser getBluetoothLeAdvertiser() { // TODO: Return null if this feature is not supported by hardware. - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - return new BluetoothLeAdvertiser(iGatt); - } catch (RemoteException e) { - Log.e(TAG, "failed to get BluetoothLeAdvertiser, error: " + e); - return null; - } + return new BluetoothLeAdvertiser(mManagerService); } /** @@ -518,13 +514,7 @@ public final class BluetoothAdapter { */ public BluetoothLeScanner getBluetoothLeScanner() { // TODO: Return null if BLE scan is not supported by hardware. - try { - IBluetoothGatt iGatt = mManagerService.getBluetoothGatt(); - return new BluetoothLeScanner(iGatt); - } catch (RemoteException e) { - Log.e(TAG, "failed to get BluetoothLeScanner, error: " + e); - return null; - } + return new BluetoothLeScanner(mManagerService); } /** @@ -2137,5 +2127,10 @@ public final class BluetoothAdapter { public void onConnectionCongested(String address, boolean congested) { // no op } + + @Override + public void onBatchScanResults(List<ScanResult> results) { + // no op + } } } diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index 6c1a45e..4255cd4 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -16,6 +16,7 @@ package android.bluetooth; +import android.bluetooth.le.ScanResult; import android.content.Context; import android.os.ParcelUuid; import android.os.RemoteException; @@ -627,6 +628,11 @@ public final class BluetoothGatt implements BluetoothProfile { Log.w(TAG, "Unhandled exception in callback", ex); } } + + @Override + public void onBatchScanResults(List<ScanResult> results) { + // no op + } }; /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device, diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl index 273d76d..5ed10a6 100644 --- a/core/java/android/bluetooth/IBluetoothGatt.aidl +++ b/core/java/android/bluetooth/IBluetoothGatt.aidl @@ -38,6 +38,7 @@ interface IBluetoothGatt { void startScanWithFilters(in int appIf, in boolean isServer, in ScanSettings settings, in List<ScanFilter> filters); void stopScan(in int appIf, in boolean isServer); + void flushPendingBatchResults(in int appIf, in boolean isServer); void startMultiAdvertising(in int appIf, in AdvertisementData advertiseData, in AdvertisementData scanResponse, diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl index 946a6f6..c18d357 100644 --- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl +++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl @@ -16,7 +16,7 @@ package android.bluetooth; import android.os.ParcelUuid; - +import android.bluetooth.le.ScanResult; /** * Callback definitions for interacting with BLE / GATT @@ -27,6 +27,7 @@ oneway interface IBluetoothGattCallback { void onClientConnectionState(in int status, in int clientIf, in boolean connected, in String address); void onScanResult(in String address, in int rssi, in byte[] advData); + void onBatchScanResults(in List<ScanResult> batchResults); void onGetService(in String address, in int srvcType, in int srvcInstId, in ParcelUuid srvcUuid); void onGetIncludedService(in String address, in int srvcType, in int srvcInstId, diff --git a/core/java/android/bluetooth/le/AdvertiseCallback.java b/core/java/android/bluetooth/le/AdvertiseCallback.java index f1334c2..59f8cdc 100644 --- a/core/java/android/bluetooth/le/AdvertiseCallback.java +++ b/core/java/android/bluetooth/le/AdvertiseCallback.java @@ -52,6 +52,12 @@ public abstract class AdvertiseCallback { public static final int ADVERTISE_FAILED_CONTROLLER_FAILURE = 5; /** + * Operation fails due to GATT service failure. + * @hide + */ + public static final int ADVERTISE_FAILED_GATT_SERVICE_FAILURE = 6; + + /** * Callback when advertising operation succeeds. * * @param settingsInEffect The actual settings used for advertising, which may be different from diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java index c20b81b..a83d875 100644 --- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java +++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java @@ -20,6 +20,7 @@ import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothGatt; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothGattCallback; +import android.bluetooth.IBluetoothManager; import android.os.Handler; import android.os.Looper; import android.os.ParcelUuid; @@ -27,6 +28,7 @@ import android.os.RemoteException; import android.util.Log; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; @@ -47,7 +49,7 @@ public final class BluetoothLeAdvertiser { private static final String TAG = "BluetoothLeAdvertiser"; - private final IBluetoothGatt mBluetoothGatt; + private final IBluetoothManager mBluetoothManager; private final Handler mHandler; private final Map<AdvertiseCallback, AdvertiseCallbackWrapper> mLeAdvertisers = new HashMap<AdvertiseCallback, AdvertiseCallbackWrapper>(); @@ -55,11 +57,11 @@ public final class BluetoothLeAdvertiser { /** * Use BluetoothAdapter.getLeAdvertiser() instead. * - * @param bluetoothGatt + * @param bluetoothManager * @hide */ - public BluetoothLeAdvertiser(IBluetoothGatt bluetoothGatt) { - mBluetoothGatt = bluetoothGatt; + public BluetoothLeAdvertiser(IBluetoothManager bluetoothManager) { + mBluetoothManager = bluetoothManager; mHandler = new Handler(Looper.getMainLooper()); } @@ -102,11 +104,19 @@ public final class BluetoothLeAdvertiser { postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED); return; } + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + Log.e(TAG, "failed to get bluetooth gatt - ", e); + postCallbackFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_CONTROLLER_FAILURE); + return; + } AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData, - scanResponse, settings, mBluetoothGatt); + scanResponse, settings, gatt); UUID uuid = UUID.randomUUID(); try { - mBluetoothGatt.registerClient(new ParcelUuid(uuid), wrapper); + gatt.registerClient(new ParcelUuid(uuid), wrapper); if (wrapper.advertiseStarted()) { mLeAdvertisers.put(callback, wrapper); } @@ -133,12 +143,19 @@ public final class BluetoothLeAdvertiser { return; } try { - mBluetoothGatt.stopMultiAdvertising(wrapper.mLeHandle); + IBluetoothGatt gatt = mBluetoothManager.getBluetoothGatt(); + if (gatt == null) { + postCallbackFailure(callback, + AdvertiseCallback.ADVERTISE_FAILED_GATT_SERVICE_FAILURE); + } + gatt.stopMultiAdvertising(wrapper.mLeHandle); if (wrapper.advertiseStopped()) { mLeAdvertisers.remove(callback); } } catch (RemoteException e) { Log.e(TAG, "failed to stop advertising", e); + postCallbackFailure(callback, + AdvertiseCallback.ADVERTISE_FAILED_GATT_SERVICE_FAILURE); } } @@ -214,8 +231,6 @@ public final class BluetoothLeAdvertiser { Log.e(TAG, "fail to start le advertise: " + e); mLeHandle = -1; notifyAll(); - } catch (Exception e) { - Log.e(TAG, "fail to start advertise: " + e.getStackTrace()); } } else { // registration failed @@ -360,6 +375,11 @@ public final class BluetoothLeAdvertiser { public void onConnectionCongested(String address, boolean congested) { // no op } + + @Override + public void onBatchScanResults(List<ScanResult> results) { + // no op + } } private void postCallbackFailure(final AdvertiseCallback callback, final int error) { diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java index fbaf5d2..44aa117 100644 --- a/core/java/android/bluetooth/le/BluetoothLeScanner.java +++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java @@ -21,6 +21,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothGattCallback; +import android.bluetooth.IBluetoothManager; import android.os.Handler; import android.os.Looper; import android.os.ParcelUuid; @@ -51,15 +52,15 @@ public final class BluetoothLeScanner { private static final String TAG = "BluetoothLeScanner"; private static final boolean DBG = true; - private final IBluetoothGatt mBluetoothGatt; + private final IBluetoothManager mBluetoothManager; private final Handler mHandler; private final Map<ScanCallback, BleScanCallbackWrapper> mLeScanClients; /** * @hide */ - public BluetoothLeScanner(IBluetoothGatt bluetoothGatt) { - mBluetoothGatt = bluetoothGatt; + public BluetoothLeScanner(IBluetoothManager bluetoothManager) { + mBluetoothManager = bluetoothManager; mHandler = new Handler(Looper.getMainLooper()); mLeScanClients = new HashMap<ScanCallback, BleScanCallbackWrapper>(); } @@ -84,11 +85,21 @@ public final class BluetoothLeScanner { postCallbackError(callback, ScanCallback.SCAN_FAILED_ALREADY_STARTED); return; } - BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(mBluetoothGatt, filters, + IBluetoothGatt gatt; + try { + gatt = mBluetoothManager.getBluetoothGatt(); + } catch (RemoteException e) { + gatt = null; + } + if (gatt == null) { + postCallbackError(callback, ScanCallback.SCAN_FAILED_GATT_SERVICE_FAILURE); + return; + } + BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters, settings, callback); try { UUID uuid = UUID.randomUUID(); - mBluetoothGatt.registerClient(new ParcelUuid(uuid), wrapper); + gatt.registerClient(new ParcelUuid(uuid), wrapper); if (wrapper.scanStarted()) { mLeScanClients.put(callback, wrapper); } else { @@ -131,18 +142,26 @@ public final class BluetoothLeScanner { } /** - * Poll scan results from bluetooth controller. This will return Bluetooth LE scan results - * batched on bluetooth controller. + * 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}. * * @param callback Callback of the Bluetooth LE Scan, it has to be the same instance as the one * used to start scan. - * @param flush Whether to flush the batch scan buffer. Note the other batch scan clients will - * get batch scan callback if the batch scan buffer is flushed. - * @return Batch Scan results. - * @hide TODO: unhide when batching is supported in stack. + * + * @hide */ - public List<ScanResult> getBatchScanResults(ScanCallback callback, boolean flush) { - throw new UnsupportedOperationException("not impelemented"); + public void flushPendingScanResults(ScanCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("callback cannot be null!"); + } + synchronized (mLeScanClients) { + BleScanCallbackWrapper wrapper = mLeScanClients.get(callback); + if (wrapper == null) { + return; + } + wrapper.flushPendingBatchResults(); + } } /** @@ -195,13 +214,27 @@ public final class BluetoothLeScanner { mBluetoothGatt.stopScan(mLeHandle, false); mBluetoothGatt.unregisterClient(mLeHandle); } catch (RemoteException e) { - Log.e(TAG, "Failed to stop scan and unregister" + e); + Log.e(TAG, "Failed to stop scan and unregister", e); } mLeHandle = -1; notifyAll(); } } + void flushPendingBatchResults() { + synchronized (this) { + if (mLeHandle <= 0) { + Log.e(TAG, "Error state, mLeHandle: " + mLeHandle); + return; + } + try { + mBluetoothGatt.flushPendingBatchResults(mLeHandle, false); + } catch (RemoteException e) { + Log.e(TAG, "Failed to get pending scan results", e); + } + } + } + /** * Application interface registered - app is ready to go */ @@ -256,9 +289,27 @@ public final class BluetoothLeScanner { BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice( address); long scanNanos = SystemClock.elapsedRealtimeNanos(); - ScanResult result = new ScanResult(device, advData, rssi, + final ScanResult result = new ScanResult(device, advData, rssi, scanNanos); - mScanCallback.onAdvertisementUpdate(result); + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + mScanCallback.onAdvertisementUpdate(result); + } + }); + + } + + @Override + public void onBatchScanResults(final List<ScanResult> results) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(new Runnable() { + @Override + public void run() { + mScanCallback.onBatchScanResults(results); + } + }); } @Override diff --git a/core/java/android/bluetooth/le/ScanSettings.java b/core/java/android/bluetooth/le/ScanSettings.java index 0a85675..3bb39b3 100644 --- a/core/java/android/bluetooth/le/ScanSettings.java +++ b/core/java/android/bluetooth/le/ScanSettings.java @@ -44,7 +44,6 @@ public final class ScanSettings implements Parcelable { public static final int CALLBACK_TYPE_ON_UPDATE = 0; /** * Callback when a bluetooth advertisement is found for the first time. - * * @hide */ public static final int CALLBACK_TYPE_ON_FOUND = 1; @@ -190,6 +189,7 @@ public final class ScanSettings implements Parcelable { * {@link ScanSettings#SCAN_RESULT_TYPE_FULL} or * {@link ScanSettings#SCAN_RESULT_TYPE_TRUNCATED}. * @throws IllegalArgumentException If the {@code scanResultType} is invalid. + * * @hide */ public Builder setScanResultType(int scanResultType) { |