summaryrefslogtreecommitdiff
path: root/core/java/android/bluetooth/BluetoothAdapter.java
diff options
context:
space:
mode:
authorLee Shombert <shombert@google.com>2020-04-03 14:00:40 -0700
committerLee Shombert <shombert@google.com>2020-04-06 18:07:33 -0700
commit81a3e1c578b5618bf02968a9b4402e70592b7b9b (patch)
treee5e53b3e1b9b2f6f2c636a9af7748a5739605636 /core/java/android/bluetooth/BluetoothAdapter.java
parente72d456c3f39ae90cdc3063d8f6b03434c134c34 (diff)
Fix exception handling in getState() binder cache
Bug: 153103051 A binder cache query function cannot compute a result based on any data that is not known to the binder server. If the code depends on local data that can change, then invalidation will not work properly. The getState() method returns OFF if the bluetooth service is unavailable. This computation now occurs in the getState() method, outside of the binder cache query() method. The query method converts RemoteExceptions to RuntimeExceptions. Then, the conversion is reversed in getState(). This double conversion is needed because the cache query() method has no throw spec. Test: Run 'atest BluetoothInstrumentationTests' with a special debug image that enables binder cache VERIFY. The test found no cache inconsistencies. Change-Id: I80db86f66d8b51fa94207824c8b15972a9066ef5
Diffstat (limited to 'core/java/android/bluetooth/BluetoothAdapter.java')
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java32
1 files changed, 23 insertions, 9 deletions
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index f216db6fc717..fc48e7f18f5f 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