OSDN Git Service

DO NOT MERGE Fix auto connection with headsets which don't send incoming
authorJaikumar Ganesh <jaikumar@google.com>
Wed, 27 Oct 2010 22:57:23 +0000 (15:57 -0700)
committerJaikumar Ganesh <jaikumar@google.com>
Wed, 27 Oct 2010 23:34:43 +0000 (16:34 -0700)
connections for all profiles.

Bug: 3136095
Change-Id: I48f36b99f3f7619a6a18c6adc2057c9d6d23c3e3

core/java/android/bluetooth/BluetoothDeviceProfileState.java

index 71aefbc..9be4c8f 100644 (file)
@@ -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;
     }