From 1f686f645294d624f8b61e4761fd14787a496c75 Mon Sep 17 00:00:00 2001 From: Jack He Date: Thu, 17 Aug 2017 12:11:18 -0700 Subject: Bluetooth: Thread-safe binder invocation * Binder object may become null between null check and actual invocation if using a instance private variable assignable by service connection callbacks * The solution to this problem without locking is to assign existing binder variable to a local final variable before the null check * Any further invocation to a disconnected binder object will result in RemoteException that is caught by the try-catch block * Read and write to volatile variable is always atomic and hence thread-safe * Removed unnecessary synchronization in BluetoothAdapter constructor * Private mConnection objects should be final * Simplfied several return statements where booleans can be returned directly * Removed unnecessary catches for NPE since there won't be any Bug: 64724692 Test: make, pair and use devices, no functional change Change-Id: Ifc9d6337c0d451a01484b61243230725d5314f8e --- framework/java/android/bluetooth/BluetoothMap.java | 68 ++++++++++++---------- 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'framework/java/android/bluetooth/BluetoothMap.java') diff --git a/framework/java/android/bluetooth/BluetoothMap.java b/framework/java/android/bluetooth/BluetoothMap.java index 26a9106f49..5b55b23680 100644 --- a/framework/java/android/bluetooth/BluetoothMap.java +++ b/framework/java/android/bluetooth/BluetoothMap.java @@ -43,7 +43,7 @@ public final class BluetoothMap implements BluetoothProfile { public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED"; - private IBluetoothMap mService; + private volatile IBluetoothMap mService; private final Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; @@ -161,9 +161,10 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getState() { if (VDBG) log("getState()"); - if (mService != null) { + final IBluetoothMap service = mService; + if (service != null) { try { - return mService.getState(); + return service.getState(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -182,9 +183,10 @@ public final class BluetoothMap implements BluetoothProfile { */ public BluetoothDevice getClient() { if (VDBG) log("getClient()"); - if (mService != null) { + final IBluetoothMap service = mService; + if (service != null) { try { - return mService.getClient(); + return service.getClient(); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -202,9 +204,10 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean isConnected(BluetoothDevice device) { if (VDBG) log("isConnected(" + device + ")"); - if (mService != null) { + final IBluetoothMap service = mService; + if (service != null) { try { - return mService.isConnected(device); + return service.isConnected(device); } catch (RemoteException e) { Log.e(TAG, e.toString()); } @@ -232,15 +235,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -272,15 +276,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public List getConnectedDevices() { if (DBG) log("getConnectedDevices()"); - if (mService != null && isEnabled()) { + final IBluetoothMap service = mService; + if (service != null && isEnabled()) { try { - return mService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList(); } @@ -291,15 +296,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public List getDevicesMatchingConnectionStates(int[] states) { if (DBG) log("getDevicesMatchingStates()"); - if (mService != null && isEnabled()) { + final IBluetoothMap service = mService; + if (service != null && isEnabled()) { try { - return mService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return new ArrayList(); } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList(); } @@ -310,15 +316,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getConnectionState(BluetoothDevice device) { if (DBG) log("getConnectionState(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } @@ -335,19 +342,20 @@ public final class BluetoothMap implements BluetoothProfile { */ public boolean setPriority(BluetoothDevice device, int priority) { if (DBG) log("setPriority(" + device + ", " + priority + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { if (priority != BluetoothProfile.PRIORITY_OFF && priority != BluetoothProfile.PRIORITY_ON) { return false; } try { - return mService.setPriority(device, priority); + return service.setPriority(device, priority); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return false; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -363,15 +371,16 @@ public final class BluetoothMap implements BluetoothProfile { */ public int getPriority(BluetoothDevice device) { if (VDBG) log("getPriority(" + device + ")"); - if (mService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothMap service = mService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mService.getPriority(device); + return service.getPriority(device); } catch (RemoteException e) { Log.e(TAG, Log.getStackTraceString(new Throwable())); return PRIORITY_OFF; } } - if (mService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return PRIORITY_OFF; } @@ -403,13 +412,8 @@ public final class BluetoothMap implements BluetoothProfile { log("Bluetooth is Not enabled"); return false; } - - private boolean isValidDevice(BluetoothDevice device) { - if (device == null) return false; - - if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true; - return false; + private static boolean isValidDevice(BluetoothDevice device) { + return device != null && BluetoothAdapter.checkBluetoothAddress(device.getAddress()); } - } -- cgit v1.2.3