summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ugo Yu <ugoyu@google.com> 2019-03-26 21:38:08 +0800
committer Ugo Yu <ugoyu@google.com> 2019-05-02 18:06:41 +0800
commit6d9cfce73a3ae7471d34d272455427ca05f757cc (patch)
tree52fcd3e335cacde42f77388f20fbf174b4d61520
parentc53df3a9cc4bf297d39b198e551be423db23acc3 (diff)
Fix binder leakage when turning off Bluetooth
* In current design, Bluetooth AdapterState stops all BR/EDR profiles' service and triggers onServiceDisconnected callback to all binder clients before BluetoothManagerService invokes onBluetoothStateChange(false), which means unbind service would never be called in framework. * Do unbind service when onServiceDisconnected is invoked. * Move profile binder logic to BluetoothProfileConnector except: - BluetoothHeadset: its binder logic is in BluetoothManagerService - BluetoothPbap: it has an individual ServiceListener Bug: 129037442 Bug: 129437895 Test: Bluetooth ON/OFF stress test. adb shell dumpsys activity services | egrep "com.android.bluetooth" to check whether AppBindRecord for com.android.bluetooth grows Change-Id: Id0d85866d386962b94d2d966f0a864b1da165d13
-rw-r--r--core/java/android/bluetooth/BluetoothA2dp.java313
-rwxr-xr-xcore/java/android/bluetooth/BluetoothA2dpSink.java129
-rw-r--r--core/java/android/bluetooth/BluetoothAvrcpController.java130
-rw-r--r--core/java/android/bluetooth/BluetoothHeadset.java40
-rw-r--r--core/java/android/bluetooth/BluetoothHeadsetClient.java196
-rw-r--r--core/java/android/bluetooth/BluetoothHearingAid.java274
-rw-r--r--core/java/android/bluetooth/BluetoothHidDevice.java139
-rw-r--r--core/java/android/bluetooth/BluetoothHidHost.java145
-rw-r--r--core/java/android/bluetooth/BluetoothMap.java129
-rw-r--r--core/java/android/bluetooth/BluetoothMapClient.java138
-rw-r--r--core/java/android/bluetooth/BluetoothPan.java135
-rw-r--r--core/java/android/bluetooth/BluetoothPbap.java85
-rw-r--r--core/java/android/bluetooth/BluetoothPbapClient.java136
-rw-r--r--core/java/android/bluetooth/BluetoothProfileConnector.java166
-rw-r--r--core/java/android/bluetooth/BluetoothSap.java129
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java16
16 files changed, 680 insertions, 1620 deletions
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 442b23938ccd..1fe1b10005cf 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -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 @BtProfileState 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 @Nullable 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;
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index cb996f3381b7..5a8055a29cfc 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -17,14 +17,10 @@
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;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -125,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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
@@ -242,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);
@@ -283,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);
@@ -302,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();
@@ -321,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);
@@ -340,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);
@@ -366,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);
@@ -396,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) {
@@ -428,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);
@@ -449,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);
@@ -488,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;
}
diff --git a/core/java/android/bluetooth/BluetoothAvrcpController.java b/core/java/android/bluetooth/BluetoothAvrcpController.java
index c447868d6f0c..4e7e4415c54d 100644
--- a/core/java/android/bluetooth/BluetoothAvrcpController.java
+++ b/core/java/android/bluetooth/BluetoothAvrcpController.java
@@ -16,14 +16,10 @@
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;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -80,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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
@@ -180,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();
@@ -199,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);
@@ -218,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);
@@ -239,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);
@@ -257,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);
@@ -277,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);
@@ -290,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;
}
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 8d9d340ee68b..9862a63ef238 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -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));
}
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 549c1faddd90..05833b5f571d 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -17,15 +17,11 @@
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;
import android.os.RemoteException;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -367,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,
- UserHandle.CURRENT_OR_SELF)) {
- Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
- return false;
- }
- return true;
+ mProfileConnector.connect(context, listener);
}
/**
@@ -444,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();
}
/**
@@ -481,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);
@@ -504,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);
@@ -525,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();
@@ -548,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);
@@ -570,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);
@@ -590,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) {
@@ -612,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);
@@ -638,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);
@@ -663,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);
@@ -683,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);
@@ -703,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);
@@ -727,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);
@@ -748,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);
@@ -774,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);
@@ -804,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);
@@ -832,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);
@@ -859,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);
@@ -882,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);
@@ -906,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);
@@ -932,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);
@@ -952,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);
@@ -975,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);
@@ -997,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);
@@ -1021,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);
@@ -1045,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);
@@ -1066,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);
@@ -1080,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;
}
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index d6edb90ca27b..60fb6fb122e3 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,21 +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.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;
/**
* This class provides the public APIs to control the Hearing Aid profile.
@@ -129,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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();
}
/**
@@ -241,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();
}
}
@@ -283,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();
}
}
@@ -304,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();
}
}
@@ -326,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();
}
}
@@ -348,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();
}
}
@@ -388,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();
}
}
@@ -419,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();
}
}
@@ -451,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();
}
}
@@ -485,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();
}
}
@@ -536,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();
}
}
@@ -567,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();
}
}
@@ -594,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();
}
}
@@ -623,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();
}
}
@@ -653,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();
}
}
@@ -681,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;
diff --git a/core/java/android/bluetooth/BluetoothHidDevice.java b/core/java/android/bluetooth/BluetoothHidDevice.java
index e44f36e90c75..e9b0be2c4cd6 100644
--- a/core/java/android/bluetooth/BluetoothHidDevice.java
+++ b/core/java/android/bluetooth/BluetoothHidDevice.java
@@ -18,13 +18,10 @@ 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.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -328,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;
@@ -386,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 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);
- }
+ 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));
}
- };
+ };
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,
- UserHandle.CURRENT_OR_SELF)) {
- 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();
@@ -510,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);
@@ -527,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);
@@ -584,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);
@@ -612,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();
@@ -637,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);
@@ -663,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);
@@ -687,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);
@@ -708,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 {
@@ -734,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);
@@ -758,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);
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 7c925a1cb5ef..4afb382c0660 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -18,14 +18,10 @@ 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.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -220,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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();
}
/**
@@ -334,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);
@@ -374,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);
@@ -393,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();
@@ -412,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);
@@ -431,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);
@@ -461,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) {
@@ -493,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);
@@ -506,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;
}
@@ -545,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);
@@ -571,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);
@@ -595,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);
@@ -626,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);
@@ -652,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);
@@ -677,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);
@@ -701,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);
@@ -726,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);
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index fc5f830a8940..dd2f150ad4eb 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -17,14 +17,10 @@
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;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -45,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;
@@ -58,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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 {
@@ -133,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();
}
/**
@@ -163,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();
@@ -185,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();
@@ -206,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);
@@ -238,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);
@@ -279,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();
@@ -299,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);
@@ -319,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);
@@ -345,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) {
@@ -374,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);
@@ -387,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);
}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 1c82e1984b66..ec0180c5adde 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -18,14 +18,11 @@ 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.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -61,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;
@@ -76,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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 {
@@ -151,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();
}
/**
@@ -180,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);
@@ -200,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);
@@ -222,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);
@@ -242,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();
@@ -263,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);
@@ -284,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);
@@ -308,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) {
@@ -337,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);
@@ -366,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);
@@ -386,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);
@@ -406,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;
diff --git a/core/java/android/bluetooth/BluetoothPan.java b/core/java/android/bluetooth/BluetoothPan.java
index 8923d734c844..fb78789ba8ad 100644
--- a/core/java/android/bluetooth/BluetoothPan.java
+++ b/core/java/android/bluetooth/BluetoothPan.java
@@ -19,14 +19,10 @@ 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;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -122,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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()");
+ mProfileConnector.disconnect();
+ }
- 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;
+ 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.
*
@@ -244,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);
@@ -285,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);
@@ -304,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();
@@ -323,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);
@@ -342,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);
@@ -358,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);
@@ -371,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();
@@ -382,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;
diff --git a/core/java/android/bluetooth/BluetoothPbap.java b/core/java/android/bluetooth/BluetoothPbap.java
index 359bec686a8a..d94c65742e6c 100644
--- a/core/java/android/bluetooth/BluetoothPbap.java
+++ b/core/java/android/bluetooth/BluetoothPbap.java
@@ -118,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();
}
}
};
@@ -155,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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();
@@ -193,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;
}
@@ -313,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();
}
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index cbc96c073338..d70e1e7f3f5f 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -16,14 +16,10 @@
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;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -43,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;
@@ -56,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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 {
@@ -139,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();
}
/**
@@ -174,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);
@@ -199,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);
@@ -226,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();
@@ -251,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);
@@ -276,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);
@@ -291,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);
}
@@ -346,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) {
@@ -379,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);
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
new file mode 100644
index 000000000000..d9987249a6e2
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothProfileConnector.java
@@ -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);
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index ebf6bed54475..e0610c890559 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -17,14 +17,10 @@
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;
-import android.os.UserHandle;
import android.util.Log;
import java.util.ArrayList;
@@ -70,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.
*
@@ -96,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,
- UserHandle.CURRENT_OR_SELF)) {
- 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 {
@@ -173,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();
}
/**
@@ -204,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();
@@ -227,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();
@@ -250,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);
@@ -285,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);
@@ -306,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();
@@ -327,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);
@@ -348,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);
@@ -373,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) {
@@ -399,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);
@@ -412,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);
}
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index c4bc52c6f4de..9405ed26e513 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -1091,11 +1091,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);
+ }
}
}
@@ -1252,6 +1262,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