summaryrefslogtreecommitdiff
path: root/framework/java/android/bluetooth/BluetoothHeadsetClient.java
diff options
context:
space:
mode:
authorJack He <siyuanh@google.com>2017-08-17 12:11:18 -0700
committerAndre Eisenbach <eisenbach@google.com>2017-09-06 00:09:47 +0000
commit1f686f645294d624f8b61e4761fd14787a496c75 (patch)
tree67556876fa2618477ed2b8afb6775c79c9e76d44 /framework/java/android/bluetooth/BluetoothHeadsetClient.java
parent97de572b1b76ba72740bea672a89a8f52a80d73c (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/BluetoothHeadsetClient.java')
-rw-r--r--framework/java/android/bluetooth/BluetoothHeadsetClient.java188
1 files changed, 105 insertions, 83 deletions
diff --git a/framework/java/android/bluetooth/BluetoothHeadsetClient.java b/framework/java/android/bluetooth/BluetoothHeadsetClient.java
index 7ed2d2e98f..031287f5ee 100644
--- a/framework/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/framework/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -76,8 +76,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* Intent sent whenever audio state changes.
*
* <p>It includes two mandatory extras:
- * {@link BluetoothProfile.EXTRA_STATE},
- * {@link BluetoothProfile.EXTRA_PREVIOUS_STATE},
+ * {@link BluetoothProfile#EXTRA_STATE},
+ * {@link BluetoothProfile#EXTRA_PREVIOUS_STATE},
* with possible values:
* {@link #STATE_AUDIO_CONNECTING},
* {@link #STATE_AUDIO_CONNECTED},
@@ -367,7 +367,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
private Context mContext;
private ServiceListener mServiceListener;
- private IBluetoothHeadsetClient mService;
+ private volatile IBluetoothHeadsetClient mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -478,15 +478,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.connect(device);
+ return service.connect(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;
}
@@ -499,15 +500,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient 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;
}
@@ -519,15 +521,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient 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<BluetoothDevice>();
}
}
- 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<BluetoothDevice>();
}
@@ -541,15 +544,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient 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<BluetoothDevice>();
}
}
- 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<BluetoothDevice>();
}
@@ -562,15 +566,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient 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;
}
@@ -581,19 +586,20 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient 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;
}
@@ -602,15 +608,16 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient 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;
}
@@ -627,14 +634,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.startVoiceRecognition(device);
+ return service.startVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -651,14 +659,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.stopVoiceRecognition(device);
+ return service.stopVoiceRecognition(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -670,14 +679,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getCurrentCalls(device);
+ return service.getCurrentCalls(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
}
@@ -689,14 +699,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public Bundle getCurrentAgEvents(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getCurrentAgEvents(device);
+ return service.getCurrentAgEvents(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
}
@@ -711,14 +722,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean acceptCall(BluetoothDevice device, int flag) {
if (DBG) log("acceptCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.acceptCall(device, flag);
+ return service.acceptCall(device, flag);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -731,14 +743,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean holdCall(BluetoothDevice device) {
if (DBG) log("holdCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.holdCall(device);
+ return service.holdCall(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -755,14 +768,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean rejectCall(BluetoothDevice device) {
if (DBG) log("rejectCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.rejectCall(device);
+ return service.rejectCall(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -784,14 +798,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
if (DBG) log("terminateCall()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.terminateCall(device, call);
+ return service.terminateCall(device, call);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -811,14 +826,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean enterPrivateMode(BluetoothDevice device, int index) {
if (DBG) log("enterPrivateMode()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.enterPrivateMode(device, index);
+ return service.enterPrivateMode(device, index);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -837,14 +853,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean explicitCallTransfer(BluetoothDevice device) {
if (DBG) log("explicitCallTransfer()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.explicitCallTransfer(device);
+ return service.explicitCallTransfer(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -859,14 +876,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
if (DBG) log("dial()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.dial(device, number);
+ return service.dial(device, number);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
}
@@ -882,14 +900,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean sendDTMF(BluetoothDevice device, byte code) {
if (DBG) log("sendDTMF()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.sendDTMF(device, code);
+ return service.sendDTMF(device, code);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -907,14 +926,15 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean getLastVoiceTagNumber(BluetoothDevice device) {
if (DBG) log("getLastVoiceTagNumber()");
- if (mService != null && isEnabled() && isValidDevice(device)) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled() && isValidDevice(device)) {
try {
- return mService.getLastVoiceTagNumber(device);
+ return service.getLastVoiceTagNumber(device);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(new Throwable()));
}
}
- if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
}
@@ -925,9 +945,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getAudioState(device);
+ return service.getAudioState(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -947,9 +968,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- mService.setAudioRouteAllowed(device, allowed);
+ service.setAudioRouteAllowed(device, allowed);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -968,9 +990,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean getAudioRouteAllowed(BluetoothDevice device) {
if (VDBG) log("getAudioRouteAllowed");
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getAudioRouteAllowed(device);
+ return service.getAudioRouteAllowed(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -991,9 +1014,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean connectAudio(BluetoothDevice device) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.connectAudio(device);
+ return service.connectAudio(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1014,9 +1038,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean disconnectAudio(BluetoothDevice device) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.disconnectAudio(device);
+ return service.disconnectAudio(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1034,9 +1059,10 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return bundle of AG features; null if no service or AG not connected
*/
public Bundle getCurrentAgFeatures(BluetoothDevice device) {
- if (mService != null && isEnabled()) {
+ final IBluetoothHeadsetClient service = mService;
+ if (service != null && isEnabled()) {
try {
- return mService.getCurrentAgFeatures(device);
+ return service.getCurrentAgFeatures(device);
} catch (RemoteException e) {
Log.e(TAG, e.toString());
}
@@ -1048,7 +1074,7 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
}
- private ServiceConnection mConnection = new ServiceConnection() {
+ private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
@@ -1071,15 +1097,11 @@ public final class BluetoothHeadsetClient 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) {