Merge "Fix binder leakage when turning off Bluetooth"

This commit is contained in:
Treehugger Robot
2019-05-06 03:21:18 +00:00
committed by Gerrit Code Review
16 changed files with 682 additions and 1610 deletions

View File

@@ -22,23 +22,16 @@ import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
@@ -209,101 +202,32 @@ public final class BluetoothA2dp implements BluetoothProfile {
@UnsupportedAppUsage
public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
private Context mContext;
private ServiceListener mServiceListener;
private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
@GuardedBy("mServiceLock")
private IBluetoothA2dp mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
try {
mServiceLock.writeLock().lock();
if (mService != null) {
mService = null;
mContext.unbindService(mConnection);
}
} catch (Exception re) {
Log.e(TAG, "", re);
} finally {
mServiceLock.writeLock().unlock();
}
} else {
try {
mServiceLock.readLock().lock();
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
} finally {
mServiceLock.readLock().unlock();
}
}
private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp",
IBluetoothA2dp.class.getName()) {
@Override
public IBluetoothA2dp getServiceInterface(IBinder service) {
return IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothA2dp proxy object for interacting with the local
* Bluetooth A2DP service.
*/
/*package*/ BluetoothA2dp(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
/*package*/ BluetoothA2dp(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothA2dp.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
UserHandle.CURRENT_OR_SELF)) {
Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
@UnsupportedAppUsage
/*package*/ void close() {
mServiceListener = null;
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
try {
mServiceLock.writeLock().lock();
if (mService != null) {
mService = null;
mContext.unbindService(mConnection);
}
} catch (Exception re) {
Log.e(TAG, "", re);
} finally {
mServiceLock.writeLock().unlock();
}
private IBluetoothA2dp getService() {
return mProfileConnector.getService();
}
@Override
@@ -333,17 +257,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && isValidDevice(device)) {
return mService.connect(device);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
return service.connect(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -376,17 +298,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && isValidDevice(device)) {
return mService.disconnect(device);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
return service.disconnect(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -397,17 +317,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getConnectedDevices();
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
return service.getConnectedDevices();
}
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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -418,17 +336,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getDevicesMatchingConnectionStates(states);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
return service.getDevicesMatchingConnectionStates(states);
}
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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -439,18 +355,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
return mService.getConnectionState(device);
return service.getConnectionState(device);
}
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;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -480,18 +394,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& ((device == null) || isValidDevice(device))) {
return mService.setActiveDevice(device);
return service.setActiveDevice(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -511,17 +423,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
public BluetoothDevice getActiveDevice() {
if (VDBG) log("getActiveDevice()");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getActiveDevice();
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
return service.getActiveDevice();
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return null;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return null;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -543,22 +453,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
return mService.setPriority(device, priority);
return service.setPriority(device, priority);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -578,18 +486,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
return mService.getPriority(device);
return service.getPriority(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.PRIORITY_OFF;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -602,17 +508,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
public boolean isAvrcpAbsoluteVolumeSupported() {
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.isAvrcpAbsoluteVolumeSupported();
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
return service.isAvrcpAbsoluteVolumeSupported();
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -625,15 +529,13 @@ public final class BluetoothA2dp implements BluetoothProfile {
public void setAvrcpAbsoluteVolume(int volume) {
if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
mService.setAvrcpAbsoluteVolume(volume);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
service.setAvrcpAbsoluteVolume(volume);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == 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();
}
}
@@ -646,18 +548,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
return mService.isA2dpPlaying(device);
return service.isA2dpPlaying(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -694,19 +594,17 @@ public final class BluetoothA2dp implements BluetoothProfile {
public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getCodecStatus(device);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
return service.getCodecStatus(device);
}
if (mService == null) {
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
}
return null;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
return null;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -723,17 +621,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
BluetoothCodecConfig codecConfig) {
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
mService.setCodecConfigPreference(device, codecConfig);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
service.setCodecConfigPreference(device, codecConfig);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
return;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -772,21 +668,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
*/
private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()) {
if (enable) {
mService.enableOptionalCodecs(device);
service.enableOptionalCodecs(device);
} else {
mService.disableOptionalCodecs(device);
service.disableOptionalCodecs(device);
}
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);
return;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -801,17 +695,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
@UnsupportedAppUsage
public int supportsOptionalCodecs(BluetoothDevice device) {
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && isValidDevice(device)) {
return mService.supportsOptionalCodecs(device);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
return service.supportsOptionalCodecs(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -826,17 +718,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
@UnsupportedAppUsage
public int getOptionalCodecsEnabled(BluetoothDevice device) {
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && isValidDevice(device)) {
return mService.getOptionalCodecsEnabled(device);
final IBluetoothA2dp service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
return service.getOptionalCodecsEnabled(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return OPTIONAL_CODECS_PREF_UNKNOWN;
} catch (RemoteException e) {
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
return OPTIONAL_CODECS_PREF_UNKNOWN;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -858,18 +748,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
return;
}
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
final IBluetoothA2dp service = getService();
if (service != null && isEnabled()
&& isValidDevice(device)) {
mService.setOptionalCodecsEnabled(device, value);
service.setOptionalCodecsEnabled(device, value);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -900,35 +788,6 @@ public final class BluetoothA2dp implements BluetoothProfile {
}
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
try {
mServiceLock.writeLock().lock();
mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
} finally {
mServiceLock.writeLock().unlock();
}
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
try {
mServiceLock.writeLock().lock();
mService = null;
} finally {
mServiceLock.writeLock().unlock();
}
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
}
}
};
private boolean isEnabled() {
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;

View File

@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -124,93 +121,31 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
public static final String EXTRA_AUDIO_CONFIG =
"android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG";
private Context mContext;
private ServiceListener mServiceListener;
private volatile IBluetoothA2dpSink mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK,
"BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) {
@Override
public IBluetoothA2dpSink getServiceInterface(IBinder service) {
return IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothA2dp proxy object for interacting with the local
* Bluetooth A2DP service.
*/
/*package*/ BluetoothA2dpSink(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
/*package*/ BluetoothA2dpSink(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothA2dpSink.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
mServiceListener = null;
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private IBluetoothA2dpSink getService() {
return mProfileConnector.getService();
}
@Override
@@ -241,7 +176,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -282,7 +217,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -301,7 +236,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -320,7 +255,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -339,7 +274,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -365,7 +300,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
*/
public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
if (VDBG) log("getAudioConfig(" + device + ")");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getAudioConfig(device);
@@ -395,7 +330,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -427,7 +362,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -448,7 +383,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
* @param device BluetoothDevice device
*/
public boolean isA2dpPlaying(BluetoothDevice device) {
final IBluetoothA2dpSink service = mService;
final IBluetoothA2dpSink service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.isA2dpPlaying(device);
@@ -487,25 +422,6 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
}
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
BluetoothA2dpSink.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK);
}
}
};
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}

View File

@@ -16,10 +16,7 @@
package android.bluetooth;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -79,93 +76,32 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
public static final String EXTRA_PLAYER_SETTING =
"android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING";
private Context mContext;
private ServiceListener mServiceListener;
private volatile IBluetoothAvrcpController mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER,
"BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) {
@Override
public IBluetoothAvrcpController getServiceInterface(IBinder service) {
return IBluetoothAvrcpController.Stub.asInterface(
Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothAvrcpController proxy object for interacting with the local
* Bluetooth AVRCP service.
*/
/*package*/ BluetoothAvrcpController(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
/*package*/ BluetoothAvrcpController(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothAvrcpController.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
mServiceListener = null;
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private IBluetoothAvrcpController getService() {
return mProfileConnector.getService();
}
@Override
@@ -179,7 +115,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothAvrcpController service = mService;
final IBluetoothAvrcpController service =
getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -198,7 +135,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothAvrcpController service = mService;
final IBluetoothAvrcpController service =
getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -217,7 +155,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothAvrcpController service = mService;
final IBluetoothAvrcpController service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -238,7 +177,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getPlayerSettings");
BluetoothAvrcpPlayerSettings settings = null;
final IBluetoothAvrcpController service = mService;
final IBluetoothAvrcpController service =
getService();
if (service != null && isEnabled()) {
try {
settings = service.getPlayerSettings(device);
@@ -256,7 +196,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
*/
public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
final IBluetoothAvrcpController service = mService;
final IBluetoothAvrcpController service =
getService();
if (service != null && isEnabled()) {
try {
return service.setPlayerApplicationSetting(plAppSetting);
@@ -276,7 +217,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
+ keyState);
final IBluetoothAvrcpController service = mService;
final IBluetoothAvrcpController service =
getService();
if (service != null && isEnabled()) {
try {
service.sendGroupNavigationCmd(device, keyCode, keyState);
@@ -289,25 +231,6 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
if (service == null) Log.w(TAG, "Proxy not attached to service");
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
BluetoothAvrcpController.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER);
}
}
};
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}

View File

@@ -337,19 +337,9 @@ public final class BluetoothHeadset implements BluetoothProfile {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
doUnbind();
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
doBind();
}
}
};
@@ -374,24 +364,32 @@ public final class BluetoothHeadset implements BluetoothProfile {
doBind();
}
boolean doBind() {
try {
return mAdapter.getBluetoothManager().bindBluetoothProfileService(
BluetoothProfile.HEADSET, mConnection);
} catch (RemoteException e) {
Log.e(TAG, "Unable to bind HeadsetService", e);
private boolean doBind() {
synchronized (mConnection) {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
try {
return mAdapter.getBluetoothManager().bindBluetoothProfileService(
BluetoothProfile.HEADSET, mConnection);
} catch (RemoteException e) {
Log.e(TAG, "Unable to bind HeadsetService", e);
}
}
}
return false;
}
void doUnbind() {
private void doUnbind() {
synchronized (mConnection) {
if (mService != null) {
if (VDBG) Log.d(TAG, "Unbinding service...");
try {
mAdapter.getBluetoothManager().unbindBluetoothProfileService(
BluetoothProfile.HEADSET, mConnection);
} catch (RemoteException e) {
Log.e(TAG, "Unable to unbind HeadsetService", e);
} finally {
mService = null;
}
}
}
@@ -411,8 +409,8 @@ public final class BluetoothHeadset implements BluetoothProfile {
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
} catch (RemoteException re) {
Log.e(TAG, "", re);
}
}
mServiceListener = null;
@@ -1169,7 +1167,7 @@ public final class BluetoothHeadset implements BluetoothProfile {
@Override
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
doUnbind();
mHandler.sendMessage(mHandler.obtainMessage(
MESSAGE_HEADSET_SERVICE_DISCONNECTED));
}

View File

@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
@@ -366,73 +363,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
public static final int CALL_ACCEPT_HOLD = 1;
public static final int CALL_ACCEPT_TERMINATE = 2;
private Context mContext;
private ServiceListener mServiceListener;
private volatile IBluetoothHeadsetClient mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
private final BluetoothProfileConnector<IBluetoothHeadsetClient> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.HEADSET_CLIENT,
"BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) {
@Override
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
Intent intent = new Intent(
IBluetoothHeadsetClient.class.getName());
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
public IBluetoothHeadsetClient getServiceInterface(IBinder service) {
return IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothHeadsetClient proxy object.
*/
/*package*/ BluetoothHeadsetClient(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
/*package*/ BluetoothHeadsetClient(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
/**
@@ -443,27 +389,11 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
/*package*/ void close() {
if (VDBG) log("close()");
mProfileConnector.disconnect();
}
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
mServiceListener = null;
private IBluetoothHeadsetClient getService() {
return mProfileConnector.getService();
}
/**
@@ -480,7 +410,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -503,7 +434,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -524,7 +456,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -547,7 +480,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -569,7 +503,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getConnectionState(" + device + ")");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -589,7 +524,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -611,7 +547,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -637,7 +574,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean startVoiceRecognition(BluetoothDevice device) {
if (DBG) log("startVoiceRecognition()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.startVoiceRecognition(device);
@@ -662,7 +600,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean stopVoiceRecognition(BluetoothDevice device) {
if (DBG) log("stopVoiceRecognition()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.stopVoiceRecognition(device);
@@ -682,7 +621,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getCurrentCalls(device);
@@ -702,7 +642,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public Bundle getCurrentAgEvents(BluetoothDevice device) {
if (DBG) log("getCurrentCalls()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getCurrentAgEvents(device);
@@ -726,7 +667,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@UnsupportedAppUsage
public boolean acceptCall(BluetoothDevice device, int flag) {
if (DBG) log("acceptCall()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.acceptCall(device, flag);
@@ -747,7 +689,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean holdCall(BluetoothDevice device) {
if (DBG) log("holdCall()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.holdCall(device);
@@ -773,7 +716,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@UnsupportedAppUsage
public boolean rejectCall(BluetoothDevice device) {
if (DBG) log("rejectCall()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.rejectCall(device);
@@ -803,7 +747,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
if (DBG) log("terminateCall()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.terminateCall(device, call);
@@ -831,7 +776,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean enterPrivateMode(BluetoothDevice device, int index) {
if (DBG) log("enterPrivateMode()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.enterPrivateMode(device, index);
@@ -858,7 +804,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean explicitCallTransfer(BluetoothDevice device) {
if (DBG) log("explicitCallTransfer()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.explicitCallTransfer(device);
@@ -881,7 +828,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
if (DBG) log("dial()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.dial(device, number);
@@ -905,7 +853,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean sendDTMF(BluetoothDevice device, byte code) {
if (DBG) log("sendDTMF()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendDTMF(device, code);
@@ -931,7 +880,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean getLastVoiceTagNumber(BluetoothDevice device) {
if (DBG) log("getLastVoiceTagNumber()");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getLastVoiceTagNumber(device);
@@ -951,7 +901,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
@UnsupportedAppUsage
public int getAudioState(BluetoothDevice device) {
if (VDBG) log("getAudioState");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
return service.getAudioState(device);
@@ -974,7 +925,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
if (VDBG) log("setAudioRouteAllowed");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
service.setAudioRouteAllowed(device, allowed);
@@ -996,7 +948,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
*/
public boolean getAudioRouteAllowed(BluetoothDevice device) {
if (VDBG) log("getAudioRouteAllowed");
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
return service.getAudioRouteAllowed(device);
@@ -1020,7 +973,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean connectAudio(BluetoothDevice device) {
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
return service.connectAudio(device);
@@ -1044,7 +998,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
*/
public boolean disconnectAudio(BluetoothDevice device) {
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
return service.disconnectAudio(device);
@@ -1065,7 +1020,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
* @return bundle of AG features; null if no service or AG not connected
*/
public Bundle getCurrentAgFeatures(BluetoothDevice device) {
final IBluetoothHeadsetClient service = mService;
final IBluetoothHeadsetClient service =
getService();
if (service != null && isEnabled()) {
try {
return service.getCurrentAgFeatures(device);
@@ -1079,29 +1035,6 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
return null;
}
private final ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
BluetoothHeadsetClient.this);
}
}
@Override
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT);
}
}
};
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}

View File

@@ -22,20 +22,14 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* This class provides the public APIs to control the Hearing Aid profile.
@@ -128,97 +122,31 @@ public final class BluetoothHearingAid implements BluetoothProfile {
*/
public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID;
private Context mContext;
private ServiceListener mServiceListener;
private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
@GuardedBy("mServiceLock")
private IBluetoothHearingAid mService;
private BluetoothAdapter mAdapter;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
try {
mServiceLock.writeLock().lock();
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
} finally {
mServiceLock.writeLock().unlock();
}
} else {
try {
mServiceLock.readLock().lock();
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
} finally {
mServiceLock.readLock().unlock();
}
}
private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID,
"BluetoothHearingAid", IBluetoothHearingAid.class.getName()) {
@Override
public IBluetoothHearingAid getServiceInterface(IBinder service) {
return IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothHearingAid proxy object for interacting with the local
* Bluetooth Hearing Aid service.
*/
/*package*/ BluetoothHearingAid(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
/*package*/ BluetoothHearingAid(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
void doBind() {
Intent intent = new Intent(IBluetoothHearingAid.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
android.os.Process.myUserHandle())) {
Log.e(TAG, "Could not bind to Bluetooth Hearing Aid Service with " + intent);
return;
}
mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
mServiceListener = null;
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
try {
mServiceLock.writeLock().lock();
if (mService != null) {
mService = null;
mContext.unbindService(mConnection);
}
} catch (Exception re) {
Log.e(TAG, "", re);
} finally {
mServiceLock.writeLock().unlock();
}
private IBluetoothHearingAid getService() {
return mProfileConnector.getService();
}
/**
@@ -240,18 +168,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && isValidDevice(device)) {
return mService.connect(device);
if (service != null && isEnabled() && isValidDevice(device)) {
return service.connect(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -282,18 +208,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled() && isValidDevice(device)) {
return mService.disconnect(device);
if (service != null && isEnabled() && isValidDevice(device)) {
return service.disconnect(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -303,18 +227,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
@Override
public @NonNull List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getConnectedDevices();
if (service != null && isEnabled()) {
return service.getConnectedDevices();
}
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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -325,18 +247,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
@NonNull int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getDevicesMatchingConnectionStates(states);
if (service != null && isEnabled()) {
return service.getDevicesMatchingConnectionStates(states);
}
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>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<BluetoothDevice>();
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -347,19 +267,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {
public @BluetoothProfile.BtProfileState int getConnectionState(
@NonNull BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
if (service != null && isEnabled()
&& isValidDevice(device)) {
return mService.getConnectionState(device);
return service.getConnectionState(device);
}
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;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.STATE_DISCONNECTED;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -387,20 +305,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {
*/
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
if (DBG) log("setActiveDevice(" + device + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
if (service != null && isEnabled()
&& ((device == null) || isValidDevice(device))) {
mService.setActiveDevice(device);
service.setActiveDevice(device);
return true;
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -418,18 +334,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
@RequiresPermission(Manifest.permission.BLUETOOTH)
public List<BluetoothDevice> getActiveDevices() {
if (VDBG) log("getActiveDevices()");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getActiveDevices();
if (service != null && isEnabled()) {
return service.getActiveDevices();
}
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<>();
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return new ArrayList<>();
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -450,23 +364,21 @@ public final class BluetoothHearingAid implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
if (service != null && isEnabled()
&& isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
return false;
}
return mService.setPriority(device, priority);
return service.setPriority(device, priority);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return false;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return false;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -484,19 +396,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {
@RequiresPermission(Manifest.permission.BLUETOOTH)
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
if (service != null && isEnabled()
&& isValidDevice(device)) {
return mService.getPriority(device);
return service.getPriority(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return BluetoothProfile.PRIORITY_OFF;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return BluetoothProfile.PRIORITY_OFF;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -535,18 +445,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
if (VDBG) {
log("getVolume()");
}
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()) {
return mService.getVolume();
if (service != null && isEnabled()) {
return service.getVolume();
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return 0;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return 0;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -566,21 +474,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {
public void adjustVolume(int direction) {
if (DBG) log("adjustVolume(" + direction + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService == null) {
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return;
}
if (!isEnabled()) return;
mService.adjustVolume(direction);
service.adjustVolume(direction);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -593,20 +498,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {
public void setVolume(int volume) {
if (DBG) Log.d(TAG, "setVolume(" + volume + ")");
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService == null) {
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return;
}
if (!isEnabled()) return;
mService.setVolume(volume);
service.setVolume(volume);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -622,21 +525,19 @@ public final class BluetoothHearingAid implements BluetoothProfile {
if (VDBG) {
log("getCustomerId(" + device + ")");
}
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService == null) {
if (service == null) {
Log.w(TAG, "Proxy not attached to service");
return HI_SYNC_ID_INVALID;
}
if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID;
return mService.getHiSyncId(device);
return service.getHiSyncId(device);
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return HI_SYNC_ID_INVALID;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -652,19 +553,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {
if (VDBG) {
log("getDeviceSide(" + device + ")");
}
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
if (service != null && isEnabled()
&& isValidDevice(device)) {
return mService.getDeviceSide(device);
return service.getDeviceSide(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return SIDE_LEFT;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return SIDE_LEFT;
} finally {
mServiceLock.readLock().unlock();
}
}
@@ -680,52 +579,20 @@ public final class BluetoothHearingAid implements BluetoothProfile {
if (VDBG) {
log("getDeviceMode(" + device + ")");
}
final IBluetoothHearingAid service = getService();
try {
mServiceLock.readLock().lock();
if (mService != null && isEnabled()
if (service != null && isEnabled()
&& isValidDevice(device)) {
return mService.getDeviceMode(device);
return service.getDeviceMode(device);
}
if (mService == null) Log.w(TAG, "Proxy not attached to service");
if (service == null) Log.w(TAG, "Proxy not attached to service");
return MODE_MONAURAL;
} catch (RemoteException e) {
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
return MODE_MONAURAL;
} finally {
mServiceLock.readLock().unlock();
}
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
try {
mServiceLock.writeLock().lock();
mService = IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
} finally {
mServiceLock.writeLock().unlock();
}
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.HEARING_AID,
BluetoothHearingAid.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
try {
mServiceLock.writeLock().lock();
mService = null;
} finally {
mServiceLock.writeLock().unlock();
}
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.HEARING_AID);
}
}
};
private boolean isEnabled() {
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
return false;

View File

@@ -18,10 +18,8 @@ package android.bluetooth;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -327,11 +325,6 @@ public final class BluetoothHidDevice implements BluetoothProfile {
}
}
private Context mContext;
private ServiceListener mServiceListener;
private volatile IBluetoothHidDevice mService;
private BluetoothAdapter mAdapter;
private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
private final Executor mExecutor;
@@ -385,114 +378,33 @@ public final class BluetoothHidDevice implements BluetoothProfile {
}
}
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
Log.d(TAG, "onBluetoothStateChange: up=" + up);
synchronized (mConnection) {
if (up) {
try {
if (mService == null) {
Log.d(TAG, "Binding HID Device service...");
doBind();
}
} catch (IllegalStateException e) {
Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
+ "service: ", e);
} catch (SecurityException e) {
Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
+ "service: ", e);
}
} else {
Log.d(TAG, "Unbinding service...");
doUnbind();
}
}
private BluetoothAdapter mAdapter;
private final BluetoothProfileConnector<IBluetoothHidDevice> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.HID_DEVICE,
"BluetoothHidDevice", IBluetoothHidDevice.class.getName()) {
@Override
public IBluetoothHidDevice getServiceInterface(IBinder service) {
return IBluetoothHidDevice.Stub.asInterface(Binder.allowBlocking(service));
}
};
private final ServiceConnection mConnection =
new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
Log.d(TAG, "onServiceConnected()");
mService = IBluetoothHidDevice.Stub.asInterface(service);
if (mServiceListener != null) {
mServiceListener.onServiceConnected(
BluetoothProfile.HID_DEVICE, BluetoothHidDevice.this);
}
}
public void onServiceDisconnected(ComponentName className) {
Log.d(TAG, "onServiceDisconnected()");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
}
}
};
};
BluetoothHidDevice(Context context, ServiceListener listener) {
mContext = context;
mServiceListener = listener;
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothHidDevice.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
return false;
}
Log.d(TAG, "Bound to HID Device Service");
return true;
}
void doUnbind() {
if (mService != null) {
mService = null;
try {
mContext.unbindService(mConnection);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Unable to unbind HidDevService", e);
}
}
mProfileConnector.connect(context, listener);
}
void close() {
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
e.printStackTrace();
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
doUnbind();
}
mServiceListener = null;
private IBluetoothHidDevice getService() {
return mProfileConnector.getService();
}
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getConnectedDevices() {
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getConnectedDevices();
@@ -509,7 +421,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
/** {@inheritDoc} */
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -526,7 +438,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
/** {@inheritDoc} */
@Override
public int getConnectionState(BluetoothDevice device) {
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
return service.getConnectionState(device);
@@ -583,7 +495,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
throw new IllegalArgumentException("callback parameter cannot be null");
}
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
CallbackWrapper cbw = new CallbackWrapper(executor, callback);
@@ -611,7 +523,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
public boolean unregisterApp() {
boolean result = false;
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.unregisterApp();
@@ -636,7 +548,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
boolean result = false;
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.sendReport(device, id, data);
@@ -662,7 +574,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
boolean result = false;
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.replyReport(device, type, id, data);
@@ -686,7 +598,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
public boolean reportError(BluetoothDevice device, byte error) {
boolean result = false;
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.reportError(device, error);
@@ -707,7 +619,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
* {@hide}
*/
public String getUserAppName() {
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
@@ -733,7 +645,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
public boolean connect(BluetoothDevice device) {
boolean result = false;
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.connect(device);
@@ -757,7 +669,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
public boolean disconnect(BluetoothDevice device) {
boolean result = false;
final IBluetoothHidDevice service = mService;
final IBluetoothHidDevice service = getService();
if (service != null) {
try {
result = service.disconnect(device);

View File

@@ -18,10 +18,7 @@ package android.bluetooth;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -219,97 +216,32 @@ public final class BluetoothHidHost implements BluetoothProfile {
public static final String EXTRA_IDLE_TIME =
"android.bluetooth.BluetoothHidHost.extra.IDLE_TIME";
private Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
private volatile IBluetoothHidHost mService;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
if (mService != null) {
mService = null;
mContext.unbindService(mConnection);
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private final BluetoothProfileConnector<IBluetoothHidHost> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.HID_HOST,
"BluetoothHidHost", IBluetoothHidHost.class.getName()) {
@Override
public IBluetoothHidHost getServiceInterface(IBinder service) {
return IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothHidHost proxy object for interacting with the local
* Bluetooth Service which handles the InputDevice profile
*/
/*package*/ BluetoothHidHost(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
/*package*/ BluetoothHidHost(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothHidHost.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
/*package*/ void close() {
if (VDBG) log("close()");
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
mServiceListener = null;
private IBluetoothHidHost getService() {
return mProfileConnector.getService();
}
/**
@@ -333,7 +265,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -373,7 +305,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -392,7 +324,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -411,7 +343,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -430,7 +362,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -460,7 +392,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -492,7 +424,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -505,26 +437,6 @@ public final class BluetoothHidHost implements BluetoothProfile {
return BluetoothProfile.PRIORITY_OFF;
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.HID_HOST,
BluetoothHidHost.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.HID_HOST);
}
}
};
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
}
@@ -544,7 +456,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean virtualUnplug(BluetoothDevice device) {
if (DBG) log("virtualUnplug(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.virtualUnplug(device);
@@ -570,7 +482,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean getProtocolMode(BluetoothDevice device) {
if (VDBG) log("getProtocolMode(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getProtocolMode(device);
@@ -594,7 +506,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
if (DBG) log("setProtocolMode(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setProtocolMode(device, protocolMode);
@@ -625,7 +537,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
+ "bufferSize=" + bufferSize);
}
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getReport(device, reportType, reportId, bufferSize);
@@ -651,7 +563,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean setReport(BluetoothDevice device, byte reportType, String report) {
if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setReport(device, reportType, report);
@@ -676,7 +588,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean sendData(BluetoothDevice device, String report) {
if (DBG) log("sendData(" + device + "), report=" + report);
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendData(device, report);
@@ -700,7 +612,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean getIdleTime(BluetoothDevice device) {
if (DBG) log("getIdletime(" + device + ")");
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getIdleTime(device);
@@ -725,7 +637,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
*/
public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
final IBluetoothHidHost service = mService;
final IBluetoothHidHost service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.setIdleTime(device, idleTime);

View File

@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -44,11 +41,6 @@ public final class BluetoothMap implements BluetoothProfile {
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
private volatile IBluetoothMap mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -57,64 +49,23 @@ public final class BluetoothMap implements BluetoothProfile {
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private BluetoothAdapter mAdapter;
private final BluetoothProfileConnector<IBluetoothMap> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.MAP,
"BluetoothMap", IBluetoothMap.class.getName()) {
@Override
public IBluetoothMap getServiceInterface(IBinder service) {
return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothMap proxy object.
*/
/*package*/ BluetoothMap(Context context, ServiceListener l) {
/*package*/ BluetoothMap(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothMap proxy object");
mContext = context;
mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothMap.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -132,26 +83,11 @@ public final class BluetoothMap implements BluetoothProfile {
* are ok.
*/
public synchronized void close() {
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
mServiceListener = null;
private IBluetoothMap getService() {
return mProfileConnector.getService();
}
/**
@@ -162,7 +98,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public int getState() {
if (VDBG) log("getState()");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null) {
try {
return service.getState();
@@ -184,7 +120,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null) {
try {
return service.getClient();
@@ -205,7 +141,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -237,7 +173,7 @@ public final class BluetoothMap implements BluetoothProfile {
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -278,7 +214,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -298,7 +234,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -318,7 +254,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -344,7 +280,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -373,7 +309,7 @@ public final class BluetoothMap implements BluetoothProfile {
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
final IBluetoothMap service = mService;
final IBluetoothMap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -386,24 +322,6 @@ public final class BluetoothMap implements BluetoothProfile {
return PRIORITY_OFF;
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) log("Proxy object connected");
mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) log("Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.MAP);
}
}
};
private static void log(String msg) {
Log.d(TAG, msg);
}

View File

@@ -18,11 +18,9 @@ package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -60,11 +58,6 @@ public final class BluetoothMapClient implements BluetoothProfile {
public static final String EXTRA_SENDER_CONTACT_NAME =
"android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
private volatile IBluetoothMapClient mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -75,64 +68,23 @@ public final class BluetoothMapClient implements BluetoothProfile {
private static final int UPLOADING_FEATURE_BITMASK = 0x08;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private BluetoothAdapter mAdapter;
private final BluetoothProfileConnector<IBluetoothMapClient> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.MAP_CLIENT,
"BluetoothMapClient", IBluetoothMapClient.class.getName()) {
@Override
public IBluetoothMapClient getServiceInterface(IBinder service) {
return IBluetoothMapClient.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothMapClient proxy object.
*/
/*package*/ BluetoothMapClient(Context context, ServiceListener l) {
/*package*/ BluetoothMapClient(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
mContext = context;
mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothMapClient.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -150,26 +102,11 @@ public final class BluetoothMapClient implements BluetoothProfile {
* are ok.
*/
public void close() {
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
mServiceListener = null;
private IBluetoothMapClient getService() {
return mProfileConnector.getService();
}
/**
@@ -179,7 +116,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -199,7 +136,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*/
public boolean connect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null) {
try {
return service.connect(device);
@@ -221,7 +158,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*/
public boolean disconnect(BluetoothDevice device) {
if (DBG) Log.d(TAG, "disconnect(" + device + ")");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -241,7 +178,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) Log.d(TAG, "getConnectedDevices()");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -262,7 +199,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -283,7 +220,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
@Override
public int getConnectionState(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -307,7 +244,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -336,7 +273,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -365,7 +302,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
PendingIntent sentIntent, PendingIntent deliveredIntent) {
if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
@@ -385,7 +322,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
*/
public boolean getUnreadMessages(BluetoothDevice device) {
if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
final IBluetoothMapClient service = mService;
final IBluetoothMapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getUnreadMessages(device);
@@ -405,34 +342,16 @@ public final class BluetoothMapClient implements BluetoothProfile {
* MapSupportedFeatures field is set. False is returned otherwise.
*/
public boolean isUploadingSupported(BluetoothDevice device) {
final IBluetoothMapClient service = getService();
try {
return (mService != null && isEnabled() && isValidDevice(device))
&& ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
return (service != null && isEnabled() && isValidDevice(device))
&& ((service.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
} catch (RemoteException e) {
Log.e(TAG, e.getMessage());
}
return false;
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "Proxy object connected");
mService = IBluetoothMapClient.Stub.asInterface(service);
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT,
BluetoothMapClient.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT);
}
}
};
private boolean isEnabled() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;

View File

@@ -19,10 +19,7 @@ package android.bluetooth;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -121,108 +118,42 @@ public final class BluetoothPan implements BluetoothProfile {
*/
public static final int PAN_OPERATION_SUCCESS = 1004;
private Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
private volatile IBluetoothPan mPanService;
private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.PAN,
"BluetoothPan", IBluetoothPan.class.getName()) {
@Override
public IBluetoothPan getServiceInterface(IBinder service) {
return IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
}
};
/**
* Create a BluetoothPan proxy object for interacting with the local
* Bluetooth Service which handles the Pan profile
*/
@UnsupportedAppUsage
/*package*/ BluetoothPan(Context context, ServiceListener l) {
mContext = context;
mServiceListener = l;
/*package*/ BluetoothPan(Context context, ServiceListener listener) {
mAdapter = BluetoothAdapter.getDefaultAdapter();
try {
mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback);
} catch (RemoteException re) {
Log.w(TAG, "Unable to register BluetoothStateChangeCallback", re);
}
if (VDBG) Log.d(TAG, "BluetoothPan() call bindService");
doBind();
}
@UnsupportedAppUsage
boolean doBind() {
Intent intent = new Intent(IBluetoothPan.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
@UnsupportedAppUsage
/*package*/ void close() {
if (VDBG) log("close()");
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mStateChangeCallback);
} catch (RemoteException re) {
Log.w(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
}
}
synchronized (mConnection) {
if (mPanService != null) {
try {
mPanService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
mServiceListener = null;
mProfileConnector.disconnect();
}
private IBluetoothPan getService() {
return mProfileConnector.getService();
}
protected void finalize() {
close();
}
private final IBluetoothStateChangeCallback mStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
@Override
public void onBluetoothStateChange(boolean on) {
// Handle enable request to bind again.
Log.d(TAG, "onBluetoothStateChange on: " + on);
if (on) {
try {
if (mPanService == null) {
if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()");
doBind();
}
} catch (IllegalStateException e) {
Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
e);
} catch (SecurityException e) {
Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
e);
}
} else {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
mPanService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
}
};
/**
* Initiate connection to a profile of the remote bluetooth device.
*
@@ -243,7 +174,7 @@ public final class BluetoothPan implements BluetoothProfile {
@UnsupportedAppUsage
public boolean connect(BluetoothDevice device) {
if (DBG) log("connect(" + device + ")");
final IBluetoothPan service = mPanService;
final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -284,7 +215,7 @@ public final class BluetoothPan implements BluetoothProfile {
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothPan service = mPanService;
final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -303,7 +234,7 @@ public final class BluetoothPan implements BluetoothProfile {
@Override
public List<BluetoothDevice> getConnectedDevices() {
if (VDBG) log("getConnectedDevices()");
final IBluetoothPan service = mPanService;
final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -322,7 +253,7 @@ public final class BluetoothPan implements BluetoothProfile {
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (VDBG) log("getDevicesMatchingStates()");
final IBluetoothPan service = mPanService;
final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -341,7 +272,7 @@ public final class BluetoothPan implements BluetoothProfile {
@Override
public int getConnectionState(BluetoothDevice device) {
if (VDBG) log("getState(" + device + ")");
final IBluetoothPan service = mPanService;
final IBluetoothPan service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -357,7 +288,7 @@ public final class BluetoothPan implements BluetoothProfile {
@UnsupportedAppUsage
public void setBluetoothTethering(boolean value) {
if (DBG) log("setBluetoothTethering(" + value + ")");
final IBluetoothPan service = mPanService;
final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
service.setBluetoothTethering(value);
@@ -370,7 +301,7 @@ public final class BluetoothPan implements BluetoothProfile {
@UnsupportedAppUsage
public boolean isTetheringOn() {
if (VDBG) log("isTetheringOn()");
final IBluetoothPan service = mPanService;
final IBluetoothPan service = getService();
if (service != null && isEnabled()) {
try {
return service.isTetheringOn();
@@ -381,25 +312,6 @@ public final class BluetoothPan implements BluetoothProfile {
return false;
}
private final ServiceConnection mConnection = new ServiceConnection() {
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);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected");
mPanService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.PAN);
}
}
};
@UnsupportedAppUsage
private boolean isEnabled() {
return mAdapter.getState() == BluetoothAdapter.STATE_ON;

View File

@@ -24,6 +24,7 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -117,28 +118,9 @@ public class BluetoothPbap implements BluetoothProfile {
public void onBluetoothStateChange(boolean up) {
log("onBluetoothStateChange: up=" + up);
if (!up) {
log("Unbinding service...");
synchronized (mConnection) {
try {
if (mService != null) {
mService = null;
mContext.unbindService(mConnection);
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
doUnbind();
} else {
synchronized (mConnection) {
try {
if (mService == null) {
log("Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
doBind();
}
}
};
@@ -154,25 +136,51 @@ public class BluetoothPbap implements BluetoothProfile {
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
} catch (RemoteException re) {
Log.e(TAG, "", re);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothPbap.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
return false;
synchronized (mConnection) {
try {
if (mService == null) {
log("Binding service...");
Intent intent = new Intent(IBluetoothPbap.class.getName());
ComponentName comp = intent.resolveSystemService(
mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
UserHandle.CURRENT_OR_SELF)) {
Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
return false;
}
}
} catch (SecurityException se) {
Log.e(TAG, "", se);
return false;
}
}
return true;
}
private void doUnbind() {
synchronized (mConnection) {
if (mService != null) {
log("Unbinding service...");
try {
mContext.unbindService(mConnection);
} catch (IllegalArgumentException ie) {
Log.e(TAG, "", ie);
} finally {
mService = null;
}
}
}
}
protected void finalize() throws Throwable {
try {
close();
@@ -192,21 +200,11 @@ public class BluetoothPbap implements BluetoothProfile {
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
} catch (RemoteException re) {
Log.e(TAG, "", re);
}
}
doUnbind();
mServiceListener = null;
}
@@ -312,7 +310,7 @@ public class BluetoothPbap implements BluetoothProfile {
public void onServiceDisconnected(ComponentName className) {
log("Proxy object disconnected");
mService = null;
doUnbind();
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected();
}

View File

@@ -16,10 +16,7 @@
package android.bluetooth;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -42,11 +39,6 @@ public final class BluetoothPbapClient implements BluetoothProfile {
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
private volatile IBluetoothPbapClient mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
/** There was an error trying to obtain the state */
public static final int STATE_ERROR = -1;
@@ -55,72 +47,25 @@ public final class BluetoothPbapClient implements BluetoothProfile {
/** Connection canceled before completion. */
public static final int RESULT_CANCELED = 2;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) {
Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up);
}
if (!up) {
if (VDBG) {
Log.d(TAG, "Unbinding service...");
}
synchronized (mConnection) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) {
Log.d(TAG, "Binding service...");
}
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private BluetoothAdapter mAdapter;
private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT,
"BluetoothPbapClient", IBluetoothPbapClient.class.getName()) {
@Override
public IBluetoothPbapClient getServiceInterface(IBinder service) {
return IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothPbapClient proxy object.
*/
BluetoothPbapClient(Context context, ServiceListener l) {
BluetoothPbapClient(Context context, ServiceListener listener) {
if (DBG) {
Log.d(TAG, "Create BluetoothPbapClient proxy object");
}
mContext = context;
mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
private boolean doBind() {
Intent intent = new Intent(IBluetoothPbapClient.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -138,26 +83,11 @@ public final class BluetoothPbapClient implements BluetoothProfile {
* are ok.
*/
public synchronized void close() {
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
mServiceListener = null;
private IBluetoothPbapClient getService() {
return mProfileConnector.getService();
}
/**
@@ -173,7 +103,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
if (DBG) {
log("connect(" + device + ") for PBAP Client.");
}
final IBluetoothPbapClient service = mService;
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.connect(device);
@@ -198,7 +128,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
if (DBG) {
log("disconnect(" + device + ")" + new Exception());
}
final IBluetoothPbapClient service = mService;
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
service.disconnect(device);
@@ -225,7 +155,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
if (DBG) {
log("getConnectedDevices()");
}
final IBluetoothPbapClient service = mService;
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -250,7 +180,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
if (DBG) {
log("getDevicesMatchingStates()");
}
final IBluetoothPbapClient service = mService;
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -275,7 +205,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
if (DBG) {
log("getConnectionState(" + device + ")");
}
final IBluetoothPbapClient service = mService;
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -290,29 +220,6 @@ public final class BluetoothPbapClient implements BluetoothProfile {
return BluetoothProfile.STATE_DISCONNECTED;
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) {
log("Proxy object connected");
}
mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT,
BluetoothPbapClient.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) {
log("Proxy object disconnected");
}
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT);
}
}
};
private static void log(String msg) {
Log.d(TAG, msg);
}
@@ -345,7 +252,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
if (DBG) {
log("setPriority(" + device + ", " + priority + ")");
}
final IBluetoothPbapClient service = mService;
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -378,7 +285,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
if (VDBG) {
log("getPriority(" + device + ")");
}
final IBluetoothPbapClient service = mService;
final IBluetoothPbapClient service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);

View File

@@ -0,0 +1,166 @@
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.bluetooth;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
/**
* Connector for Bluetooth profile proxies to bind manager service and
* profile services
* @param <T> The Bluetooth profile interface for this connection.
* @hide
*/
public abstract class BluetoothProfileConnector<T> {
private int mProfileId;
private BluetoothProfile.ServiceListener mServiceListener;
private BluetoothProfile mProfileProxy;
private Context mContext;
private String mProfileName;
private String mServiceName;
private volatile T mService;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (up) {
doBind();
} else {
doUnbind();
}
}
};
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
logDebug("Proxy object connected");
mService = getServiceInterface(service);
if (mServiceListener != null) {
mServiceListener.onServiceConnected(mProfileId, mProfileProxy);
}
}
public void onServiceDisconnected(ComponentName className) {
logDebug("Proxy object disconnected");
doUnbind();
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
}
}
};
BluetoothProfileConnector(BluetoothProfile profile, int profileId, String profileName,
String serviceName) {
mProfileId = profileId;
mProfileProxy = profile;
mProfileName = profileName;
mServiceName = serviceName;
}
private boolean doBind() {
synchronized (mConnection) {
if (mService == null) {
logDebug("Binding service...");
try {
Intent intent = new Intent(mServiceName);
ComponentName comp = intent.resolveSystemService(
mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
UserHandle.CURRENT_OR_SELF)) {
logError("Could not bind to Bluetooth Service with " + intent);
return false;
}
} catch (SecurityException se) {
logError("Failed to bind service. " + se);
return false;
}
}
}
return true;
}
private void doUnbind() {
synchronized (mConnection) {
if (mService != null) {
logDebug("Unbinding service...");
try {
mContext.unbindService(mConnection);
} catch (IllegalArgumentException ie) {
logError("Unable to unbind service: " + ie);
} finally {
mService = null;
}
}
}
}
void connect(Context context, BluetoothProfile.ServiceListener listener) {
mContext = context;
mServiceListener = listener;
IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException re) {
logError("Failed to register state change callback. " + re);
}
}
doBind();
}
void disconnect() {
mServiceListener = null;
IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException re) {
logError("Failed to unregister state change callback" + re);
}
}
doUnbind();
}
T getService() {
return mService;
}
/**
* This abstract function is used to implement method to get the
* connected Bluetooth service interface.
* @param service the connected binder service.
* @return T the binder interface of {@code service}.
* @hide
*/
public abstract T getServiceInterface(IBinder service);
private void logDebug(String log) {
Log.d(mProfileName, log);
}
private void logError(String log) {
Log.e(mProfileName, log);
}
}

View File

@@ -17,10 +17,7 @@
package android.bluetooth;
import android.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -69,11 +66,6 @@ public final class BluetoothSap implements BluetoothProfile {
public static final String ACTION_CONNECTION_STATE_CHANGED =
"android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
private volatile IBluetoothSap mService;
private final Context mContext;
private ServiceListener mServiceListener;
private BluetoothAdapter mAdapter;
/**
* There was an error trying to obtain the state.
*
@@ -95,64 +87,23 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public static final int RESULT_CANCELED = 2;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
new IBluetoothStateChangeCallback.Stub() {
public void onBluetoothStateChange(boolean up) {
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
if (!up) {
if (VDBG) Log.d(TAG, "Unbinding service...");
synchronized (mConnection) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
} else {
synchronized (mConnection) {
try {
if (mService == null) {
if (VDBG) Log.d(TAG, "Binding service...");
doBind();
}
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
private BluetoothAdapter mAdapter;
private final BluetoothProfileConnector<IBluetoothSap> mProfileConnector =
new BluetoothProfileConnector(this, BluetoothProfile.SAP,
"BluetoothSap", IBluetoothSap.class.getName()) {
@Override
public IBluetoothSap getServiceInterface(IBinder service) {
return IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
}
};
};
/**
* Create a BluetoothSap proxy object.
*/
/*package*/ BluetoothSap(Context context, ServiceListener l) {
/*package*/ BluetoothSap(Context context, ServiceListener listener) {
if (DBG) Log.d(TAG, "Create BluetoothSap proxy object");
mContext = context;
mServiceListener = l;
mAdapter = BluetoothAdapter.getDefaultAdapter();
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
doBind();
}
boolean doBind() {
Intent intent = new Intent(IBluetoothSap.class.getName());
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
mContext.getUser())) {
Log.e(TAG, "Could not bind to Bluetooth SAP Service with " + intent);
return false;
}
return true;
mProfileConnector.connect(context, listener);
}
protected void finalize() throws Throwable {
@@ -172,26 +123,11 @@ public final class BluetoothSap implements BluetoothProfile {
* @hide
*/
public synchronized void close() {
IBluetoothManager mgr = mAdapter.getBluetoothManager();
if (mgr != null) {
try {
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
mProfileConnector.disconnect();
}
synchronized (mConnection) {
if (mService != null) {
try {
mService = null;
mContext.unbindService(mConnection);
} catch (Exception re) {
Log.e(TAG, "", re);
}
}
}
mServiceListener = null;
private IBluetoothSap getService() {
return mProfileConnector.getService();
}
/**
@@ -203,7 +139,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public int getState() {
if (VDBG) log("getState()");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null) {
try {
return service.getState();
@@ -226,7 +162,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public BluetoothDevice getClient() {
if (VDBG) log("getClient()");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null) {
try {
return service.getClient();
@@ -249,7 +185,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public boolean isConnected(BluetoothDevice device) {
if (VDBG) log("isConnected(" + device + ")");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null) {
try {
return service.isConnected(device);
@@ -284,7 +220,7 @@ public final class BluetoothSap implements BluetoothProfile {
@UnsupportedAppUsage
public boolean disconnect(BluetoothDevice device) {
if (DBG) log("disconnect(" + device + ")");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.disconnect(device);
@@ -305,7 +241,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public List<BluetoothDevice> getConnectedDevices() {
if (DBG) log("getConnectedDevices()");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null && isEnabled()) {
try {
return service.getConnectedDevices();
@@ -326,7 +262,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
if (DBG) log("getDevicesMatchingStates()");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null && isEnabled()) {
try {
return service.getDevicesMatchingConnectionStates(states);
@@ -347,7 +283,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public int getConnectionState(BluetoothDevice device) {
if (DBG) log("getConnectionState(" + device + ")");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getConnectionState(device);
@@ -372,7 +308,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public boolean setPriority(BluetoothDevice device, int priority) {
if (DBG) log("setPriority(" + device + ", " + priority + ")");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
if (priority != BluetoothProfile.PRIORITY_OFF
&& priority != BluetoothProfile.PRIORITY_ON) {
@@ -398,7 +334,7 @@ public final class BluetoothSap implements BluetoothProfile {
*/
public int getPriority(BluetoothDevice device) {
if (VDBG) log("getPriority(" + device + ")");
final IBluetoothSap service = mService;
final IBluetoothSap service = getService();
if (service != null && isEnabled() && isValidDevice(device)) {
try {
return service.getPriority(device);
@@ -411,24 +347,6 @@ public final class BluetoothSap implements BluetoothProfile {
return PRIORITY_OFF;
}
private final ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) log("Proxy object connected");
mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
if (mServiceListener != null) {
mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this);
}
}
public void onServiceDisconnected(ComponentName className) {
if (DBG) log("Proxy object disconnected");
mService = null;
if (mServiceListener != null) {
mServiceListener.onServiceDisconnected(BluetoothProfile.SAP);
}
}
};
private static void log(String msg) {
Log.d(TAG, msg);
}

View File

@@ -1094,11 +1094,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
public void unbindBluetoothProfileService(int bluetoothProfile,
IBluetoothProfileServiceConnection proxy) {
synchronized (mProfileServices) {
ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
Integer profile = new Integer(bluetoothProfile);
ProfileServiceConnections psc = mProfileServices.get(profile);
if (psc == null) {
return;
}
psc.removeProxy(proxy);
if (psc.isEmpty()) {
// All prxoies are disconnected, unbind with the service.
try {
mContext.unbindService(psc);
} catch (IllegalArgumentException e) {
Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
}
mProfileServices.remove(profile);
}
}
}
@@ -1255,6 +1265,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
mProxies.kill();
}
private boolean isEmpty() {
return mProxies.getRegisteredCallbackCount() == 0;
}
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// remove timeout message