Merge "Guard concurrent accesses to BluetoothA2dp service object" into nyc-mr1-dev

This commit is contained in:
TreeHugger Robot
2016-06-22 02:31:35 +00:00
committed by Android (Google) Code Review

View File

@@ -30,8 +30,11 @@ import android.os.ParcelUuid;
import android.os.RemoteException; import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/** /**
@@ -114,7 +117,8 @@ public final class BluetoothA2dp implements BluetoothProfile {
private Context mContext; private Context mContext;
private ServiceListener mServiceListener; private ServiceListener mServiceListener;
private IBluetoothA2dp mService; private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
@GuardedBy("mServiceLock") private IBluetoothA2dp mService;
private BluetoothAdapter mAdapter; private BluetoothAdapter mAdapter;
final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -122,25 +126,27 @@ public final class BluetoothA2dp implements BluetoothProfile {
public void onBluetoothStateChange(boolean up) { public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) { if (!up) {
if (VDBG) Log.d(TAG,"Unbinding service..."); if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try { try {
mServiceLock.writeLock().lock();
mService = null; mService = null;
mContext.unbindService(mConnection); mContext.unbindService(mConnection);
} catch (Exception re) { } catch (Exception re) {
Log.e(TAG,"",re); Log.e(TAG, "", re);
} } finally {
mServiceLock.writeLock().unlock();
} }
} else { } else {
synchronized (mConnection) {
try { try {
mServiceLock.readLock().lock();
if (mService == null) { if (mService == null) {
if (VDBG) Log.d(TAG,"Binding service..."); if (VDBG) Log.d(TAG,"Binding service...");
doBind(); doBind();
} }
} catch (Exception re) { } catch (Exception re) {
Log.e(TAG,"",re); Log.e(TAG,"",re);
} } finally {
mServiceLock.readLock().unlock();
} }
} }
} }
@@ -189,15 +195,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
} }
} }
synchronized (mConnection) {
if (mService != null) {
try { try {
mServiceLock.writeLock().lock();
if (mService != null) {
mService = null; mService = null;
mContext.unbindService(mConnection); mContext.unbindService(mConnection);
}
} catch (Exception re) { } catch (Exception re) {
Log.e(TAG,"",re); Log.e(TAG, "", re);
} } finally {
} mServiceLock.writeLock().unlock();
} }
} }
@@ -229,17 +236,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public boolean connect(BluetoothDevice device) { public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")"); if (DBG) log("connect(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && if (mService != null && isEnabled() &&
isValidDevice(device)) { isValidDevice(device)) {
try {
return mService.connect(device); return mService.connect(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false; return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -270,17 +280,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public boolean disconnect(BluetoothDevice device) { public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")"); if (DBG) log("disconnect(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && if (mService != null && isEnabled() &&
isValidDevice(device)) { isValidDevice(device)) {
try {
return mService.disconnect(device); return mService.disconnect(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false; return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -288,16 +301,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public List<BluetoothDevice> getConnectedDevices() { public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()"); if (VDBG) log("getConnectedDevices()");
if (mService != null && isEnabled()) {
try { try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getConnectedDevices(); return mService.getConnectedDevices();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>(); return new ArrayList<BluetoothDevice>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -305,16 +321,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()"); if (VDBG) log("getDevicesMatchingStates()");
if (mService != null && isEnabled()) {
try { try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getDevicesMatchingConnectionStates(states); return mService.getDevicesMatchingConnectionStates(states);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return new ArrayList<BluetoothDevice>(); return new ArrayList<BluetoothDevice>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -322,17 +341,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public int getConnectionState(BluetoothDevice device) { public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")"); if (VDBG) log("getState(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() if (mService != null && isEnabled()
&& isValidDevice(device)) { && isValidDevice(device)) {
try {
return mService.getConnectionState(device); return mService.getConnectionState(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.STATE_DISCONNECTED; return BluetoothProfile.STATE_DISCONNECTED;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -352,21 +374,24 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public boolean setPriority(BluetoothDevice device, int priority) { public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")"); if (DBG) log("setPriority(" + device + ", " + priority + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() if (mService != null && isEnabled()
&& isValidDevice(device)) { && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF && if (priority != BluetoothProfile.PRIORITY_OFF &&
priority != BluetoothProfile.PRIORITY_ON){ priority != BluetoothProfile.PRIORITY_ON) {
return false; return false;
} }
try {
return mService.setPriority(device, priority); return mService.setPriority(device, priority);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false; return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -385,17 +410,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
@RequiresPermission(Manifest.permission.BLUETOOTH) @RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) { public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")"); if (VDBG) log("getPriority(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() if (mService != null && isEnabled()
&& isValidDevice(device)) { && isValidDevice(device)) {
try {
return mService.getPriority(device); return mService.getPriority(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.PRIORITY_OFF; return BluetoothProfile.PRIORITY_OFF;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -406,16 +434,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public boolean isAvrcpAbsoluteVolumeSupported() { public boolean isAvrcpAbsoluteVolumeSupported() {
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported"); if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
if (mService != null && isEnabled()) {
try { try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.isAvrcpAbsoluteVolumeSupported(); return mService.isAvrcpAbsoluteVolumeSupported();
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
return false;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false; return false;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
return false;
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -433,16 +464,17 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public void adjustAvrcpAbsoluteVolume(int direction) { public void adjustAvrcpAbsoluteVolume(int direction) {
if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume"); if (DBG) Log.d(TAG, "adjustAvrcpAbsoluteVolume");
if (mService != null && isEnabled()) {
try { try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
mService.adjustAvrcpAbsoluteVolume(direction); mService.adjustAvrcpAbsoluteVolume(direction);
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
return;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in adjustAvrcpAbsoluteVolume()", e);
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -453,16 +485,17 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/ */
public void setAvrcpAbsoluteVolume(int volume) { public void setAvrcpAbsoluteVolume(int volume) {
if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume"); if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
if (mService != null && isEnabled()) {
try { try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
mService.setAvrcpAbsoluteVolume(volume); mService.setAvrcpAbsoluteVolume(volume);
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
return;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -473,17 +506,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
* @param device BluetoothDevice device * @param device BluetoothDevice device
*/ */
public boolean isA2dpPlaying(BluetoothDevice device) { public boolean isA2dpPlaying(BluetoothDevice device) {
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() if (mService != null && isEnabled()
&& isValidDevice(device)) { && isValidDevice(device)) {
try {
return mService.isA2dpPlaying(device); return mService.isA2dpPlaying(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
}
} }
if (mService == null) Log.w(TAG, "Proxy not attached to service"); if (mService == null) Log.w(TAG, "Proxy not attached to service");
return false; return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
} }
/** /**
@@ -534,7 +570,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
private final ServiceConnection mConnection = new ServiceConnection() { private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) { public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected"); if (DBG) Log.d(TAG, "Proxy object connected");
try {
mServiceLock.writeLock().lock();
mService = IBluetoothA2dp.Stub.asInterface(service); mService = IBluetoothA2dp.Stub.asInterface(service);
} finally {
mServiceLock.writeLock().unlock();
}
if (mServiceListener != null) { if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this); mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
@@ -542,7 +583,12 @@ public final class BluetoothA2dp implements BluetoothProfile {
} }
public void onServiceDisconnected(ComponentName className) { public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected"); if (DBG) Log.d(TAG, "Proxy object disconnected");
try {
mServiceLock.writeLock().lock();
mService = null; mService = null;
} finally {
mServiceLock.writeLock().unlock();
}
if (mServiceListener != null) { if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP); mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
} }