diff options
author | Jack He <siyuanh@google.com> | 2017-08-17 12:11:18 -0700 |
---|---|---|
committer | Andre Eisenbach <eisenbach@google.com> | 2017-09-06 00:09:47 +0000 |
commit | 1f686f645294d624f8b61e4761fd14787a496c75 (patch) | |
tree | 67556876fa2618477ed2b8afb6775c79c9e76d44 /framework/java/android/bluetooth/BluetoothPan.java | |
parent | 97de572b1b76ba72740bea672a89a8f52a80d73c (diff) |
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
Diffstat (limited to 'framework/java/android/bluetooth/BluetoothPan.java')
-rw-r--r-- | framework/java/android/bluetooth/BluetoothPan.java | 61 |
1 files changed, 30 insertions, 31 deletions
diff --git a/framework/java/android/bluetooth/BluetoothPan.java b/framework/java/android/bluetooth/BluetoothPan.java index 63e83d2217..866b063083 100644 --- a/framework/java/android/bluetooth/BluetoothPan.java +++ b/framework/java/android/bluetooth/BluetoothPan.java @@ -123,7 +123,7 @@ public final class BluetoothPan implements BluetoothProfile { private Context mContext; private ServiceListener mServiceListener; private BluetoothAdapter mAdapter; - private IBluetoothPan mPanService; + private volatile IBluetoothPan mPanService; /** * Create a BluetoothPan proxy object for interacting with the local @@ -238,15 +238,16 @@ public final class BluetoothPan implements BluetoothProfile { */ public boolean connect(BluetoothDevice device) { if (DBG) log("connect(" + device + ")"); - if (mPanService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mPanService.connect(device); + return service.connect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -277,15 +278,16 @@ public final class BluetoothPan implements BluetoothProfile { */ public boolean disconnect(BluetoothDevice device) { if (DBG) log("disconnect(" + device + ")"); - if (mPanService != null && isEnabled() && isValidDevice(device)) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mPanService.disconnect(device); + return service.disconnect(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return false; } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return false; } @@ -295,15 +297,16 @@ public final class BluetoothPan implements BluetoothProfile { @Override public List<BluetoothDevice> getConnectedDevices() { if (VDBG) log("getConnectedDevices()"); - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - return mPanService.getConnectedDevices(); + return service.getConnectedDevices(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -313,15 +316,16 @@ public final class BluetoothPan implements BluetoothProfile { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { if (VDBG) log("getDevicesMatchingStates()"); - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - return mPanService.getDevicesMatchingConnectionStates(states); + return service.getDevicesMatchingConnectionStates(states); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return new ArrayList<BluetoothDevice>(); } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return new ArrayList<BluetoothDevice>(); } @@ -331,25 +335,25 @@ public final class BluetoothPan implements BluetoothProfile { @Override public int getConnectionState(BluetoothDevice device) { if (VDBG) log("getState(" + device + ")"); - if (mPanService != null && isEnabled() - && isValidDevice(device)) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled() && isValidDevice(device)) { try { - return mPanService.getConnectionState(device); + return service.getConnectionState(device); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); return BluetoothProfile.STATE_DISCONNECTED; } } - if (mPanService == null) Log.w(TAG, "Proxy not attached to service"); + if (service == null) Log.w(TAG, "Proxy not attached to service"); return BluetoothProfile.STATE_DISCONNECTED; } public void setBluetoothTethering(boolean value) { if (DBG) log("setBluetoothTethering(" + value + ")"); - - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - mPanService.setBluetoothTethering(value); + service.setBluetoothTethering(value); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); } @@ -358,10 +362,10 @@ public final class BluetoothPan implements BluetoothProfile { public boolean isTetheringOn() { if (VDBG) log("isTetheringOn()"); - - if (mPanService != null && isEnabled()) { + final IBluetoothPan service = mPanService; + if (service != null && isEnabled()) { try { - return mPanService.isTetheringOn(); + return service.isTetheringOn(); } catch (RemoteException e) { Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable())); } @@ -373,7 +377,6 @@ public final class BluetoothPan implements BluetoothProfile { public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected"); mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service)); - if (mServiceListener != null) { mServiceListener.onServiceConnected(BluetoothProfile.PAN, BluetoothPan.this); @@ -390,15 +393,11 @@ public final class BluetoothPan implements BluetoothProfile { }; private boolean isEnabled() { - if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true; - return false; + return mAdapter.getState() == BluetoothAdapter.STATE_ON; } - 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()); } private static void log(String msg) { |