From 8021537ffea45d1a36274217610a314b3a0ac774 Mon Sep 17 00:00:00 2001 From: Jake Hamby Date: Tue, 12 Oct 2010 16:12:06 -0700 Subject: [PATCH] BT settings wait for HS service before connect. DO NOT MERGE Bluetooth connections from Settings app can sometimes fail if the connection to BluetoothHeadsetService isn't ready. Changed code to delay any headset connect or disconnect attempt when the service isn't connected until onServiceConnected() is called. Tested by adding a call to Thread.sleep(5000) before the return statement in BluetoothHeadsetService.onBind(). This makes it easier to kill the phone process and then attempt to connect in the settings app before the service restarts. Bug: 3048839 Change-Id: I2114ff8ad67c8c672fcf6ce0bf3de61fca7a49b3 --- .../LocalBluetoothProfileManager.java | 62 ++++++++++++++++--- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java index 5fcddf0ab47..8d294280d2c 100644 --- a/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java +++ b/src/com/android/settings/bluetooth/LocalBluetoothProfileManager.java @@ -309,6 +309,8 @@ public abstract class LocalBluetoothProfileManager { private BluetoothHeadset mService; private Handler mUiHandler = new Handler(); private boolean profileReady = false; + private BluetoothDevice mDelayedConnectDevice = null; + private BluetoothDevice mDelayedDisconnectDevice = null; public HeadsetProfileManager(LocalBluetoothManager localManager) { super(localManager); @@ -318,19 +320,43 @@ public abstract class LocalBluetoothProfileManager { public void onServiceConnected() { profileReady = true; // This could be called on a non-UI thread, funnel to UI thread. - mUiHandler.post(new Runnable() { + // Delay for a few seconds to allow other proxies to connect. + mUiHandler.postDelayed(new Runnable() { public void run() { - /* - * We just bound to the service, so refresh the UI of the - * headset device. - */ BluetoothDevice device = mService.getCurrentHeadset(); - if (device == null) return; - mLocalManager.getCachedDeviceManager() + + if (mDelayedConnectDevice != null) { + Log.i(TAG, "service ready: connecting..."); + BluetoothDevice newDevice = mDelayedConnectDevice; + mDelayedConnectDevice = null; + + if (!newDevice.equals(device)) { + if (device != null) { + Log.i(TAG, "disconnecting old headset"); + mService.disconnectHeadset(device); + } + Log.i(TAG, "connecting to pending headset"); + mService.connectHeadset(newDevice); + } + } else if (mDelayedDisconnectDevice != null) { + Log.i(TAG, "service ready: disconnecting..."); + if (mDelayedDisconnectDevice.equals(device)) { + Log.i(TAG, "disconnecting headset"); + mService.disconnectHeadset(device); + } + mDelayedDisconnectDevice = null; + } else { + /* + * We just bound to the service, so refresh the UI of the + * headset device. + */ + if (device == null) return; + mLocalManager.getCachedDeviceManager() .onProfileStateChanged(device, Profile.HEADSET, BluetoothHeadset.STATE_CONNECTED); + } } - }); + }, 2000); // wait 2 seconds for other proxies to connect if (mServiceListeners.size() > 0) { Iterator it = mServiceListeners.iterator(); @@ -368,6 +394,16 @@ public abstract class LocalBluetoothProfileManager { @Override public boolean connect(BluetoothDevice device) { + // Delay connection until onServiceConnected() if the + // manager isn't ready + if (!isManagerReady()) { + Log.w(TAG, "HeadsetProfileManager delaying connect, " + + "manager not ready"); + mDelayedConnectDevice = device; + mDelayedDisconnectDevice = null; + return true; // hopefully it will succeed + } + // Since connectHeadset fails if already connected to a headset, we // disconnect from any headset first BluetoothDevice currDevice = mService.getCurrentHeadset(); @@ -379,6 +415,16 @@ public abstract class LocalBluetoothProfileManager { @Override public boolean disconnect(BluetoothDevice device) { + // Delay connection until onServiceConnected() if the + // manager isn't ready + if (!isManagerReady()) { + Log.w(TAG, "HeadsetProfileManager delaying disconnect, " + + "manager not ready"); + mDelayedConnectDevice = null; + mDelayedDisconnectDevice = device; + return true; // hopefully it will succeed + } + BluetoothDevice currDevice = mService.getCurrentHeadset(); if (currDevice != null && currDevice.equals(device)) { // Downgrade prority as user is disconnecting the headset.