summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/java/android/bluetooth/BluetoothDeviceProfileState.java89
-rw-r--r--core/java/android/content/res/AssetFileDescriptor.java6
2 files changed, 90 insertions, 5 deletions
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 71aefbc..9be4c8f 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -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;
}
diff --git a/core/java/android/content/res/AssetFileDescriptor.java b/core/java/android/content/res/AssetFileDescriptor.java
index a37e4e8..34f1f5c 100644
--- a/core/java/android/content/res/AssetFileDescriptor.java
+++ b/core/java/android/content/res/AssetFileDescriptor.java
@@ -130,7 +130,11 @@ public class AssetFileDescriptor implements Parcelable {
* Checks whether this file descriptor is for a memory file.
*/
private boolean isMemoryFile() throws IOException {
- return MemoryFile.isMemoryFile(mFd.getFileDescriptor());
+ try {
+ return MemoryFile.isMemoryFile(mFd.getFileDescriptor());
+ } catch (IOException e) {
+ return false;
+ }
}
/**