summaryrefslogtreecommitdiffstats
path: root/core/java/android/bluetooth
diff options
context:
space:
mode:
authorWei Wang <weiwa@google.com>2014-08-18 16:08:00 -0700
committerWei Wang <weiwa@google.com>2014-08-19 10:46:52 -0700
commitb661bb79584f83ae95713e502fc14363c80c0278 (patch)
tree5945e5a8ebeb428e6b484167aa5061844993185d /core/java/android/bluetooth
parent3f05bf4d7838cb719e78f9d93b22d7ce777392c5 (diff)
downloadframeworks_base-b661bb79584f83ae95713e502fc14363c80c0278.zip
frameworks_base-b661bb79584f83ae95713e502fc14363c80c0278.tar.gz
frameworks_base-b661bb79584f83ae95713e502fc14363c80c0278.tar.bz2
Fix race condition for BluetoothLeScanner.
Root cause of the issue: Client registeration was done on caller's thread, while onClientRegistered was called from binder thread. There is a slight chance that onClientRegistered was called before registerClient returned, causing a premature notifyAll before wait was called. By forcing acquiring the same lock now it's guaranteed wait would happen before onClientRegistered callback was executed. Bug: 16707401 Change-Id: Ic60adec475085741d14ecd2d2bb462246f88da58
Diffstat (limited to 'core/java/android/bluetooth')
-rw-r--r--core/java/android/bluetooth/le/BluetoothLeScanner.java62
1 files changed, 25 insertions, 37 deletions
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index 988cea5..e1d4bbd2 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -130,20 +130,7 @@ public final class BluetoothLeScanner {
}
BleScanCallbackWrapper wrapper = new BleScanCallbackWrapper(gatt, filters,
settings, callback, resultStorages);
- try {
- UUID uuid = UUID.randomUUID();
- gatt.registerClient(new ParcelUuid(uuid), wrapper);
- if (wrapper.scanStarted()) {
- mLeScanClients.put(callback, wrapper);
- } else {
- postCallbackError(callback,
- ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED);
- return;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "GATT service exception when starting scan", e);
- postCallbackError(callback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
- }
+ wrapper.startRegisteration();
}
}
@@ -159,8 +146,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");
+ if (DBG) Log.d(TAG, "could not find callback wrapper");
return;
}
wrapper.stopLeScan();
@@ -220,8 +206,8 @@ public final class BluetoothLeScanner {
/**
* Bluetooth GATT interface callbacks
*/
- private static class BleScanCallbackWrapper extends BluetoothGattCallbackWrapper {
- private static final int REGISTRATION_CALLBACK_TIMEOUT_SECONDS = 5;
+ private class BleScanCallbackWrapper extends BluetoothGattCallbackWrapper {
+ private static final int REGISTRATION_CALLBACK_TIMEOUT_MILLIS = 2000;
private final ScanCallback mScanCallback;
private final List<ScanFilter> mFilters;
@@ -245,18 +231,25 @@ public final class BluetoothLeScanner {
mResultStorages = resultStorages;
}
- public boolean scanStarted() {
+ public void startRegisteration() {
synchronized (this) {
- if (mClientIf == -1) {
- return false;
- }
+ // Scan stopped.
+ if (mClientIf == -1) return;
try {
- wait(REGISTRATION_CALLBACK_TIMEOUT_SECONDS);
- } catch (InterruptedException e) {
- Log.e(TAG, "Callback reg wait interrupted: " + e);
+ UUID uuid = UUID.randomUUID();
+ mBluetoothGatt.registerClient(new ParcelUuid(uuid), this);
+ wait(REGISTRATION_CALLBACK_TIMEOUT_MILLIS);
+ } catch (InterruptedException | RemoteException e) {
+ Log.e(TAG, "application registeration exception", e);
+ postCallbackError(mScanCallback, ScanCallback.SCAN_FAILED_INTERNAL_ERROR);
+ }
+ if (mClientIf > 0) {
+ mLeScanClients.put(mScanCallback, this);
+ } else {
+ postCallbackError(mScanCallback,
+ ScanCallback.SCAN_FAILED_APPLICATION_REGISTRATION_FAILED);
}
}
- return mClientIf > 0;
}
public void stopLeScan() {
@@ -272,7 +265,6 @@ public final class BluetoothLeScanner {
Log.e(TAG, "Failed to stop scan and unregister", e);
}
mClientIf = -1;
- notifyAll();
}
}
@@ -297,11 +289,9 @@ public final class BluetoothLeScanner {
public void onClientRegistered(int status, int clientIf) {
Log.d(TAG, "onClientRegistered() - status=" + status +
" clientIf=" + clientIf);
-
synchronized (this) {
if (mClientIf == -1) {
- if (DBG)
- Log.d(TAG, "onClientRegistered LE scan canceled");
+ if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled");
}
if (status == BluetoothGatt.GATT_SUCCESS) {
@@ -328,17 +318,15 @@ public final class BluetoothLeScanner {
*/
@Override
public void onScanResult(final ScanResult scanResult) {
- if (DBG)
- Log.d(TAG, "onScanResult() - " + scanResult.toString());
+ if (DBG) Log.d(TAG, "onScanResult() - " + scanResult.toString());
// Check null in case the scan has been stopped
synchronized (this) {
- if (mClientIf <= 0)
- return;
+ if (mClientIf <= 0) return;
}
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
- @Override
+ @Override
public void run() {
mScanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
}
@@ -350,7 +338,7 @@ public final class BluetoothLeScanner {
public void onBatchScanResults(final List<ScanResult> results) {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
- @Override
+ @Override
public void run() {
mScanCallback.onBatchScanResults(results);
}
@@ -394,7 +382,7 @@ public final class BluetoothLeScanner {
private void postCallbackError(final ScanCallback callback, final int errorCode) {
mHandler.post(new Runnable() {
- @Override
+ @Override
public void run() {
callback.onScanFailed(errorCode);
}