diff options
author | Wei Wang <weiwa@google.com> | 2014-07-23 23:34:00 -0700 |
---|---|---|
committer | Wei Wang <weiwa@google.com> | 2014-07-24 20:26:55 -0700 |
commit | c3059ccfb07837d7760b24f552ec8ff6098d4350 (patch) | |
tree | 720efec887a72a8c8f50c4bdcff721e915723b73 /core | |
parent | b3bb0e3f0df1e6b7fe3e681a29d9eb3045992f73 (diff) | |
download | frameworks_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.java | 364 | ||||
-rw-r--r-- | core/java/android/bluetooth/IBluetoothGatt.aidl | 6 | ||||
-rw-r--r-- | core/java/android/bluetooth/le/BluetoothLeScanner.java | 3 |
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; |