Loading core/java/android/bluetooth/BluetoothDeviceProfileState.java +85 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -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: Loading Loading @@ -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: Loading Loading @@ -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: Loading Loading @@ -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; Loading @@ -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: Loading Loading @@ -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; } Loading Loading
core/java/android/bluetooth/BluetoothDeviceProfileState.java +85 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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: Loading Loading @@ -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: Loading Loading @@ -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: Loading Loading @@ -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: Loading Loading @@ -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; Loading @@ -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: Loading Loading @@ -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; } Loading