Set service priority of A2DP and Headset from BluetoothService via IPC call
We used to do the priority change in the 2 services after the broadcasted
intent reach them. But that left a small time gap that could reject
incoming connection due to undefined priorities.
Bug 4096186
Change-Id: I9bb6aedc7ed98c53a9b00c48eedd20b0cf5f1660
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 132c346..ca2212c 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -83,19 +83,6 @@
onBluetoothDisable();
break;
}
- } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
- int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
- BluetoothDevice.ERROR);
- switch(bondState) {
- case BluetoothDevice.BOND_BONDED:
- if (getPriority(device) == BluetoothA2dp.PRIORITY_UNDEFINED) {
- setPriority(device, BluetoothA2dp.PRIORITY_ON);
- }
- break;
- case BluetoothDevice.BOND_NONE:
- setPriority(device, BluetoothA2dp.PRIORITY_UNDEFINED);
- break;
- }
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
synchronized (this) {
if (mAudioDevices.containsKey(device)) {
@@ -158,7 +145,6 @@
mAdapter = BluetoothAdapter.getDefaultAdapter();
mIntentFilter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
- mIntentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
mIntentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
mIntentFilter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
diff --git a/core/java/android/server/BluetoothBondState.java b/core/java/android/server/BluetoothBondState.java
index 2304a70..a36cd24 100644
--- a/core/java/android/server/BluetoothBondState.java
+++ b/core/java/android/server/BluetoothBondState.java
@@ -18,6 +18,9 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothA2dp;
+import android.bluetooth.BluetoothHeadset;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
@@ -68,6 +71,8 @@
private final Context mContext;
private final BluetoothService mService;
private final BluetoothInputProfileHandler mBluetoothInputProfileHandler;
+ private BluetoothA2dp mA2dpProxy;
+ private BluetoothHeadset mHeadsetProxy;
BluetoothBondState(Context context, BluetoothService service) {
mContext = context;
@@ -126,14 +131,15 @@
if (state == BluetoothDevice.BOND_BONDED) {
mService.addProfileState(address);
+ } else if (state == BluetoothDevice.BOND_BONDING) {
+ if (mA2dpProxy == null || mHeadsetProxy == null) {
+ getProfileProxy();
+ }
} else if (state == BluetoothDevice.BOND_NONE) {
mService.removeProfileState(address);
}
- // HID is handled by BluetoothService, other profiles
- // will be handled by their respective services.
- mBluetoothInputProfileHandler.setInitialInputDevicePriority(
- mService.getRemoteDevice(address), state);
+ setProfilePriorities(address, state);
if (DBG) {
Log.d(TAG, address + " bond state " + oldState + " -> " + state
@@ -261,6 +267,52 @@
mPinAttempt.put(address, new Integer(newAttempt));
}
+ private void getProfileProxy() {
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ if (mA2dpProxy == null) {
+ bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
+ BluetoothProfile.A2DP);
+ }
+
+ if (mHeadsetProxy == null) {
+ bluetoothAdapter.getProfileProxy(mContext, mProfileServiceListener,
+ BluetoothProfile.HEADSET);
+ }
+ }
+
+ private void closeProfileProxy() {
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ if (mA2dpProxy != null) {
+ bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mA2dpProxy);
+ }
+
+ if (mHeadsetProxy != null) {
+ bluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mHeadsetProxy);
+ }
+ }
+
+ private BluetoothProfile.ServiceListener mProfileServiceListener =
+ new BluetoothProfile.ServiceListener() {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (profile == BluetoothProfile.A2DP) {
+ mA2dpProxy = (BluetoothA2dp) proxy;
+ } else if (profile == BluetoothProfile.HEADSET) {
+ mHeadsetProxy = (BluetoothHeadset) proxy;
+ }
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (profile == BluetoothProfile.A2DP) {
+ mA2dpProxy = null;
+ } else if (profile == BluetoothProfile.HEADSET) {
+ mHeadsetProxy = null;
+ }
+ }
+ };
+
private void copyAutoPairingData() {
FileInputStream in = null;
FileOutputStream out = null;
@@ -365,4 +417,30 @@
}
}
}
+
+ // Set service priority of Hid, A2DP and Headset profiles depending on
+ // the bond state change
+ private void setProfilePriorities(String address, int state) {
+ BluetoothDevice remoteDevice = mService.getRemoteDevice(address);
+ // HID is handled by BluetoothService
+ mBluetoothInputProfileHandler.setInitialInputDevicePriority(remoteDevice, state);
+
+ // Set service priority of A2DP and Headset
+ // We used to do the priority change in the 2 services after the broadcast
+ // intent reach them. But that left a small time gap that could reject
+ // incoming connection due to undefined priorities.
+ if (state == BluetoothDevice.BOND_BONDED) {
+ if (mA2dpProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
+ mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
+ }
+
+ if (mHeadsetProxy.getPriority(remoteDevice) == BluetoothProfile.PRIORITY_UNDEFINED) {
+ mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_ON);
+ }
+ } else if (state == BluetoothDevice.BOND_NONE) {
+ mA2dpProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
+ mHeadsetProxy.setPriority(remoteDevice, BluetoothProfile.PRIORITY_UNDEFINED);
+ }
+ }
+
}