Merge "DO NOT MERGE Fix auto connection with headsets which don't send incoming connections for all profiles." into gingerbread
This commit is contained in:
committed by
Android (Google) Code Review
commit
025f78ebb8
@@ -72,6 +72,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
public static final int UNPAIR = 100;
|
||||
public static final int AUTO_CONNECT_PROFILES = 101;
|
||||
public static final int TRANSITION_TO_STABLE = 102;
|
||||
public static final int CONNECT_OTHER_PROFILES = 103;
|
||||
|
||||
private static final int AUTO_CONNECT_DELAY = 6000; // 6 secs
|
||||
|
||||
@@ -129,10 +130,6 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
sendMessage(TRANSITION_TO_STABLE);
|
||||
}
|
||||
} else if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
|
||||
if (!getCurrentState().equals(mBondedDevice)) {
|
||||
Log.e(TAG, "State is: " + getCurrentState());
|
||||
return;
|
||||
}
|
||||
Message msg = new Message();
|
||||
msg.what = AUTO_CONNECT_PROFILES;
|
||||
sendMessageDelayed(msg, AUTO_CONNECT_DELAY);
|
||||
@@ -274,16 +271,39 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
if (mHeadsetService.getPriority(mDevice) ==
|
||||
BluetoothHeadset.PRIORITY_AUTO_CONNECT &&
|
||||
!mHeadsetService.isConnected(mDevice)) {
|
||||
Log.i(TAG, "Headset:Auto Connect Profiles");
|
||||
mHeadsetService.connectHeadset(mDevice);
|
||||
}
|
||||
if (mA2dpService != null &&
|
||||
mA2dpService.getSinkPriority(mDevice) ==
|
||||
BluetoothA2dp.PRIORITY_AUTO_CONNECT &&
|
||||
mA2dpService.getConnectedSinks().length == 0) {
|
||||
Log.i(TAG, "A2dp:Auto Connect Profiles");
|
||||
mA2dpService.connectSink(mDevice);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONNECT_OTHER_PROFILES:
|
||||
if (isPhoneDocked(mDevice)) {
|
||||
break;
|
||||
}
|
||||
if (message.arg1 == CONNECT_A2DP_OUTGOING) {
|
||||
if (mA2dpService != null &&
|
||||
mA2dpService.getConnectedSinks().length == 0) {
|
||||
Log.i(TAG, "A2dp:Connect Other Profiles");
|
||||
mA2dpService.connectSink(mDevice);
|
||||
}
|
||||
} else if (message.arg1 == CONNECT_HFP_OUTGOING) {
|
||||
if (!mHeadsetServiceConnected) {
|
||||
deferMessage(message);
|
||||
} else {
|
||||
if (!mHeadsetService.isConnected(mDevice)) {
|
||||
Log.i(TAG, "Headset:Connect Other Profiles");
|
||||
mHeadsetService.connectHeadset(mDevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TRANSITION_TO_STABLE:
|
||||
// ignore.
|
||||
break;
|
||||
@@ -377,6 +397,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
case DISCONNECT_PBAP_OUTGOING:
|
||||
case UNPAIR:
|
||||
case AUTO_CONNECT_PROFILES:
|
||||
case CONNECT_OTHER_PROFILES:
|
||||
deferMessage(message);
|
||||
break;
|
||||
case TRANSITION_TO_STABLE:
|
||||
@@ -449,6 +470,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
case DISCONNECT_PBAP_OUTGOING:
|
||||
case UNPAIR:
|
||||
case AUTO_CONNECT_PROFILES:
|
||||
case CONNECT_OTHER_PROFILES:
|
||||
deferMessage(message);
|
||||
break;
|
||||
case TRANSITION_TO_STABLE:
|
||||
@@ -541,6 +563,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
case DISCONNECT_PBAP_OUTGOING:
|
||||
case UNPAIR:
|
||||
case AUTO_CONNECT_PROFILES:
|
||||
case CONNECT_OTHER_PROFILES:
|
||||
deferMessage(message);
|
||||
break;
|
||||
case TRANSITION_TO_STABLE:
|
||||
@@ -611,6 +634,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
case DISCONNECT_PBAP_OUTGOING:
|
||||
case UNPAIR:
|
||||
case AUTO_CONNECT_PROFILES:
|
||||
case CONNECT_OTHER_PROFILES:
|
||||
deferMessage(message);
|
||||
break;
|
||||
case TRANSITION_TO_STABLE:
|
||||
@@ -656,6 +680,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
} else if (mHeadsetState == BluetoothHeadset.STATE_CONNECTING) {
|
||||
return mHeadsetService.acceptIncomingConnect(mDevice);
|
||||
} else if (mHeadsetState == BluetoothHeadset.STATE_DISCONNECTED) {
|
||||
handleConnectionOfOtherProfiles(command);
|
||||
return mHeadsetService.createIncomingConnect(mDevice);
|
||||
}
|
||||
break;
|
||||
@@ -665,6 +690,7 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
}
|
||||
break;
|
||||
case CONNECT_A2DP_INCOMING:
|
||||
handleConnectionOfOtherProfiles(command);
|
||||
// ignore, Bluez takes care
|
||||
return true;
|
||||
case DISCONNECT_HFP_OUTGOING:
|
||||
@@ -713,6 +739,61 @@ public final class BluetoothDeviceProfileState extends HierarchicalStateMachine
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleConnectionOfOtherProfiles(int command) {
|
||||
// The white paper recommendations mentions that when there is a
|
||||
// link loss, it is the responsibility of the remote device to connect.
|
||||
// Many connect only 1 profile - and they connect the second profile on
|
||||
// some user action (like play being pressed) and so we need this code.
|
||||
// Auto Connect code only connects to the last connected device - which
|
||||
// is useful in cases like when the phone reboots. But consider the
|
||||
// following case:
|
||||
// User is connected to the car's phone and A2DP profile.
|
||||
// User comes to the desk and places the phone in the dock
|
||||
// (or any speaker or music system or even another headset) and thus
|
||||
// gets connected to the A2DP profile. User goes back to the car.
|
||||
// Ideally the car's system is supposed to send incoming connections
|
||||
// from both Handsfree and A2DP profile. But they don't. The Auto
|
||||
// connect code, will not work here because we only auto connect to the
|
||||
// last connected device for that profile which in this case is the dock.
|
||||
// Now suppose a user is using 2 headsets simultaneously, one for the
|
||||
// phone profile one for the A2DP profile. If this is the use case, we
|
||||
// expect the user to use the preference to turn off the A2DP profile in
|
||||
// the Settings screen for the first headset. Else, after link loss,
|
||||
// there can be an incoming connection from the first headset which
|
||||
// might result in the connection of the A2DP profile (if the second
|
||||
// headset is slower) and thus the A2DP profile on the second headset
|
||||
// will never get connected.
|
||||
//
|
||||
// TODO(): Handle other profiles here.
|
||||
switch (command) {
|
||||
case CONNECT_HFP_INCOMING:
|
||||
// Connect A2DP if there is no incoming connection
|
||||
// If the priority is OFF - don't auto connect.
|
||||
// If the priority is AUTO_CONNECT, auto connect code takes care.
|
||||
if (mA2dpService.getSinkPriority(mDevice) == BluetoothA2dp.PRIORITY_ON) {
|
||||
Message msg = new Message();
|
||||
msg.what = CONNECT_OTHER_PROFILES;
|
||||
msg.arg1 = CONNECT_A2DP_OUTGOING;
|
||||
sendMessageDelayed(msg, AUTO_CONNECT_DELAY);
|
||||
}
|
||||
break;
|
||||
case CONNECT_A2DP_INCOMING:
|
||||
// This is again against spec. HFP incoming connections should be made
|
||||
// before A2DP, so we should not hit this case. But many devices
|
||||
// don't follow this.
|
||||
if (mHeadsetService.getPriority(mDevice) == BluetoothHeadset.PRIORITY_ON) {
|
||||
Message msg = new Message();
|
||||
msg.what = CONNECT_OTHER_PROFILES;
|
||||
msg.arg1 = CONNECT_HFP_OUTGOING;
|
||||
sendMessageDelayed(msg, AUTO_CONNECT_DELAY);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*package*/ BluetoothDevice getDevice() {
|
||||
return mDevice;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user