summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/settings/bluetooth/DockEventReceiver.java53
-rw-r--r--src/com/android/settings/bluetooth/DockService.java99
2 files changed, 143 insertions, 9 deletions
diff --git a/src/com/android/settings/bluetooth/DockEventReceiver.java b/src/com/android/settings/bluetooth/DockEventReceiver.java
index 2d634b2..6d11972 100644
--- a/src/com/android/settings/bluetooth/DockEventReceiver.java
+++ b/src/com/android/settings/bluetooth/DockEventReceiver.java
@@ -16,12 +16,17 @@
package com.android.settings.bluetooth;
+import com.android.settings.bluetooth.LocalBluetoothProfileManager.Profile;
+
import android.app.Service;
+import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.PowerManager;
import android.util.Log;
@@ -75,6 +80,54 @@ public class DockEventReceiver extends BroadcastReceiver {
if (DEBUG) Log.e(TAG, "Unknown state");
break;
}
+ } else if (BluetoothHeadset.ACTION_STATE_CHANGED.equals(intent.getAction())) {
+ /*
+ * Reconnect to the dock if:
+ * 1) it is a dock
+ * 2) it is disconnected
+ * 3) the disconnect is initiated remotely
+ * 4) the dock is still docked (check can only be done in the Service)
+ */
+ if (device == null) {
+ if (DEBUG) Log.d(TAG, "Device is missing");
+ return;
+ }
+
+ int newState = intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
+ BluetoothHeadset.STATE_CONNECTED);
+ if (newState != BluetoothHeadset.STATE_DISCONNECTED) return;
+
+ int source = intent.getIntExtra(BluetoothHeadset.EXTRA_DISCONNECT_INITIATOR,
+ BluetoothHeadset.LOCAL_DISCONNECT);
+ if (source != BluetoothHeadset.REMOTE_DISCONNECT) return;
+
+ // Too bad, the dock state can't be checked from a BroadcastReceiver.
+ Intent i = new Intent(intent);
+ i.setClass(context, DockService.class);
+ beginStartingService(context, i);
+
+ } else if (BluetoothA2dp.ACTION_SINK_STATE_CHANGED.equals(intent.getAction())) {
+ /*
+ * Reconnect to the dock if:
+ * 1) it is a dock
+ * 2) it is an unexpected disconnect i.e. didn't go through disconnecting state
+ * 3) the dock is still docked (check can only be done in the Service)
+ */
+ if (device == null) {
+ if (DEBUG) Log.d(TAG, "Device is missing");
+ return;
+ }
+
+ int newState = intent.getIntExtra(BluetoothA2dp.EXTRA_SINK_STATE, 0);
+ int oldState = intent.getIntExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, 0);
+ if (newState == BluetoothA2dp.STATE_DISCONNECTED &&
+ oldState != BluetoothA2dp.STATE_DISCONNECTING) {
+ // Too bad, the dock state can't be checked from a BroadcastReceiver.
+ Intent i = new Intent(intent);
+ i.setClass(context, DockService.class);
+ beginStartingService(context, i);
+ }
+
} else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(intent.getAction())) {
int btState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
if (btState != BluetoothAdapter.STATE_TURNING_ON) {
diff --git a/src/com/android/settings/bluetooth/DockService.java b/src/com/android/settings/bluetooth/DockService.java
index 1425e23..f318987 100644
--- a/src/com/android/settings/bluetooth/DockService.java
+++ b/src/com/android/settings/bluetooth/DockService.java
@@ -87,6 +87,15 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
private static final String SHARED_PREFERENCES_KEY_DISABLE_BT =
"disable_bt";
+ private static final String SHARED_PREFERENCES_KEY_CONNECT_RETRY_COUNT =
+ "connect_retry_count";
+
+ /*
+ * If disconnected unexpectedly, reconnect up to 6 times. Each profile counts
+ * as one time so it's only 3 times for both profiles on the car dock.
+ */
+ private static final int MAX_CONNECT_RETRY = 6;
+
private static final int INVALID_STARTID = -100;
// Created in OnCreate()
@@ -161,6 +170,32 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
return START_NOT_STICKY;
}
+ /*
+ * This assumes that the intent sender has checked that this is a dock
+ * and that the intent is for a disconnect
+ */
+ if (BluetoothHeadset.ACTION_STATE_CHANGED.equals(intent.getAction())) {
+ BluetoothDevice disconnectedDevice = intent
+ .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+ int retryCount = getSettingInt(SHARED_PREFERENCES_KEY_CONNECT_RETRY_COUNT, 0);
+ if (retryCount < MAX_CONNECT_RETRY) {
+ setSettingInt(SHARED_PREFERENCES_KEY_CONNECT_RETRY_COUNT, retryCount + 1);
+ handleUnexpectedDisconnect(disconnectedDevice, Profile.HEADSET, startId);
+ }
+ return START_NOT_STICKY;
+ } else if (BluetoothA2dp.ACTION_SINK_STATE_CHANGED.equals(intent.getAction())) {
+ BluetoothDevice disconnectedDevice = intent
+ .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+ int retryCount = getSettingInt(SHARED_PREFERENCES_KEY_CONNECT_RETRY_COUNT, 0);
+ if (retryCount < MAX_CONNECT_RETRY) {
+ setSettingInt(SHARED_PREFERENCES_KEY_CONNECT_RETRY_COUNT, retryCount + 1);
+ handleUnexpectedDisconnect(disconnectedDevice, Profile.A2DP, startId);
+ }
+ return START_NOT_STICKY;
+ }
+
Message msg = parseIntent(intent);
if (msg == null) {
// Bad intent
@@ -169,6 +204,10 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
return START_NOT_STICKY;
}
+ if (msg.what == MSG_TYPE_DOCKED) {
+ removeSetting(SHARED_PREFERENCES_KEY_CONNECT_RETRY_COUNT);
+ }
+
msg.arg2 = startId;
processMessage(msg);
@@ -248,10 +287,10 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
if (DEBUG) {
Log.d(TAG, "DISABLE_BT_WHEN_UNDOCKED = "
- + getSetting(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED));
+ + getSettingBool(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED));
}
- if (getSetting(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED)) {
+ if (getSettingBool(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED)) {
// BT was disabled when we first docked
if (!hasOtherConnectedDevices(device)) {
if(DEBUG) Log.d(TAG, "QUEUED BT DISABLE");
@@ -280,7 +319,7 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
removeSetting(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED);
} else {
// disable() returned an error. Persist a flag to disable BT later
- setSetting(SHARED_PREFERENCES_KEY_DISABLE_BT, true);
+ setSettingBool(SHARED_PREFERENCES_KEY_DISABLE_BT, true);
mPendingTurnOffStartId = startId;
deferFinishCall = true;
if(DEBUG) Log.d(TAG, "disable failed. try again later " + startId);
@@ -509,7 +548,7 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
} else {
if (DEBUG) {
Log.d(TAG, "A DISABLE_BT_WHEN_UNDOCKED = "
- + getSetting(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED));
+ + getSettingBool(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED));
}
// Reconnect if docked and bluetooth was enabled by user.
Intent i = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
@@ -522,7 +561,7 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
if (device != null) {
connectIfEnabled(device);
}
- } else if (getSetting(SHARED_PREFERENCES_KEY_DISABLE_BT)
+ } else if (getSettingBool(SHARED_PREFERENCES_KEY_DISABLE_BT)
&& mBtManager.getBluetoothAdapter().disable()) {
mPendingTurnOffStartId = startId;
removeSetting(SHARED_PREFERENCES_KEY_DISABLE_BT);
@@ -565,6 +604,34 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
}
}
+ private void handleUnexpectedDisconnect(BluetoothDevice disconnectedDevice, Profile profile,
+ int startId) {
+ synchronized (this) {
+ if (DEBUG) Log.d(TAG, "handling failed connect for " + disconnectedDevice);
+
+ // Reconnect if docked.
+ if (disconnectedDevice != null) {
+ // registerReceiver can't be called from a BroadcastReceiver
+ Intent i = registerReceiver(null, new IntentFilter(Intent.ACTION_DOCK_EVENT));
+ if (i != null) {
+ int state = i.getIntExtra(Intent.EXTRA_DOCK_STATE,
+ Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ if (state != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+ BluetoothDevice dockedDevice = i
+ .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (dockedDevice != null && dockedDevice.equals(disconnectedDevice)) {
+ CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(mContext,
+ mBtManager, dockedDevice);
+ cachedDevice.connect(profile);
+ }
+ }
+ }
+ }
+
+ DockEventReceiver.finishStartingService(this, startId);
+ }
+ }
+
private synchronized void connectIfEnabled(BluetoothDevice device) {
CachedBluetoothDevice cachedDevice = getCachedBluetoothDevice(mContext, mBtManager, device);
List<Profile> profiles = cachedDevice.getConnectableProfiles();
@@ -612,7 +679,8 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
mPendingDevice = device;
mPendingStartId = startId;
if (btState != BluetoothAdapter.STATE_TURNING_ON) {
- setSetting(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED, true);
+ setSettingBool(SHARED_PREFERENCES_KEY_DISABLE_BT_WHEN_UNDOCKED,
+ true);
}
return;
}
@@ -676,16 +744,29 @@ public class DockService extends Service implements AlertDialog.OnMultiChoiceCli
return cachedBluetoothDevice;
}
- private boolean getSetting(String key) {
+ private boolean getSettingBool(String key) {
SharedPreferences sharedPref = getSharedPreferences(SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE);
return sharedPref.getBoolean(key, false);
}
- private void setSetting(String key, boolean disableBt) {
+ private int getSettingInt(String key, int defaultValue) {
+ SharedPreferences sharedPref = getSharedPreferences(SHARED_PREFERENCES_NAME,
+ Context.MODE_PRIVATE);
+ return sharedPref.getInt(key, defaultValue);
+ }
+
+ private void setSettingBool(String key, boolean bool) {
+ SharedPreferences.Editor editor = getSharedPreferences(SHARED_PREFERENCES_NAME,
+ Context.MODE_PRIVATE).edit();
+ editor.putBoolean(key, bool);
+ editor.commit();
+ }
+
+ private void setSettingInt(String key, int value) {
SharedPreferences.Editor editor = getSharedPreferences(SHARED_PREFERENCES_NAME,
Context.MODE_PRIVATE).edit();
- editor.putBoolean(key, disableBt);
+ editor.putInt(key, value);
editor.commit();
}