summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorWei Wang <weiwa@google.com>2014-07-23 23:34:00 -0700
committerWei Wang <weiwa@google.com>2014-07-24 20:26:55 -0700
commitc3059ccfb07837d7760b24f552ec8ff6098d4350 (patch)
tree720efec887a72a8c8f50c4bdcff721e915723b73 /core
parentb3bb0e3f0df1e6b7fe3e681a29d9eb3045992f73 (diff)
downloadframeworks_base-c3059ccfb07837d7760b24f552ec8ff6098d4350.zip
frameworks_base-c3059ccfb07837d7760b24f552ec8ff6098d4350.tar.gz
frameworks_base-c3059ccfb07837d7760b24f552ec8ff6098d4350.tar.bz2
Use Scanner for legacy LE scans(1/2).
Also removed different scan methods from IBluetoothGatt and make BluetoothLeScanner and BluetoothLEAdvertiser singleton. Change-Id: Ifa2e950b50f100f5507a6dace3bd70db18d7f9ca
Diffstat (limited to 'core')
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java364
-rw-r--r--core/java/android/bluetooth/IBluetoothGatt.aidl6
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeScanner.java3
3 files changed, 95 insertions, 278 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index b1cbb13..42b8dbf 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -21,6 +21,8 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
@@ -371,12 +373,14 @@ public final class BluetoothAdapter {
*/
private static BluetoothAdapter sAdapter;
+ private static BluetoothLeScanner sBluetoothLeScanner;
+ private static BluetoothLeAdvertiser sBluetoothLeAdvertiser;
+
private final IBluetoothManager mManagerService;
private IBluetooth mService;
- private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients;
- private final Handler mHandler; // Handler to post the advertise callback to run on main thread.
private final Object mLock = new Object();
+ private final Map<LeScanCallback, ScanCallback> mLeScanClients;
/**
* Get a handle to the default local Bluetooth adapter.
@@ -411,8 +415,7 @@ public final class BluetoothAdapter {
mService = managerService.registerAdapter(mManagerCallback);
} catch (RemoteException e) {Log.e(TAG, "", e);}
mManagerService = managerService;
- mLeScanClients = new HashMap<LeScanCallback, GattCallbackWrapper>();
- mHandler = new Handler(Looper.getMainLooper());
+ mLeScanClients = new HashMap<LeScanCallback, ScanCallback>();
}
/**
@@ -451,19 +454,40 @@ public final class BluetoothAdapter {
}
/**
- * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations.
+ * Returns a {@link BluetoothLeAdvertiser} object for Bluetooth LE Advertising operations, or
+ * null if Bluetooth LE Advertising is not support on this device.
+ * <p>
+ * Use {@link #isMultipleAdvertisementSupported()} to check whether LE Advertising is supported
+ * on this device before calling this method.
*/
public BluetoothLeAdvertiser getBluetoothLeAdvertiser() {
- // TODO: Return null if this feature is not supported by hardware.
- return new BluetoothLeAdvertiser(mManagerService);
+ if (getState() != STATE_ON) {
+ return null;
+ }
+ if (!isMultipleAdvertisementSupported()) {
+ return null;
+ }
+ synchronized(mLock) {
+ if (sBluetoothLeAdvertiser == null) {
+ sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
+ }
+ }
+ return sBluetoothLeAdvertiser;
}
/**
* Returns a {@link BluetoothLeScanner} object for Bluetooth LE scan operations.
*/
public BluetoothLeScanner getBluetoothLeScanner() {
- // TODO: Return null if BLE scan is not supported by hardware.
- return new BluetoothLeScanner(mManagerService);
+ if (getState() != STATE_ON) {
+ return null;
+ }
+ synchronized(mLock) {
+ if (sBluetoothLeScanner == null) {
+ sBluetoothLeScanner = new BluetoothLeScanner(mManagerService);
+ }
+ }
+ return sBluetoothLeScanner;
}
/**
@@ -1625,13 +1649,17 @@ public final class BluetoothAdapter {
* instead.
*/
@Deprecated
- public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) {
+ public boolean startLeScan(final UUID[] serviceUuids, final LeScanCallback callback) {
if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids);
-
if (callback == null) {
if (DBG) Log.e(TAG, "startLeScan: null callback");
return false;
}
+ BluetoothLeScanner scanner = getBluetoothLeScanner();
+ if (scanner == null) {
+ if (DBG) Log.e(TAG, "startLeScan: cannot get BluetoothLeScanner");
+ return false;
+ }
synchronized(mLeScanClients) {
if (mLeScanClients.containsKey(callback)) {
@@ -1646,13 +1674,50 @@ public final class BluetoothAdapter {
return false;
}
- UUID uuid = UUID.randomUUID();
- GattCallbackWrapper wrapper = new GattCallbackWrapper(this, callback, serviceUuids);
- iGatt.registerClient(new ParcelUuid(uuid), wrapper);
- if (wrapper.scanStarted()) {
- mLeScanClients.put(callback, wrapper);
- return true;
+ ScanCallback scanCallback = new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ if (callbackType != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
+ // Should not happen.
+ Log.e(TAG, "LE Scan has already started");
+ return;
+ }
+ ScanRecord scanRecord = result.getScanRecord();
+ if (scanRecord == null) {
+ return;
+ }
+ if (serviceUuids != null) {
+ List<ParcelUuid> uuids = new ArrayList<ParcelUuid>();
+ for (UUID uuid : serviceUuids) {
+ uuids.add(new ParcelUuid(uuid));
+ }
+ List<ParcelUuid> scanServiceUuids = scanRecord.getServiceUuids();
+ if (scanServiceUuids == null || !scanServiceUuids.containsAll(uuids)) {
+ if (DBG) Log.d(TAG, "uuids does not match");
+ return;
+ }
+ }
+ callback.onLeScan(result.getDevice(), result.getRssi(),
+ scanRecord.getBytes());
+ }
+ };
+ ScanSettings settings = new ScanSettings.Builder()
+ .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
+ .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
+
+ List<ScanFilter> filters = new ArrayList<ScanFilter>();
+ if (serviceUuids != null && serviceUuids.length > 0) {
+ // Note scan filter does not support matching an UUID array so we put one
+ // UUID to hardware and match the whole array in callback.
+ ScanFilter filter = new ScanFilter.Builder().setServiceUuid(
+ new ParcelUuid(serviceUuids[0])).build();
+ filters.add(filter);
}
+ scanner.startScan(filters, settings, scanCallback);
+
+ mLeScanClients.put(callback, scanCallback);
+ return true;
+
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
@@ -1672,264 +1737,17 @@ public final class BluetoothAdapter {
@Deprecated
public void stopLeScan(LeScanCallback callback) {
if (DBG) Log.d(TAG, "stopLeScan()");
- GattCallbackWrapper wrapper;
- synchronized(mLeScanClients) {
- wrapper = mLeScanClients.remove(callback);
- if (wrapper == null) return;
- }
- wrapper.stopLeScan();
- }
-
- /**
- * Bluetooth GATT interface callbacks
- */
- private static class GattCallbackWrapper extends IBluetoothGattCallback.Stub {
- private static final int LE_CALLBACK_REG_TIMEOUT = 2000;
- private static final int LE_CALLBACK_REG_WAIT_COUNT = 5;
-
- private final LeScanCallback mLeScanCb;
-
- // mLeHandle 0: not registered
- // -1: scan stopped
- // >0: registered and scan started
- private int mLeHandle;
- private final UUID[] mScanFilter;
- private WeakReference<BluetoothAdapter> mBluetoothAdapter;
-
- public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter,
- LeScanCallback leScanCb, UUID[] uuid) {
- mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter);
- mLeScanCb = leScanCb;
- mScanFilter = uuid;
- mLeHandle = 0;
- }
-
- public boolean scanStarted() {
- return waitForRegisteration(LE_CALLBACK_REG_WAIT_COUNT);
- }
-
- private boolean waitForRegisteration(int maxWaitCount) {
- boolean started = false;
- synchronized(this) {
- if (mLeHandle == -1) return false;
- int count = 0;
- // wait for callback registration and LE scan to start
- while (mLeHandle == 0 && count < maxWaitCount) {
- try {
- wait(LE_CALLBACK_REG_TIMEOUT);
- } catch (InterruptedException e) {
- Log.e(TAG, "Callback reg wait interrupted: " + e);
- }
- count++;
- }
- started = (mLeHandle > 0);
- }
- return started;
- }
-
- public void stopLeScan() {
- synchronized(this) {
- if (mLeHandle <= 0) {
- Log.e(TAG, "Error state, mLeHandle: " + mLeHandle);
- return;
- }
- BluetoothAdapter adapter = mBluetoothAdapter.get();
- if (adapter != null) {
- try {
- IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt();
- iGatt.stopScan(mLeHandle, false);
- iGatt.unregisterClient(mLeHandle);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to stop scan and unregister" + e);
- }
- } else {
- Log.e(TAG, "stopLeScan, BluetoothAdapter is null");
- }
- mLeHandle = -1;
- notifyAll();
- }
- }
-
- /**
- * Application interface registered - app is ready to go
- */
- public void onClientRegistered(int status, int clientIf) {
- if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status +
- " clientIf=" + clientIf);
- synchronized(this) {
- if (mLeHandle == -1) {
- if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled");
- }
-
- if (status == BluetoothGatt.GATT_SUCCESS) {
- mLeHandle = clientIf;
- IBluetoothGatt iGatt = null;
- try {
- BluetoothAdapter adapter = mBluetoothAdapter.get();
- if (adapter != null) {
- iGatt = adapter.getBluetoothManager().getBluetoothGatt();
- if (mScanFilter == null) {
- iGatt.startScan(mLeHandle, false);
- } else {
- ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(mScanFilter[i]);
- }
- iGatt.startScanWithUuids(mLeHandle, false, uuids);
- }
- } else {
- Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
- mLeHandle = -1;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "fail to start le scan: " + e);
- mLeHandle = -1;
- }
- if (mLeHandle == -1) {
- // registration succeeded but start scan or advertise failed
- if (iGatt != null) {
- try {
- iGatt.unregisterClient(mLeHandle);
- } catch (RemoteException e) {
- Log.e(TAG, "fail to unregister callback: " + mLeHandle +
- " error: " + e);
- }
- }
- }
- } else {
- // registration failed
- mLeHandle = -1;
- }
- notifyAll();
- }
- }
-
- public void onClientConnectionState(int status, int clientIf,
- boolean connected, String address) {
- // no op
+ BluetoothLeScanner scanner = getBluetoothLeScanner();
+ if (scanner == null) {
+ return;
}
-
- /**
- * Callback reporting an LE scan result.
- * @hide
- */
- public void onScanResult(String address, int rssi, byte[] advData) {
- if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
-
- // Check null in case the scan has been stopped
- synchronized(this) {
- if (mLeHandle <= 0) return;
+ synchronized (mLeScanClients) {
+ ScanCallback scanCallback = mLeScanClients.remove(callback);
+ if (scanCallback == null) {
+ if (DBG) Log.d(TAG, "scan not started yet");
+ return;
}
- try {
- BluetoothAdapter adapter = mBluetoothAdapter.get();
- if (adapter == null) {
- Log.d(TAG, "onScanResult, BluetoothAdapter null");
- return;
- }
- mLeScanCb.onLeScan(adapter.getRemoteDevice(address), rssi, advData);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
- }
-
- public void onGetService(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid) {
- // no op
- }
-
- public void onGetIncludedService(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int inclSrvcType, int inclSrvcInstId,
- ParcelUuid inclSrvcUuid) {
- // no op
- }
-
- public void onGetCharacteristic(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int charProps) {
- // no op
- }
-
- public void onGetDescriptor(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int descInstId, ParcelUuid descUuid) {
- // no op
- }
-
- public void onSearchComplete(String address, int status) {
- // no op
- }
-
- public void onCharacteristicRead(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid, byte[] value) {
- // no op
- }
-
- public void onCharacteristicWrite(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid) {
- // no op
- }
-
- public void onNotify(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- byte[] value) {
- // no op
- }
-
- public void onDescriptorRead(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int descInstId, ParcelUuid descrUuid, byte[] value) {
- // no op
- }
-
- public void onDescriptorWrite(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int descInstId, ParcelUuid descrUuid) {
- // no op
- }
-
- public void onExecuteWrite(String address, int status) {
- // no op
- }
-
- public void onReadRemoteRssi(String address, int rssi, int status) {
- // no op
- }
-
- public void onAdvertiseStateChange(int advertiseState, int status) {
- }
-
- @Override
- public void onMultiAdvertiseCallback(int status) {
- // no op
- }
-
- @Override
- public void onConfigureMTU(String address, int mtu, int status) {
- // no op
- }
-
- @Override
- public void onConnectionCongested(String address, boolean congested) {
- // no op
- }
-
- @Override
- public void onBatchScanResults(List<ScanResult> results) {
- // no op
- }
-
- @Override
- public void onFoundOrLost(boolean onFound, String address,int rssi,
- byte[] advData) {
- // no op
+ scanner.stopScan(scanCallback);
}
}
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 533be13..edf823e 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -33,10 +33,8 @@ import android.bluetooth.IBluetoothGattServerCallback;
interface IBluetoothGatt {
List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
- void startScan(in int appIf, in boolean isServer);
- void startScanWithUuids(in int appIf, in boolean isServer, in ParcelUuid[] ids);
- void startScanWithFilters(in int appIf, in boolean isServer,
- in ScanSettings settings, in List<ScanFilter> filters);
+ void startScan(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,
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 980f717..8e7d400 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -151,6 +151,7 @@ public final class BluetoothLeScanner {
synchronized (mLeScanClients) {
BleScanCallbackWrapper wrapper = mLeScanClients.remove(callback);
if (wrapper == null) {
+ if (DBG) Log.d(TAG, "could not find callback wrapper");
return;
}
wrapper.stopLeScan();
@@ -266,7 +267,7 @@ public final class BluetoothLeScanner {
if (status == BluetoothGatt.GATT_SUCCESS) {
mClientIf = clientIf;
try {
- mBluetoothGatt.startScanWithFilters(mClientIf, false, mSettings, mFilters);
+ mBluetoothGatt.startScan(mClientIf, false, mSettings, mFilters);
} catch (RemoteException e) {
Log.e(TAG, "fail to start le scan: " + e);
mClientIf = -1;