From c131051e2866bb01ac3bda0a0a6a8b5cae3ff676 Mon Sep 17 00:00:00 2001 From: Ruben Brunk Date: Mon, 1 May 2017 16:57:31 -0700 Subject: Fix Bluetooth GATT API default handler assignment Restores previous behaviour where GATT callbacks are invoked on the binder thread and not the calling process main looper thread. This fixes performance regressions as well as some NetworkOnMainThreadException's for some applications. Bug: 37544152 Bug: 37871717 Test: Covered by prior API tests. Change-Id: Id8ab705dd4d7f00030e6ac29e056dde5180670e9 (cherry picked from commit 6bdc550e27e2c4e7b32bb91085eaac898d7d1156) --- core/java/android/bluetooth/BluetoothDevice.java | 5 +-- core/java/android/bluetooth/BluetoothGatt.java | 44 ++++++++++++++++-------- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java index e0b03d22abe9..f158f5f29ecd 100644 --- a/core/java/android/bluetooth/BluetoothDevice.java +++ b/core/java/android/bluetooth/BluetoothDevice.java @@ -1714,7 +1714,7 @@ public final class BluetoothDevice implements Parcelable { * an d{@link BluetoothDevice#PHY_LE_CODED_MASK}. This option does not take effect * if {@code autoConnect} is set to true. * @param handler The handler to use for the callback. If {@code null}, callbacks will happen - * on the service's main thread. + * on an un-specified background thread. * @throws NullPointerException if callback is null */ public BluetoothGatt connectGatt(Context context, boolean autoConnect, @@ -1723,9 +1723,6 @@ public final class BluetoothDevice implements Parcelable { if (callback == null) throw new NullPointerException("callback is null"); - if (handler == null) - handler = new Handler(Looper.getMainLooper()); - // TODO(Bluetooth) check whether platform support BLE // Do the check here or in GattServer? BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index 40f10a8edd22..3135b30ebcc8 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -156,7 +156,7 @@ public final class BluetoothGatt implements BluetoothProfile { } mClientIf = clientIf; if (status != GATT_SUCCESS) { - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -191,7 +191,7 @@ public final class BluetoothGatt implements BluetoothProfile { return; } - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -213,7 +213,7 @@ public final class BluetoothGatt implements BluetoothProfile { return; } - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -238,7 +238,7 @@ public final class BluetoothGatt implements BluetoothProfile { int profileState = connected ? BluetoothProfile.STATE_CONNECTED : BluetoothProfile.STATE_DISCONNECTED; - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -300,7 +300,7 @@ public final class BluetoothGatt implements BluetoothProfile { } } - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -352,7 +352,7 @@ public final class BluetoothGatt implements BluetoothProfile { if (status == 0) characteristic.setValue(value); - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -401,7 +401,7 @@ public final class BluetoothGatt implements BluetoothProfile { mAuthRetryState = AUTH_RETRY_STATE_IDLE; - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -430,7 +430,7 @@ public final class BluetoothGatt implements BluetoothProfile { characteristic.setValue(value); - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -477,7 +477,7 @@ public final class BluetoothGatt implements BluetoothProfile { mAuthRetryState = AUTH_RETRY_STATE_IDLE; - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -523,7 +523,7 @@ public final class BluetoothGatt implements BluetoothProfile { mAuthRetryState = AUTH_RETRY_STATE_IDLE; - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -549,7 +549,7 @@ public final class BluetoothGatt implements BluetoothProfile { mDeviceBusy = false; } - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -570,7 +570,7 @@ public final class BluetoothGatt implements BluetoothProfile { if (!address.equals(mDevice.getAddress())) { return; } - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -592,7 +592,7 @@ public final class BluetoothGatt implements BluetoothProfile { return; } - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -616,7 +616,7 @@ public final class BluetoothGatt implements BluetoothProfile { return; } - mHandler.post(new Runnable() { + runOrQueueCallback(new Runnable() { @Override public void run() { if (mCallback != null) { @@ -702,6 +702,22 @@ public final class BluetoothGatt implements BluetoothProfile { return null; } + /** + * Queue the runnable on a {@link Handler} provided by the user, or execute the runnable + * immediately if no Handler was provided. + */ + private void runOrQueueCallback(final Runnable cb) { + if (mHandler == null) { + try { + cb.run(); + } catch (Exception ex) { + Log.w(TAG, "Unhandled exception in callback", ex); + } + } else { + mHandler.post(cb); + } + } + /** * Register an application callback to start using GATT. * -- cgit v1.2.3-59-g8ed1b