Merge "Fix binder leakage when turning off Bluetooth"
This commit is contained in:
@@ -22,23 +22,16 @@ import android.annotation.RequiresPermission;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.os.ParcelUuid;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
|
||||
/**
|
||||
@@ -209,101 +202,32 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public static final int OPTIONAL_CODECS_PREF_ENABLED = 1;
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
|
||||
@GuardedBy("mServiceLock")
|
||||
private IBluetoothA2dp mService;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
if (mService != null) {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
private final BluetoothProfileConnector<IBluetoothA2dp> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.A2DP, "BluetoothA2dp",
|
||||
IBluetoothA2dp.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothA2dp getServiceInterface(IBinder service) {
|
||||
return IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothA2dp proxy object for interacting with the local
|
||||
* Bluetooth A2DP service.
|
||||
*/
|
||||
/*package*/ BluetoothA2dp(Context context, ServiceListener l) {
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
/*package*/ BluetoothA2dp(Context context, ServiceListener listener) {
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothA2dp.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
UserHandle.CURRENT_OR_SELF)) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
/*package*/ void close() {
|
||||
mServiceListener = null;
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
if (mService != null) {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
private IBluetoothA2dp getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -333,17 +257,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) log("connect(" + device + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
return mService.connect(device);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
return service.connect(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,17 +298,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
return mService.disconnect(device);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
return service.disconnect(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,17 +317,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (VDBG) log("getConnectedDevices()");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getConnectedDevices();
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getConnectedDevices();
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,17 +336,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (VDBG) log("getDevicesMatchingStates()");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getDevicesMatchingConnectionStates(states);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,18 +355,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (VDBG) log("getState(" + device + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
return mService.getConnectionState(device);
|
||||
return service.getConnectionState(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return BluetoothProfile.STATE_DISCONNECTED;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return BluetoothProfile.STATE_DISCONNECTED;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,18 +394,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
|
||||
if (DBG) log("setActiveDevice(" + device + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()
|
||||
&& ((device == null) || isValidDevice(device))) {
|
||||
return mService.setActiveDevice(device);
|
||||
return service.setActiveDevice(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -511,17 +423,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public BluetoothDevice getActiveDevice() {
|
||||
if (VDBG) log("getActiveDevice()");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getActiveDevice();
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getActiveDevice();
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return null;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return null;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,22 +453,20 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) log("setPriority(" + device + ", " + priority + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
return false;
|
||||
}
|
||||
return mService.setPriority(device, priority);
|
||||
return service.setPriority(device, priority);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,18 +486,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) log("getPriority(" + device + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
return mService.getPriority(device);
|
||||
return service.getPriority(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return BluetoothProfile.PRIORITY_OFF;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return BluetoothProfile.PRIORITY_OFF;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,17 +508,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public boolean isAvrcpAbsoluteVolumeSupported() {
|
||||
if (DBG) Log.d(TAG, "isAvrcpAbsoluteVolumeSupported");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.isAvrcpAbsoluteVolumeSupported();
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.isAvrcpAbsoluteVolumeSupported();
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in isAvrcpAbsoluteVolumeSupported()", e);
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,15 +529,13 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public void setAvrcpAbsoluteVolume(int volume) {
|
||||
if (DBG) Log.d(TAG, "setAvrcpAbsoluteVolume");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
mService.setAvrcpAbsoluteVolume(volume);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
service.setAvrcpAbsoluteVolume(volume);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in setAvrcpAbsoluteVolume()", e);
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,18 +548,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
*/
|
||||
public boolean isA2dpPlaying(BluetoothDevice device) {
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
return mService.isA2dpPlaying(device);
|
||||
return service.isA2dpPlaying(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,19 +594,17 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
public BluetoothCodecStatus getCodecStatus(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "getCodecStatus(" + device + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getCodecStatus(device);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getCodecStatus(device);
|
||||
}
|
||||
if (mService == null) {
|
||||
if (service == null) {
|
||||
Log.w(TAG, "Proxy not attached to service");
|
||||
}
|
||||
return null;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in getCodecStatus()", e);
|
||||
return null;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -723,17 +621,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
BluetoothCodecConfig codecConfig) {
|
||||
if (DBG) Log.d(TAG, "setCodecConfigPreference(" + device + ")");
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
mService.setCodecConfigPreference(device, codecConfig);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
service.setCodecConfigPreference(device, codecConfig);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in setCodecConfigPreference()", e);
|
||||
return;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -772,21 +668,19 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
*/
|
||||
private void enableDisableOptionalCodecs(BluetoothDevice device, boolean enable) {
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
if (enable) {
|
||||
mService.enableOptionalCodecs(device);
|
||||
service.enableOptionalCodecs(device);
|
||||
} else {
|
||||
mService.disableOptionalCodecs(device);
|
||||
service.disableOptionalCodecs(device);
|
||||
}
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in enableDisableOptionalCodecs()", e);
|
||||
return;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -801,17 +695,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public int supportsOptionalCodecs(BluetoothDevice device) {
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
return mService.supportsOptionalCodecs(device);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
return service.supportsOptionalCodecs(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
|
||||
return OPTIONAL_CODECS_SUPPORT_UNKNOWN;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,17 +718,15 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public int getOptionalCodecsEnabled(BluetoothDevice device) {
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
return mService.getOptionalCodecsEnabled(device);
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
return service.getOptionalCodecsEnabled(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return OPTIONAL_CODECS_PREF_UNKNOWN;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error talking to BT service in getSupportsOptionalCodecs()", e);
|
||||
return OPTIONAL_CODECS_PREF_UNKNOWN;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -858,18 +748,16 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
Log.e(TAG, "Invalid value passed to setOptionalCodecsEnabled: " + value);
|
||||
return;
|
||||
}
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
final IBluetoothA2dp service = getService();
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
mService.setOptionalCodecsEnabled(device, value);
|
||||
service.setOptionalCodecsEnabled(device, value);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -900,35 +788,6 @@ public final class BluetoothA2dp implements BluetoothProfile {
|
||||
}
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
mService = IBluetoothA2dp.Stub.asInterface(Binder.allowBlocking(service));
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.A2DP, BluetoothA2dp.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
mService = null;
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
|
||||
return false;
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
package android.bluetooth;
|
||||
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -124,93 +121,31 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
public static final String EXTRA_AUDIO_CONFIG =
|
||||
"android.bluetooth.a2dp-sink.profile.extra.AUDIO_CONFIG";
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private volatile IBluetoothA2dpSink mService;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private final BluetoothProfileConnector<IBluetoothA2dpSink> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.A2DP_SINK,
|
||||
"BluetoothA2dpSink", IBluetoothA2dpSink.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothA2dpSink getServiceInterface(IBinder service) {
|
||||
return IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothA2dp proxy object for interacting with the local
|
||||
* Bluetooth A2DP service.
|
||||
*/
|
||||
/*package*/ BluetoothA2dpSink(Context context, ServiceListener l) {
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
/*package*/ BluetoothA2dpSink(Context context, ServiceListener listener) {
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothA2dpSink.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
/*package*/ void close() {
|
||||
mServiceListener = null;
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IBluetoothA2dpSink getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,7 +176,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
*/
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) log("connect(" + device + ")");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.connect(device);
|
||||
@@ -282,7 +217,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.disconnect(device);
|
||||
@@ -301,7 +236,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (VDBG) log("getConnectedDevices()");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -320,7 +255,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (VDBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -339,7 +274,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (VDBG) log("getState(" + device + ")");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -365,7 +300,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
*/
|
||||
public BluetoothAudioConfig getAudioConfig(BluetoothDevice device) {
|
||||
if (VDBG) log("getAudioConfig(" + device + ")");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getAudioConfig(device);
|
||||
@@ -395,7 +330,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) log("setPriority(" + device + ", " + priority + ")");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
@@ -427,7 +362,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
*/
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) log("getPriority(" + device + ")");
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getPriority(device);
|
||||
@@ -448,7 +383,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
* @param device BluetoothDevice device
|
||||
*/
|
||||
public boolean isA2dpPlaying(BluetoothDevice device) {
|
||||
final IBluetoothA2dpSink service = mService;
|
||||
final IBluetoothA2dpSink service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.isA2dpPlaying(device);
|
||||
@@ -487,25 +422,6 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
|
||||
}
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
mService = IBluetoothA2dpSink.Stub.asInterface(Binder.allowBlocking(service));
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.A2DP_SINK,
|
||||
BluetoothA2dpSink.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP_SINK);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package android.bluetooth;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -79,93 +76,32 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
public static final String EXTRA_PLAYER_SETTING =
|
||||
"android.bluetooth.avrcp-controller.profile.extra.PLAYER_SETTING";
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private volatile IBluetoothAvrcpController mService;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private final BluetoothProfileConnector<IBluetoothAvrcpController> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.AVRCP_CONTROLLER,
|
||||
"BluetoothAvrcpController", IBluetoothAvrcpController.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothAvrcpController getServiceInterface(IBinder service) {
|
||||
return IBluetoothAvrcpController.Stub.asInterface(
|
||||
Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothAvrcpController proxy object for interacting with the local
|
||||
* Bluetooth AVRCP service.
|
||||
*/
|
||||
/*package*/ BluetoothAvrcpController(Context context, ServiceListener l) {
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
/*package*/ BluetoothAvrcpController(Context context, ServiceListener listener) {
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothAvrcpController.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth AVRCP Controller Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
/*package*/ void close() {
|
||||
mServiceListener = null;
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private IBluetoothAvrcpController getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -179,7 +115,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (VDBG) log("getConnectedDevices()");
|
||||
final IBluetoothAvrcpController service = mService;
|
||||
final IBluetoothAvrcpController service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -198,7 +135,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (VDBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothAvrcpController service = mService;
|
||||
final IBluetoothAvrcpController service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -217,7 +155,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (VDBG) log("getState(" + device + ")");
|
||||
final IBluetoothAvrcpController service = mService;
|
||||
final IBluetoothAvrcpController service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -238,7 +177,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
public BluetoothAvrcpPlayerSettings getPlayerSettings(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "getPlayerSettings");
|
||||
BluetoothAvrcpPlayerSettings settings = null;
|
||||
final IBluetoothAvrcpController service = mService;
|
||||
final IBluetoothAvrcpController service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
settings = service.getPlayerSettings(device);
|
||||
@@ -256,7 +196,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPlayerApplicationSetting(BluetoothAvrcpPlayerSettings plAppSetting) {
|
||||
if (DBG) Log.d(TAG, "setPlayerApplicationSetting");
|
||||
final IBluetoothAvrcpController service = mService;
|
||||
final IBluetoothAvrcpController service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.setPlayerApplicationSetting(plAppSetting);
|
||||
@@ -276,7 +217,8 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
public void sendGroupNavigationCmd(BluetoothDevice device, int keyCode, int keyState) {
|
||||
Log.d(TAG, "sendGroupNavigationCmd dev = " + device + " key " + keyCode + " State = "
|
||||
+ keyState);
|
||||
final IBluetoothAvrcpController service = mService;
|
||||
final IBluetoothAvrcpController service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
service.sendGroupNavigationCmd(device, keyCode, keyState);
|
||||
@@ -289,25 +231,6 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
mService = IBluetoothAvrcpController.Stub.asInterface(Binder.allowBlocking(service));
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.AVRCP_CONTROLLER,
|
||||
BluetoothAvrcpController.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.AVRCP_CONTROLLER);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
package android.bluetooth;
|
||||
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -366,73 +363,22 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
public static final int CALL_ACCEPT_HOLD = 1;
|
||||
public static final int CALL_ACCEPT_TERMINATE = 2;
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private volatile IBluetoothHeadsetClient mService;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
private final BluetoothProfileConnector<IBluetoothHeadsetClient> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.HEADSET_CLIENT,
|
||||
"BluetoothHeadsetClient", IBluetoothHeadsetClient.class.getName()) {
|
||||
@Override
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
Intent intent = new Intent(
|
||||
IBluetoothHeadsetClient.class.getName());
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
public IBluetoothHeadsetClient getServiceInterface(IBinder service) {
|
||||
return IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothHeadsetClient proxy object.
|
||||
*/
|
||||
/*package*/ BluetoothHeadsetClient(Context context, ServiceListener l) {
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
/*package*/ BluetoothHeadsetClient(Context context, ServiceListener listener) {
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothHeadsetClient.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth Headset Client Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,27 +389,11 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
/*package*/ void close() {
|
||||
if (VDBG) log("close()");
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
mServiceListener = null;
|
||||
private IBluetoothHeadsetClient getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,7 +410,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) log("connect(" + device + ")");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.connect(device);
|
||||
@@ -503,7 +434,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.disconnect(device);
|
||||
@@ -524,7 +456,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (VDBG) log("getConnectedDevices()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -547,7 +480,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (VDBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -569,7 +503,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (VDBG) log("getConnectionState(" + device + ")");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -589,7 +524,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) log("setPriority(" + device + ", " + priority + ")");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
@@ -611,7 +547,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) log("getPriority(" + device + ")");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getPriority(device);
|
||||
@@ -637,7 +574,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean startVoiceRecognition(BluetoothDevice device) {
|
||||
if (DBG) log("startVoiceRecognition()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.startVoiceRecognition(device);
|
||||
@@ -662,7 +600,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean stopVoiceRecognition(BluetoothDevice device) {
|
||||
if (DBG) log("stopVoiceRecognition()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.stopVoiceRecognition(device);
|
||||
@@ -682,7 +621,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
|
||||
if (DBG) log("getCurrentCalls()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getCurrentCalls(device);
|
||||
@@ -702,7 +642,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public Bundle getCurrentAgEvents(BluetoothDevice device) {
|
||||
if (DBG) log("getCurrentCalls()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getCurrentAgEvents(device);
|
||||
@@ -726,7 +667,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean acceptCall(BluetoothDevice device, int flag) {
|
||||
if (DBG) log("acceptCall()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.acceptCall(device, flag);
|
||||
@@ -747,7 +689,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean holdCall(BluetoothDevice device) {
|
||||
if (DBG) log("holdCall()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.holdCall(device);
|
||||
@@ -773,7 +716,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean rejectCall(BluetoothDevice device) {
|
||||
if (DBG) log("rejectCall()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.rejectCall(device);
|
||||
@@ -803,7 +747,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
|
||||
if (DBG) log("terminateCall()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.terminateCall(device, call);
|
||||
@@ -831,7 +776,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean enterPrivateMode(BluetoothDevice device, int index) {
|
||||
if (DBG) log("enterPrivateMode()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.enterPrivateMode(device, index);
|
||||
@@ -858,7 +804,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean explicitCallTransfer(BluetoothDevice device) {
|
||||
if (DBG) log("explicitCallTransfer()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.explicitCallTransfer(device);
|
||||
@@ -881,7 +828,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
|
||||
if (DBG) log("dial()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.dial(device, number);
|
||||
@@ -905,7 +853,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean sendDTMF(BluetoothDevice device, byte code) {
|
||||
if (DBG) log("sendDTMF()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.sendDTMF(device, code);
|
||||
@@ -931,7 +880,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean getLastVoiceTagNumber(BluetoothDevice device) {
|
||||
if (DBG) log("getLastVoiceTagNumber()");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getLastVoiceTagNumber(device);
|
||||
@@ -951,7 +901,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public int getAudioState(BluetoothDevice device) {
|
||||
if (VDBG) log("getAudioState");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getAudioState(device);
|
||||
@@ -974,7 +925,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public void setAudioRouteAllowed(BluetoothDevice device, boolean allowed) {
|
||||
if (VDBG) log("setAudioRouteAllowed");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
service.setAudioRouteAllowed(device, allowed);
|
||||
@@ -996,7 +948,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean getAudioRouteAllowed(BluetoothDevice device) {
|
||||
if (VDBG) log("getAudioRouteAllowed");
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getAudioRouteAllowed(device);
|
||||
@@ -1020,7 +973,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
|
||||
*/
|
||||
public boolean connectAudio(BluetoothDevice device) {
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.connectAudio(device);
|
||||
@@ -1044,7 +998,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
* otherwise; upon completion HFP sends {@link #ACTION_AUDIO_STATE_CHANGED} intent;
|
||||
*/
|
||||
public boolean disconnectAudio(BluetoothDevice device) {
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.disconnectAudio(device);
|
||||
@@ -1065,7 +1020,8 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
* @return bundle of AG features; null if no service or AG not connected
|
||||
*/
|
||||
public Bundle getCurrentAgFeatures(BluetoothDevice device) {
|
||||
final IBluetoothHeadsetClient service = mService;
|
||||
final IBluetoothHeadsetClient service =
|
||||
getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getCurrentAgFeatures(device);
|
||||
@@ -1079,29 +1035,6 @@ public final class BluetoothHeadsetClient implements BluetoothProfile {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
mService = IBluetoothHeadsetClient.Stub.asInterface(Binder.allowBlocking(service));
|
||||
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.HEADSET_CLIENT,
|
||||
BluetoothHeadsetClient.this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET_CLIENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
|
||||
}
|
||||
|
||||
@@ -22,20 +22,14 @@ import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
/**
|
||||
* This class provides the public APIs to control the Hearing Aid profile.
|
||||
@@ -128,97 +122,31 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
*/
|
||||
public static final long HI_SYNC_ID_INVALID = IBluetoothHearingAid.HI_SYNC_ID_INVALID;
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();
|
||||
@GuardedBy("mServiceLock")
|
||||
private IBluetoothHearingAid mService;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
private final BluetoothProfileConnector<IBluetoothHearingAid> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.HEARING_AID,
|
||||
"BluetoothHearingAid", IBluetoothHearingAid.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothHearingAid getServiceInterface(IBinder service) {
|
||||
return IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothHearingAid proxy object for interacting with the local
|
||||
* Bluetooth Hearing Aid service.
|
||||
*/
|
||||
/*package*/ BluetoothHearingAid(Context context, ServiceListener l) {
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
/*package*/ BluetoothHearingAid(Context context, ServiceListener listener) {
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
doBind();
|
||||
}
|
||||
|
||||
void doBind() {
|
||||
Intent intent = new Intent(IBluetoothHearingAid.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
android.os.Process.myUserHandle())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth Hearing Aid Service with " + intent);
|
||||
return;
|
||||
}
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
/*package*/ void close() {
|
||||
mServiceListener = null;
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
if (mService != null) {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
private IBluetoothHearingAid getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,18 +168,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
*/
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) log("connect(" + device + ")");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
return mService.connect(device);
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
return service.connect(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,18 +208,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
*/
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled() && isValidDevice(device)) {
|
||||
return mService.disconnect(device);
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
return service.disconnect(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,18 +227,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
@Override
|
||||
public @NonNull List<BluetoothDevice> getConnectedDevices() {
|
||||
if (VDBG) log("getConnectedDevices()");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getConnectedDevices();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getConnectedDevices();
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,18 +247,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
|
||||
@NonNull int[] states) {
|
||||
if (VDBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getDevicesMatchingConnectionStates(states);
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return new ArrayList<BluetoothDevice>();
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,19 +267,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
public @BluetoothProfile.BtProfileState int getConnectionState(
|
||||
@NonNull BluetoothDevice device) {
|
||||
if (VDBG) log("getState(" + device + ")");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
return mService.getConnectionState(device);
|
||||
return service.getConnectionState(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return BluetoothProfile.STATE_DISCONNECTED;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return BluetoothProfile.STATE_DISCONNECTED;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -387,20 +305,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setActiveDevice(@Nullable BluetoothDevice device) {
|
||||
if (DBG) log("setActiveDevice(" + device + ")");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
if (service != null && isEnabled()
|
||||
&& ((device == null) || isValidDevice(device))) {
|
||||
mService.setActiveDevice(device);
|
||||
service.setActiveDevice(device);
|
||||
return true;
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,18 +334,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
@RequiresPermission(Manifest.permission.BLUETOOTH)
|
||||
public List<BluetoothDevice> getActiveDevices() {
|
||||
if (VDBG) log("getActiveDevices()");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getActiveDevices();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getActiveDevices();
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return new ArrayList<>();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return new ArrayList<>();
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,23 +364,21 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) log("setPriority(" + device + ", " + priority + ")");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
return false;
|
||||
}
|
||||
return mService.setPriority(device, priority);
|
||||
return service.setPriority(device, priority);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return false;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return false;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,19 +396,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
@RequiresPermission(Manifest.permission.BLUETOOTH)
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) log("getPriority(" + device + ")");
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
return mService.getPriority(device);
|
||||
return service.getPriority(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return BluetoothProfile.PRIORITY_OFF;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return BluetoothProfile.PRIORITY_OFF;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,18 +445,16 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
if (VDBG) {
|
||||
log("getVolume()");
|
||||
}
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()) {
|
||||
return mService.getVolume();
|
||||
if (service != null && isEnabled()) {
|
||||
return service.getVolume();
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return 0;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return 0;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,21 +474,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
public void adjustVolume(int direction) {
|
||||
if (DBG) log("adjustVolume(" + direction + ")");
|
||||
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
|
||||
if (mService == null) {
|
||||
if (service == null) {
|
||||
Log.w(TAG, "Proxy not attached to service");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isEnabled()) return;
|
||||
|
||||
mService.adjustVolume(direction);
|
||||
service.adjustVolume(direction);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,20 +498,18 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
public void setVolume(int volume) {
|
||||
if (DBG) Log.d(TAG, "setVolume(" + volume + ")");
|
||||
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService == null) {
|
||||
if (service == null) {
|
||||
Log.w(TAG, "Proxy not attached to service");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isEnabled()) return;
|
||||
|
||||
mService.setVolume(volume);
|
||||
service.setVolume(volume);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,21 +525,19 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
if (VDBG) {
|
||||
log("getCustomerId(" + device + ")");
|
||||
}
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService == null) {
|
||||
if (service == null) {
|
||||
Log.w(TAG, "Proxy not attached to service");
|
||||
return HI_SYNC_ID_INVALID;
|
||||
}
|
||||
|
||||
if (!isEnabled() || !isValidDevice(device)) return HI_SYNC_ID_INVALID;
|
||||
|
||||
return mService.getHiSyncId(device);
|
||||
return service.getHiSyncId(device);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return HI_SYNC_ID_INVALID;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,19 +553,17 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
if (VDBG) {
|
||||
log("getDeviceSide(" + device + ")");
|
||||
}
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
return mService.getDeviceSide(device);
|
||||
return service.getDeviceSide(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return SIDE_LEFT;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return SIDE_LEFT;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,52 +579,20 @@ public final class BluetoothHearingAid implements BluetoothProfile {
|
||||
if (VDBG) {
|
||||
log("getDeviceMode(" + device + ")");
|
||||
}
|
||||
final IBluetoothHearingAid service = getService();
|
||||
try {
|
||||
mServiceLock.readLock().lock();
|
||||
if (mService != null && isEnabled()
|
||||
if (service != null && isEnabled()
|
||||
&& isValidDevice(device)) {
|
||||
return mService.getDeviceMode(device);
|
||||
return service.getDeviceMode(device);
|
||||
}
|
||||
if (mService == null) Log.w(TAG, "Proxy not attached to service");
|
||||
if (service == null) Log.w(TAG, "Proxy not attached to service");
|
||||
return MODE_MONAURAL;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
|
||||
return MODE_MONAURAL;
|
||||
} finally {
|
||||
mServiceLock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
mService = IBluetoothHearingAid.Stub.asInterface(Binder.allowBlocking(service));
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.HEARING_AID,
|
||||
BluetoothHearingAid.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
try {
|
||||
mServiceLock.writeLock().lock();
|
||||
mService = null;
|
||||
} finally {
|
||||
mServiceLock.writeLock().unlock();
|
||||
}
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.HEARING_AID);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
if (mAdapter.getState() == BluetoothAdapter.STATE_ON) return true;
|
||||
return false;
|
||||
|
||||
@@ -18,10 +18,8 @@ package android.bluetooth;
|
||||
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
@@ -327,11 +325,6 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
}
|
||||
}
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private volatile IBluetoothHidDevice mService;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
private static class CallbackWrapper extends IBluetoothHidDeviceCallback.Stub {
|
||||
|
||||
private final Executor mExecutor;
|
||||
@@ -385,114 +378,33 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
}
|
||||
}
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
synchronized (mConnection) {
|
||||
if (up) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
Log.d(TAG, "Binding HID Device service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
|
||||
+ "service: ", e);
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "onBluetoothStateChange: could not bind to HID Dev "
|
||||
+ "service: ", e);
|
||||
}
|
||||
} else {
|
||||
Log.d(TAG, "Unbinding service...");
|
||||
doUnbind();
|
||||
}
|
||||
}
|
||||
private BluetoothAdapter mAdapter;
|
||||
private final BluetoothProfileConnector<IBluetoothHidDevice> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.HID_DEVICE,
|
||||
"BluetoothHidDevice", IBluetoothHidDevice.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothHidDevice getServiceInterface(IBinder service) {
|
||||
return IBluetoothHidDevice.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
|
||||
private final ServiceConnection mConnection =
|
||||
new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
Log.d(TAG, "onServiceConnected()");
|
||||
mService = IBluetoothHidDevice.Stub.asInterface(service);
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(
|
||||
BluetoothProfile.HID_DEVICE, BluetoothHidDevice.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
Log.d(TAG, "onServiceDisconnected()");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.HID_DEVICE);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
BluetoothHidDevice(Context context, ServiceListener listener) {
|
||||
mContext = context;
|
||||
mServiceListener = listener;
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothHidDevice.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth HID Device Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
Log.d(TAG, "Bound to HID Device Service");
|
||||
return true;
|
||||
}
|
||||
|
||||
void doUnbind() {
|
||||
if (mService != null) {
|
||||
mService = null;
|
||||
try {
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.e(TAG, "Unable to unbind HidDevService", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
void close() {
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
doUnbind();
|
||||
}
|
||||
mServiceListener = null;
|
||||
private IBluetoothHidDevice getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -509,7 +421,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -526,7 +438,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -583,7 +495,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
throw new IllegalArgumentException("callback parameter cannot be null");
|
||||
}
|
||||
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
CallbackWrapper cbw = new CallbackWrapper(executor, callback);
|
||||
@@ -611,7 +523,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
public boolean unregisterApp() {
|
||||
boolean result = false;
|
||||
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
result = service.unregisterApp();
|
||||
@@ -636,7 +548,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
public boolean sendReport(BluetoothDevice device, int id, byte[] data) {
|
||||
boolean result = false;
|
||||
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
result = service.sendReport(device, id, data);
|
||||
@@ -662,7 +574,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
public boolean replyReport(BluetoothDevice device, byte type, byte id, byte[] data) {
|
||||
boolean result = false;
|
||||
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
result = service.replyReport(device, type, id, data);
|
||||
@@ -686,7 +598,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
public boolean reportError(BluetoothDevice device, byte error) {
|
||||
boolean result = false;
|
||||
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
result = service.reportError(device, error);
|
||||
@@ -707,7 +619,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
* {@hide}
|
||||
*/
|
||||
public String getUserAppName() {
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
|
||||
if (service != null) {
|
||||
try {
|
||||
@@ -733,7 +645,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
boolean result = false;
|
||||
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
result = service.connect(device);
|
||||
@@ -757,7 +669,7 @@ public final class BluetoothHidDevice implements BluetoothProfile {
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
boolean result = false;
|
||||
|
||||
final IBluetoothHidDevice service = mService;
|
||||
final IBluetoothHidDevice service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
result = service.disconnect(device);
|
||||
|
||||
@@ -18,10 +18,7 @@ package android.bluetooth;
|
||||
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -219,97 +216,32 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
public static final String EXTRA_IDLE_TIME =
|
||||
"android.bluetooth.BluetoothHidHost.extra.IDLE_TIME";
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private BluetoothAdapter mAdapter;
|
||||
private volatile IBluetoothHidHost mService;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService != null) {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private final BluetoothProfileConnector<IBluetoothHidHost> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.HID_HOST,
|
||||
"BluetoothHidHost", IBluetoothHidHost.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothHidHost getServiceInterface(IBinder service) {
|
||||
return IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothHidHost proxy object for interacting with the local
|
||||
* Bluetooth Service which handles the InputDevice profile
|
||||
*/
|
||||
/*package*/ BluetoothHidHost(Context context, ServiceListener l) {
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
/*package*/ BluetoothHidHost(Context context, ServiceListener listener) {
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothHidHost.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth HID Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
/*package*/ void close() {
|
||||
if (VDBG) log("close()");
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
mServiceListener = null;
|
||||
private IBluetoothHidHost getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -333,7 +265,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) log("connect(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.connect(device);
|
||||
@@ -373,7 +305,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.disconnect(device);
|
||||
@@ -392,7 +324,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (VDBG) log("getConnectedDevices()");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -411,7 +343,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (VDBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -430,7 +362,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (VDBG) log("getState(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -460,7 +392,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) log("setPriority(" + device + ", " + priority + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
@@ -492,7 +424,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) log("getPriority(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getPriority(device);
|
||||
@@ -505,26 +437,6 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
return BluetoothProfile.PRIORITY_OFF;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
mService = IBluetoothHidHost.Stub.asInterface(Binder.allowBlocking(service));
|
||||
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.HID_HOST,
|
||||
BluetoothHidHost.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.HID_HOST);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
|
||||
}
|
||||
@@ -544,7 +456,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean virtualUnplug(BluetoothDevice device) {
|
||||
if (DBG) log("virtualUnplug(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.virtualUnplug(device);
|
||||
@@ -570,7 +482,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean getProtocolMode(BluetoothDevice device) {
|
||||
if (VDBG) log("getProtocolMode(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getProtocolMode(device);
|
||||
@@ -594,7 +506,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setProtocolMode(BluetoothDevice device, int protocolMode) {
|
||||
if (DBG) log("setProtocolMode(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.setProtocolMode(device, protocolMode);
|
||||
@@ -625,7 +537,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
log("getReport(" + device + "), reportType=" + reportType + " reportId=" + reportId
|
||||
+ "bufferSize=" + bufferSize);
|
||||
}
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getReport(device, reportType, reportId, bufferSize);
|
||||
@@ -651,7 +563,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setReport(BluetoothDevice device, byte reportType, String report) {
|
||||
if (VDBG) log("setReport(" + device + "), reportType=" + reportType + " report=" + report);
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.setReport(device, reportType, report);
|
||||
@@ -676,7 +588,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean sendData(BluetoothDevice device, String report) {
|
||||
if (DBG) log("sendData(" + device + "), report=" + report);
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.sendData(device, report);
|
||||
@@ -700,7 +612,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean getIdleTime(BluetoothDevice device) {
|
||||
if (DBG) log("getIdletime(" + device + ")");
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getIdleTime(device);
|
||||
@@ -725,7 +637,7 @@ public final class BluetoothHidHost implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setIdleTime(BluetoothDevice device, byte idleTime) {
|
||||
if (DBG) log("setIdletime(" + device + "), idleTime=" + idleTime);
|
||||
final IBluetoothHidHost service = mService;
|
||||
final IBluetoothHidHost service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.setIdleTime(device, idleTime);
|
||||
|
||||
@@ -17,10 +17,7 @@
|
||||
package android.bluetooth;
|
||||
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -44,11 +41,6 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
public static final String ACTION_CONNECTION_STATE_CHANGED =
|
||||
"android.bluetooth.map.profile.action.CONNECTION_STATE_CHANGED";
|
||||
|
||||
private volatile IBluetoothMap mService;
|
||||
private final Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
/** There was an error trying to obtain the state */
|
||||
public static final int STATE_ERROR = -1;
|
||||
|
||||
@@ -57,64 +49,23 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
/** Connection canceled before completion. */
|
||||
public static final int RESULT_CANCELED = 2;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private BluetoothAdapter mAdapter;
|
||||
private final BluetoothProfileConnector<IBluetoothMap> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.MAP,
|
||||
"BluetoothMap", IBluetoothMap.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothMap getServiceInterface(IBinder service) {
|
||||
return IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothMap proxy object.
|
||||
*/
|
||||
/*package*/ BluetoothMap(Context context, ServiceListener l) {
|
||||
/*package*/ BluetoothMap(Context context, ServiceListener listener) {
|
||||
if (DBG) Log.d(TAG, "Create BluetoothMap proxy object");
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothMap.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth MAP Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
@@ -132,26 +83,11 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
* are ok.
|
||||
*/
|
||||
public synchronized void close() {
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
mServiceListener = null;
|
||||
private IBluetoothMap getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +98,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public int getState() {
|
||||
if (VDBG) log("getState()");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getState();
|
||||
@@ -184,7 +120,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public BluetoothDevice getClient() {
|
||||
if (VDBG) log("getClient()");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getClient();
|
||||
@@ -205,7 +141,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public boolean isConnected(BluetoothDevice device) {
|
||||
if (VDBG) log("isConnected(" + device + ")");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.isConnected(device);
|
||||
@@ -237,7 +173,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.disconnect(device);
|
||||
@@ -278,7 +214,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (DBG) log("getConnectedDevices()");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -298,7 +234,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (DBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -318,7 +254,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (DBG) log("getConnectionState(" + device + ")");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -344,7 +280,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) log("setPriority(" + device + ", " + priority + ")");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
@@ -373,7 +309,7 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
*/
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) log("getPriority(" + device + ")");
|
||||
final IBluetoothMap service = mService;
|
||||
final IBluetoothMap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getPriority(device);
|
||||
@@ -386,24 +322,6 @@ public final class BluetoothMap implements BluetoothProfile {
|
||||
return PRIORITY_OFF;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) log("Proxy object connected");
|
||||
mService = IBluetoothMap.Stub.asInterface(Binder.allowBlocking(service));
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.MAP, BluetoothMap.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) log("Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.MAP);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static void log(String msg) {
|
||||
Log.d(TAG, msg);
|
||||
}
|
||||
|
||||
@@ -18,11 +18,9 @@ package android.bluetooth;
|
||||
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.net.Uri;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
@@ -60,11 +58,6 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
public static final String EXTRA_SENDER_CONTACT_NAME =
|
||||
"android.bluetooth.mapmce.profile.extra.SENDER_CONTACT_NAME";
|
||||
|
||||
private volatile IBluetoothMapClient mService;
|
||||
private final Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
/** There was an error trying to obtain the state */
|
||||
public static final int STATE_ERROR = -1;
|
||||
|
||||
@@ -75,64 +68,23 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
|
||||
private static final int UPLOADING_FEATURE_BITMASK = 0x08;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private BluetoothAdapter mAdapter;
|
||||
private final BluetoothProfileConnector<IBluetoothMapClient> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.MAP_CLIENT,
|
||||
"BluetoothMapClient", IBluetoothMapClient.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothMapClient getServiceInterface(IBinder service) {
|
||||
return IBluetoothMapClient.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothMapClient proxy object.
|
||||
*/
|
||||
/*package*/ BluetoothMapClient(Context context, ServiceListener l) {
|
||||
/*package*/ BluetoothMapClient(Context context, ServiceListener listener) {
|
||||
if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothMapClient.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
@@ -150,26 +102,11 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
* are ok.
|
||||
*/
|
||||
public void close() {
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
mServiceListener = null;
|
||||
private IBluetoothMapClient getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,7 +116,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean isConnected(BluetoothDevice device) {
|
||||
if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.isConnected(device);
|
||||
@@ -199,7 +136,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.connect(device);
|
||||
@@ -221,7 +158,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "disconnect(" + device + ")");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.disconnect(device);
|
||||
@@ -241,7 +178,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (DBG) Log.d(TAG, "getConnectedDevices()");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -262,7 +199,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -283,7 +220,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -307,7 +244,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
@@ -336,7 +273,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
*/
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getPriority(device);
|
||||
@@ -365,7 +302,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
|
||||
PendingIntent sentIntent, PendingIntent deliveredIntent) {
|
||||
if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
|
||||
@@ -385,7 +322,7 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
*/
|
||||
public boolean getUnreadMessages(BluetoothDevice device) {
|
||||
if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
|
||||
final IBluetoothMapClient service = mService;
|
||||
final IBluetoothMapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getUnreadMessages(device);
|
||||
@@ -405,34 +342,16 @@ public final class BluetoothMapClient implements BluetoothProfile {
|
||||
* MapSupportedFeatures field is set. False is returned otherwise.
|
||||
*/
|
||||
public boolean isUploadingSupported(BluetoothDevice device) {
|
||||
final IBluetoothMapClient service = getService();
|
||||
try {
|
||||
return (mService != null && isEnabled() && isValidDevice(device))
|
||||
&& ((mService.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
|
||||
return (service != null && isEnabled() && isValidDevice(device))
|
||||
&& ((service.getSupportedFeatures(device) & UPLOADING_FEATURE_BITMASK) > 0);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "Proxy object connected");
|
||||
mService = IBluetoothMapClient.Stub.asInterface(service);
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT,
|
||||
BluetoothMapClient.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isEnabled() {
|
||||
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||
if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
|
||||
|
||||
@@ -19,10 +19,7 @@ package android.bluetooth;
|
||||
import android.annotation.SdkConstant;
|
||||
import android.annotation.SdkConstant.SdkConstantType;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -121,108 +118,42 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
*/
|
||||
public static final int PAN_OPERATION_SUCCESS = 1004;
|
||||
|
||||
private Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private BluetoothAdapter mAdapter;
|
||||
private volatile IBluetoothPan mPanService;
|
||||
private final BluetoothProfileConnector<IBluetoothPan> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.PAN,
|
||||
"BluetoothPan", IBluetoothPan.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothPan getServiceInterface(IBinder service) {
|
||||
return IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a BluetoothPan proxy object for interacting with the local
|
||||
* Bluetooth Service which handles the Pan profile
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
/*package*/ BluetoothPan(Context context, ServiceListener l) {
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
/*package*/ BluetoothPan(Context context, ServiceListener listener) {
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
try {
|
||||
mAdapter.getBluetoothManager().registerStateChangeCallback(mStateChangeCallback);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Unable to register BluetoothStateChangeCallback", re);
|
||||
}
|
||||
if (VDBG) Log.d(TAG, "BluetoothPan() call bindService");
|
||||
doBind();
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothPan.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth Pan Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
/*package*/ void close() {
|
||||
if (VDBG) log("close()");
|
||||
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mStateChangeCallback);
|
||||
} catch (RemoteException re) {
|
||||
Log.w(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mPanService != null) {
|
||||
try {
|
||||
mPanService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
mServiceListener = null;
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
private IBluetoothPan getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
|
||||
protected void finalize() {
|
||||
close();
|
||||
}
|
||||
|
||||
private final IBluetoothStateChangeCallback mStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
|
||||
@Override
|
||||
public void onBluetoothStateChange(boolean on) {
|
||||
// Handle enable request to bind again.
|
||||
Log.d(TAG, "onBluetoothStateChange on: " + on);
|
||||
if (on) {
|
||||
try {
|
||||
if (mPanService == null) {
|
||||
if (VDBG) Log.d(TAG, "onBluetoothStateChange calling doBind()");
|
||||
doBind();
|
||||
}
|
||||
|
||||
} catch (IllegalStateException e) {
|
||||
Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
|
||||
e);
|
||||
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "onBluetoothStateChange: could not bind to PAN service: ",
|
||||
e);
|
||||
}
|
||||
} else {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mPanService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initiate connection to a profile of the remote bluetooth device.
|
||||
*
|
||||
@@ -243,7 +174,7 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean connect(BluetoothDevice device) {
|
||||
if (DBG) log("connect(" + device + ")");
|
||||
final IBluetoothPan service = mPanService;
|
||||
final IBluetoothPan service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.connect(device);
|
||||
@@ -284,7 +215,7 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
final IBluetoothPan service = mPanService;
|
||||
final IBluetoothPan service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.disconnect(device);
|
||||
@@ -303,7 +234,7 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (VDBG) log("getConnectedDevices()");
|
||||
final IBluetoothPan service = mPanService;
|
||||
final IBluetoothPan service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -322,7 +253,7 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
@Override
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (VDBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothPan service = mPanService;
|
||||
final IBluetoothPan service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -341,7 +272,7 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
@Override
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (VDBG) log("getState(" + device + ")");
|
||||
final IBluetoothPan service = mPanService;
|
||||
final IBluetoothPan service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -357,7 +288,7 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public void setBluetoothTethering(boolean value) {
|
||||
if (DBG) log("setBluetoothTethering(" + value + ")");
|
||||
final IBluetoothPan service = mPanService;
|
||||
final IBluetoothPan service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
service.setBluetoothTethering(value);
|
||||
@@ -370,7 +301,7 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean isTetheringOn() {
|
||||
if (VDBG) log("isTetheringOn()");
|
||||
final IBluetoothPan service = mPanService;
|
||||
final IBluetoothPan service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.isTetheringOn();
|
||||
@@ -381,25 +312,6 @@ public final class BluetoothPan implements BluetoothProfile {
|
||||
return false;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) Log.d(TAG, "BluetoothPAN Proxy object connected");
|
||||
mPanService = IBluetoothPan.Stub.asInterface(Binder.allowBlocking(service));
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.PAN,
|
||||
BluetoothPan.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) Log.d(TAG, "BluetoothPAN Proxy object disconnected");
|
||||
mPanService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.PAN);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@UnsupportedAppUsage
|
||||
private boolean isEnabled() {
|
||||
return mAdapter.getState() == BluetoothAdapter.STATE_ON;
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -117,28 +118,9 @@ public class BluetoothPbap implements BluetoothProfile {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
log("onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
log("Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService != null) {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
doUnbind();
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
log("Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -154,25 +136,51 @@ public class BluetoothPbap implements BluetoothProfile {
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
} catch (RemoteException re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothPbap.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
|
||||
return false;
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
log("Binding service...");
|
||||
Intent intent = new Intent(IBluetoothPbap.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(
|
||||
mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
UserHandle.CURRENT_OR_SELF)) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth Pbap Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
Log.e(TAG, "", se);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doUnbind() {
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
log("Unbinding service...");
|
||||
try {
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (IllegalArgumentException ie) {
|
||||
Log.e(TAG, "", ie);
|
||||
} finally {
|
||||
mService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
close();
|
||||
@@ -192,21 +200,11 @@ public class BluetoothPbap implements BluetoothProfile {
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
} catch (RemoteException re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
doUnbind();
|
||||
mServiceListener = null;
|
||||
}
|
||||
|
||||
@@ -312,7 +310,7 @@ public class BluetoothPbap implements BluetoothProfile {
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
log("Proxy object disconnected");
|
||||
mService = null;
|
||||
doUnbind();
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected();
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package android.bluetooth;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -42,11 +39,6 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
public static final String ACTION_CONNECTION_STATE_CHANGED =
|
||||
"android.bluetooth.pbapclient.profile.action.CONNECTION_STATE_CHANGED";
|
||||
|
||||
private volatile IBluetoothPbapClient mService;
|
||||
private final Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
/** There was an error trying to obtain the state */
|
||||
public static final int STATE_ERROR = -1;
|
||||
|
||||
@@ -55,72 +47,25 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
/** Connection canceled before completion. */
|
||||
public static final int RESULT_CANCELED = 2;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) {
|
||||
Log.d(TAG, "onBluetoothStateChange: PBAP CLIENT up=" + up);
|
||||
}
|
||||
if (!up) {
|
||||
if (VDBG) {
|
||||
Log.d(TAG, "Unbinding service...");
|
||||
}
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) {
|
||||
Log.d(TAG, "Binding service...");
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private BluetoothAdapter mAdapter;
|
||||
private final BluetoothProfileConnector<IBluetoothPbapClient> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.PBAP_CLIENT,
|
||||
"BluetoothPbapClient", IBluetoothPbapClient.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothPbapClient getServiceInterface(IBinder service) {
|
||||
return IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothPbapClient proxy object.
|
||||
*/
|
||||
BluetoothPbapClient(Context context, ServiceListener l) {
|
||||
BluetoothPbapClient(Context context, ServiceListener listener) {
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Create BluetoothPbapClient proxy object");
|
||||
}
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
|
||||
private boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothPbapClient.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth PBAP Client Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
@@ -138,26 +83,11 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
* are ok.
|
||||
*/
|
||||
public synchronized void close() {
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
mServiceListener = null;
|
||||
private IBluetoothPbapClient getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +103,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
if (DBG) {
|
||||
log("connect(" + device + ") for PBAP Client.");
|
||||
}
|
||||
final IBluetoothPbapClient service = mService;
|
||||
final IBluetoothPbapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.connect(device);
|
||||
@@ -198,7 +128,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
if (DBG) {
|
||||
log("disconnect(" + device + ")" + new Exception());
|
||||
}
|
||||
final IBluetoothPbapClient service = mService;
|
||||
final IBluetoothPbapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
service.disconnect(device);
|
||||
@@ -225,7 +155,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
if (DBG) {
|
||||
log("getConnectedDevices()");
|
||||
}
|
||||
final IBluetoothPbapClient service = mService;
|
||||
final IBluetoothPbapClient service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -250,7 +180,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
if (DBG) {
|
||||
log("getDevicesMatchingStates()");
|
||||
}
|
||||
final IBluetoothPbapClient service = mService;
|
||||
final IBluetoothPbapClient service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -275,7 +205,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
if (DBG) {
|
||||
log("getConnectionState(" + device + ")");
|
||||
}
|
||||
final IBluetoothPbapClient service = mService;
|
||||
final IBluetoothPbapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -290,29 +220,6 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
return BluetoothProfile.STATE_DISCONNECTED;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) {
|
||||
log("Proxy object connected");
|
||||
}
|
||||
mService = IBluetoothPbapClient.Stub.asInterface(Binder.allowBlocking(service));
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.PBAP_CLIENT,
|
||||
BluetoothPbapClient.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) {
|
||||
log("Proxy object disconnected");
|
||||
}
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.PBAP_CLIENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static void log(String msg) {
|
||||
Log.d(TAG, msg);
|
||||
}
|
||||
@@ -345,7 +252,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
if (DBG) {
|
||||
log("setPriority(" + device + ", " + priority + ")");
|
||||
}
|
||||
final IBluetoothPbapClient service = mService;
|
||||
final IBluetoothPbapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
@@ -378,7 +285,7 @@ public final class BluetoothPbapClient implements BluetoothProfile {
|
||||
if (VDBG) {
|
||||
log("getPriority(" + device + ")");
|
||||
}
|
||||
final IBluetoothPbapClient service = mService;
|
||||
final IBluetoothPbapClient service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getPriority(device);
|
||||
|
||||
166
core/java/android/bluetooth/BluetoothProfileConnector.java
Normal file
166
core/java/android/bluetooth/BluetoothProfileConnector.java
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.bluetooth;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Connector for Bluetooth profile proxies to bind manager service and
|
||||
* profile services
|
||||
* @param <T> The Bluetooth profile interface for this connection.
|
||||
* @hide
|
||||
*/
|
||||
public abstract class BluetoothProfileConnector<T> {
|
||||
private int mProfileId;
|
||||
private BluetoothProfile.ServiceListener mServiceListener;
|
||||
private BluetoothProfile mProfileProxy;
|
||||
private Context mContext;
|
||||
private String mProfileName;
|
||||
private String mServiceName;
|
||||
private volatile T mService;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (up) {
|
||||
doBind();
|
||||
} else {
|
||||
doUnbind();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
logDebug("Proxy object connected");
|
||||
mService = getServiceInterface(service);
|
||||
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(mProfileId, mProfileProxy);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
logDebug("Proxy object disconnected");
|
||||
doUnbind();
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
BluetoothProfileConnector(BluetoothProfile profile, int profileId, String profileName,
|
||||
String serviceName) {
|
||||
mProfileId = profileId;
|
||||
mProfileProxy = profile;
|
||||
mProfileName = profileName;
|
||||
mServiceName = serviceName;
|
||||
}
|
||||
|
||||
private boolean doBind() {
|
||||
synchronized (mConnection) {
|
||||
if (mService == null) {
|
||||
logDebug("Binding service...");
|
||||
try {
|
||||
Intent intent = new Intent(mServiceName);
|
||||
ComponentName comp = intent.resolveSystemService(
|
||||
mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
UserHandle.CURRENT_OR_SELF)) {
|
||||
logError("Could not bind to Bluetooth Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
logError("Failed to bind service. " + se);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doUnbind() {
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
logDebug("Unbinding service...");
|
||||
try {
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (IllegalArgumentException ie) {
|
||||
logError("Unable to unbind service: " + ie);
|
||||
} finally {
|
||||
mService = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void connect(Context context, BluetoothProfile.ServiceListener listener) {
|
||||
mContext = context;
|
||||
mServiceListener = listener;
|
||||
IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException re) {
|
||||
logError("Failed to register state change callback. " + re);
|
||||
}
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
|
||||
void disconnect() {
|
||||
mServiceListener = null;
|
||||
IBluetoothManager mgr = BluetoothAdapter.getDefaultAdapter().getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException re) {
|
||||
logError("Failed to unregister state change callback" + re);
|
||||
}
|
||||
}
|
||||
doUnbind();
|
||||
}
|
||||
|
||||
T getService() {
|
||||
return mService;
|
||||
}
|
||||
|
||||
/**
|
||||
* This abstract function is used to implement method to get the
|
||||
* connected Bluetooth service interface.
|
||||
* @param service the connected binder service.
|
||||
* @return T the binder interface of {@code service}.
|
||||
* @hide
|
||||
*/
|
||||
public abstract T getServiceInterface(IBinder service);
|
||||
|
||||
private void logDebug(String log) {
|
||||
Log.d(mProfileName, log);
|
||||
}
|
||||
|
||||
private void logError(String log) {
|
||||
Log.e(mProfileName, log);
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,7 @@
|
||||
package android.bluetooth;
|
||||
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
@@ -69,11 +66,6 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
public static final String ACTION_CONNECTION_STATE_CHANGED =
|
||||
"android.bluetooth.sap.profile.action.CONNECTION_STATE_CHANGED";
|
||||
|
||||
private volatile IBluetoothSap mService;
|
||||
private final Context mContext;
|
||||
private ServiceListener mServiceListener;
|
||||
private BluetoothAdapter mAdapter;
|
||||
|
||||
/**
|
||||
* There was an error trying to obtain the state.
|
||||
*
|
||||
@@ -95,64 +87,23 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public static final int RESULT_CANCELED = 2;
|
||||
|
||||
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
|
||||
new IBluetoothStateChangeCallback.Stub() {
|
||||
public void onBluetoothStateChange(boolean up) {
|
||||
if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
|
||||
if (!up) {
|
||||
if (VDBG) Log.d(TAG, "Unbinding service...");
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
synchronized (mConnection) {
|
||||
try {
|
||||
if (mService == null) {
|
||||
if (VDBG) Log.d(TAG, "Binding service...");
|
||||
doBind();
|
||||
}
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
private BluetoothAdapter mAdapter;
|
||||
private final BluetoothProfileConnector<IBluetoothSap> mProfileConnector =
|
||||
new BluetoothProfileConnector(this, BluetoothProfile.SAP,
|
||||
"BluetoothSap", IBluetoothSap.class.getName()) {
|
||||
@Override
|
||||
public IBluetoothSap getServiceInterface(IBinder service) {
|
||||
return IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a BluetoothSap proxy object.
|
||||
*/
|
||||
/*package*/ BluetoothSap(Context context, ServiceListener l) {
|
||||
/*package*/ BluetoothSap(Context context, ServiceListener listener) {
|
||||
if (DBG) Log.d(TAG, "Create BluetoothSap proxy object");
|
||||
mContext = context;
|
||||
mServiceListener = l;
|
||||
mAdapter = BluetoothAdapter.getDefaultAdapter();
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
doBind();
|
||||
}
|
||||
|
||||
boolean doBind() {
|
||||
Intent intent = new Intent(IBluetoothSap.class.getName());
|
||||
ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
|
||||
intent.setComponent(comp);
|
||||
if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
|
||||
mContext.getUser())) {
|
||||
Log.e(TAG, "Could not bind to Bluetooth SAP Service with " + intent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
mProfileConnector.connect(context, listener);
|
||||
}
|
||||
|
||||
protected void finalize() throws Throwable {
|
||||
@@ -172,26 +123,11 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
* @hide
|
||||
*/
|
||||
public synchronized void close() {
|
||||
IBluetoothManager mgr = mAdapter.getBluetoothManager();
|
||||
if (mgr != null) {
|
||||
try {
|
||||
mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "", e);
|
||||
}
|
||||
}
|
||||
mProfileConnector.disconnect();
|
||||
}
|
||||
|
||||
synchronized (mConnection) {
|
||||
if (mService != null) {
|
||||
try {
|
||||
mService = null;
|
||||
mContext.unbindService(mConnection);
|
||||
} catch (Exception re) {
|
||||
Log.e(TAG, "", re);
|
||||
}
|
||||
}
|
||||
}
|
||||
mServiceListener = null;
|
||||
private IBluetoothSap getService() {
|
||||
return mProfileConnector.getService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,7 +139,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public int getState() {
|
||||
if (VDBG) log("getState()");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getState();
|
||||
@@ -226,7 +162,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public BluetoothDevice getClient() {
|
||||
if (VDBG) log("getClient()");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getClient();
|
||||
@@ -249,7 +185,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public boolean isConnected(BluetoothDevice device) {
|
||||
if (VDBG) log("isConnected(" + device + ")");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.isConnected(device);
|
||||
@@ -284,7 +220,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
@UnsupportedAppUsage
|
||||
public boolean disconnect(BluetoothDevice device) {
|
||||
if (DBG) log("disconnect(" + device + ")");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.disconnect(device);
|
||||
@@ -305,7 +241,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public List<BluetoothDevice> getConnectedDevices() {
|
||||
if (DBG) log("getConnectedDevices()");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getConnectedDevices();
|
||||
@@ -326,7 +262,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
|
||||
if (DBG) log("getDevicesMatchingStates()");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null && isEnabled()) {
|
||||
try {
|
||||
return service.getDevicesMatchingConnectionStates(states);
|
||||
@@ -347,7 +283,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public int getConnectionState(BluetoothDevice device) {
|
||||
if (DBG) log("getConnectionState(" + device + ")");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getConnectionState(device);
|
||||
@@ -372,7 +308,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public boolean setPriority(BluetoothDevice device, int priority) {
|
||||
if (DBG) log("setPriority(" + device + ", " + priority + ")");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
if (priority != BluetoothProfile.PRIORITY_OFF
|
||||
&& priority != BluetoothProfile.PRIORITY_ON) {
|
||||
@@ -398,7 +334,7 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
*/
|
||||
public int getPriority(BluetoothDevice device) {
|
||||
if (VDBG) log("getPriority(" + device + ")");
|
||||
final IBluetoothSap service = mService;
|
||||
final IBluetoothSap service = getService();
|
||||
if (service != null && isEnabled() && isValidDevice(device)) {
|
||||
try {
|
||||
return service.getPriority(device);
|
||||
@@ -411,24 +347,6 @@ public final class BluetoothSap implements BluetoothProfile {
|
||||
return PRIORITY_OFF;
|
||||
}
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
if (DBG) log("Proxy object connected");
|
||||
mService = IBluetoothSap.Stub.asInterface(Binder.allowBlocking(service));
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceConnected(BluetoothProfile.SAP, BluetoothSap.this);
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName className) {
|
||||
if (DBG) log("Proxy object disconnected");
|
||||
mService = null;
|
||||
if (mServiceListener != null) {
|
||||
mServiceListener.onServiceDisconnected(BluetoothProfile.SAP);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static void log(String msg) {
|
||||
Log.d(TAG, msg);
|
||||
}
|
||||
|
||||
@@ -1094,11 +1094,21 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
||||
public void unbindBluetoothProfileService(int bluetoothProfile,
|
||||
IBluetoothProfileServiceConnection proxy) {
|
||||
synchronized (mProfileServices) {
|
||||
ProfileServiceConnections psc = mProfileServices.get(new Integer(bluetoothProfile));
|
||||
Integer profile = new Integer(bluetoothProfile);
|
||||
ProfileServiceConnections psc = mProfileServices.get(profile);
|
||||
if (psc == null) {
|
||||
return;
|
||||
}
|
||||
psc.removeProxy(proxy);
|
||||
if (psc.isEmpty()) {
|
||||
// All prxoies are disconnected, unbind with the service.
|
||||
try {
|
||||
mContext.unbindService(psc);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Slog.e(TAG, "Unable to unbind service with intent: " + psc.mIntent, e);
|
||||
}
|
||||
mProfileServices.remove(profile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1255,6 +1265,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
|
||||
mProxies.kill();
|
||||
}
|
||||
|
||||
private boolean isEmpty() {
|
||||
return mProxies.getRegisteredCallbackCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
// remove timeout message
|
||||
|
||||
Reference in New Issue
Block a user