diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index f216db6fc7175..fc48e7f18f5fc 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -979,17 +979,14 @@ public final class BluetoothAdapter { 8, BLUETOOTH_GET_STATE_CACHE_PROPERTY) { @Override protected Integer recompute(Void query) { + // This function must be called while holding the + // mServiceLock, and with mService not null. The public + // getState() method makes this guarantee. try { - mServiceLock.readLock().lock(); - if (mService != null) { - return mService.getState(); - } + return mService.getState(); } catch (RemoteException e) { - Log.e(TAG, "", e); - } finally { - mServiceLock.readLock().unlock(); + throw e.rethrowFromSystemServer(); } - return BluetoothAdapter.STATE_OFF; } }; @@ -1016,7 +1013,24 @@ public final class BluetoothAdapter { @RequiresPermission(Manifest.permission.BLUETOOTH) @AdapterState public int getState() { - int state = mBluetoothGetStateCache.query(null); + int state = BluetoothAdapter.STATE_OFF; + + try { + mServiceLock.readLock().lock(); + // The test for mService must either be outside the cache, or + // the cache must be invalidated when mService changes. + if (mService != null) { + state = mBluetoothGetStateCache.query(null); + } + } catch (RuntimeException e) { + if (e.getCause() instanceof RemoteException) { + Log.e(TAG, "", e.getCause()); + } else { + throw e; + } + } finally { + mServiceLock.readLock().unlock(); + } // Consider all internal states as OFF if (state == BluetoothAdapter.STATE_BLE_ON || state == BluetoothAdapter.STATE_BLE_TURNING_ON