Auto connect hf/a2dp when any one of them gets connected and timeout happens

Change-Id: I6249c2fceab87f91c6629d19f72268d000ecf61c
This commit is contained in:
Swaminatha Balaji
2012-05-09 01:44:38 -07:00
committed by Matthew Xie
parent 654a3ab77d
commit 00ec05985d
3 changed files with 79 additions and 9 deletions

View File

@@ -30,10 +30,6 @@ import com.android.settings.R;
import java.util.List; import java.util.List;
/**
* A2dpProfile handles Bluetooth A2DP.
* TODO: add null checks around calls to mService object.
*/
final class A2dpProfile implements LocalBluetoothProfile { final class A2dpProfile implements LocalBluetoothProfile {
private static final String TAG = "A2dpProfile"; private static final String TAG = "A2dpProfile";
private static boolean V = true; private static boolean V = true;
@@ -89,7 +85,7 @@ final class A2dpProfile implements LocalBluetoothProfile {
return true; return true;
} }
private List<BluetoothDevice> getConnectedDevices() { public List<BluetoothDevice> getConnectedDevices() {
return mService.getDevicesMatchingConnectionStates( return mService.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED, new int[] {BluetoothProfile.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING, BluetoothProfile.STATE_CONNECTING,

View File

@@ -95,10 +95,6 @@ final class HeadsetProfile implements LocalBluetoothProfile {
return mIsProfileReady; return mIsProfileReady;
} }
// TODO(): The calls must get queued if mService becomes null.
// It can happen when the phone app crashes for some reason.
// All callers should have service listeners. Dock Service is the only
// one right now.
HeadsetProfile(Context context, LocalBluetoothAdapter adapter, HeadsetProfile(Context context, LocalBluetoothAdapter adapter,
CachedBluetoothDeviceManager deviceManager, CachedBluetoothDeviceManager deviceManager,
LocalBluetoothProfileManager profileManager) { LocalBluetoothProfileManager profileManager) {
@@ -168,6 +164,14 @@ final class HeadsetProfile implements LocalBluetoothProfile {
} }
} }
public List<BluetoothDevice> getConnectedDevices() {
return mService.getDevicesMatchingConnectionStates(
new int[] {BluetoothProfile.STATE_CONNECTED,
BluetoothProfile.STATE_CONNECTING,
BluetoothProfile.STATE_DISCONNECTING});
}
// This function is added as the AUTO CONNECT priority could not be set by using setPreferred(), // This function is added as the AUTO CONNECT priority could not be set by using setPreferred(),
// as setPreferred() takes only boolean input but getPreferred() supports interger output. // as setPreferred() takes only boolean input but getPreferred() supports interger output.
// Also this need not implemented by all profiles so this has been added here. // Also this need not implemented by all profiles so this has been added here.

View File

@@ -27,12 +27,15 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.ParcelUuid; import android.os.ParcelUuid;
import android.util.Log; import android.util.Log;
import android.os.Handler;
import android.os.Message;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.List;
/** /**
* LocalBluetoothProfileManager provides access to the LocalBluetoothProfile * LocalBluetoothProfileManager provides access to the LocalBluetoothProfile
@@ -40,6 +43,12 @@ import java.util.Set;
*/ */
final class LocalBluetoothProfileManager { final class LocalBluetoothProfileManager {
private static final String TAG = "LocalBluetoothProfileManager"; private static final String TAG = "LocalBluetoothProfileManager";
private static final int CONNECT_HF_OR_A2DP = 1;
// If either a2dp or hf is connected and if the other profile conneciton is not
// happening with the timeout , the other profile(a2dp or hf) will be inititate connection.
// Give reasonable timeout for the device to initiate the other profile connection.
private static final int CONNECT_HF_OR_A2DP_TIMEOUT = 6000;
/** Singleton instance. */ /** Singleton instance. */
private static LocalBluetoothProfileManager sInstance; private static LocalBluetoothProfileManager sInstance;
@@ -80,6 +89,21 @@ final class LocalBluetoothProfileManager {
private final PanProfile mPanProfile; private final PanProfile mPanProfile;
private boolean isHfServiceUp; private boolean isHfServiceUp;
private boolean isA2dpServiceUp; private boolean isA2dpServiceUp;
private boolean isHfA2dpConnectMessagePosted;
private final Handler hfA2dpConnectHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
synchronized (this) {
if (isA2dpConnectRequired((BluetoothDevice)msg.obj)) {
mA2dpProfile.connect((BluetoothDevice)msg.obj);
} else if (isHfConnectRequired((BluetoothDevice)msg.obj)) {
mHeadsetProfile.connect((BluetoothDevice)msg.obj);
}
isHfA2dpConnectMessagePosted =false;
}
}
};
/** /**
* Mapping from profile name, e.g. "HEADSET" to profile object. * Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -224,6 +248,21 @@ final class LocalBluetoothProfileManager {
cachedDevice.onProfileStateChanged(mProfile, newState); cachedDevice.onProfileStateChanged(mProfile, newState);
cachedDevice.refresh(); cachedDevice.refresh();
if ((mProfile instanceof HeadsetProfile)||(mProfile instanceof A2dpProfile)) {
if ((BluetoothProfile.STATE_CONNECTED == newState)&&
(!isHfA2dpConnectMessagePosted)) {
Message mes = hfA2dpConnectHandler.obtainMessage(CONNECT_HF_OR_A2DP);
mes.obj = device;
hfA2dpConnectHandler.sendMessageDelayed(mes,CONNECT_HF_OR_A2DP_TIMEOUT);
Log.i(TAG,"Message posted for hf/a2dp connection");
isHfA2dpConnectMessagePosted = true;
} else if (isHfA2dpConnectMessagePosted) {
hfA2dpConnectHandler.removeMessages(CONNECT_HF_OR_A2DP);
Log.i(TAG,"Message removed for hf/a2dp connection");
isHfA2dpConnectMessagePosted =false;
}
}
} }
} }
@@ -390,4 +429,35 @@ final class LocalBluetoothProfileManager {
removedProfiles.remove(mPanProfile); removedProfiles.remove(mPanProfile);
} }
} }
private boolean isHfConnectRequired(BluetoothDevice device) {
List<BluetoothDevice> a2dpConnDevList= mA2dpProfile.getConnectedDevices();
List<BluetoothDevice> hfConnDevList= mHeadsetProfile.getConnectedDevices();
// If both hf and a2dp is connected hf connection is not required
// Hf connection is required only when a2dp is connected but
// hf connect did no happen untill CONNECT_HF_OR_A2DP_TIMEOUT
if (!a2dpConnDevList.isEmpty() && !hfConnDevList.isEmpty())
return false;
if (hfConnDevList.isEmpty() && mHeadsetProfile.isPreferred(device))
return true;
return false;
}
private boolean isA2dpConnectRequired(BluetoothDevice device) {
List<BluetoothDevice> a2dpConnDevList= mA2dpProfile.getConnectedDevices();
List<BluetoothDevice> hfConnDevList= mHeadsetProfile.getConnectedDevices();
// If both hf and a2dp is connected a2dp connection is not required
// A2dp connection is required only when hf is connected but
// a2dp connect did no happen until CONNECT_HF_OR_A2DP_TIMEOUT
if (!a2dpConnDevList.isEmpty() && !hfConnDevList.isEmpty())
return false;
if (a2dpConnDevList.isEmpty() && mA2dpProfile.isPreferred(device))
return true;
return false;
}
} }