summaryrefslogtreecommitdiffstats
path: root/core/java/android/bluetooth
diff options
context:
space:
mode:
authorWei Wang <weiwa@google.com>2014-07-01 15:10:06 -0700
committerWei Wang <weiwa@google.com>2014-07-08 00:42:32 -0700
commit9fb1791e1a6859bfb14006a6d101cdecc88f3f95 (patch)
tree1ed816c3313b638d471e925d11622ceaaaab9c38 /core/java/android/bluetooth
parentb93ccca6139a7ee2dba5c110e5f8213a2bd231e5 (diff)
downloadframeworks_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')
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java23
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java6
-rw-r--r--core/java/android/bluetooth/IBluetoothGatt.aidl1
-rw-r--r--core/java/android/bluetooth/IBluetoothGattCallback.aidl3
-rw-r--r--core/java/android/bluetooth/le/AdvertiseCallback.java6
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeAdvertiser.java38
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeScanner.java83
-rw-r--r--core/java/android/bluetooth/le/ScanSettings.java2
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) {