Loading AndroidManifest.xml +3 −1 Original line number Diff line number Diff line Loading @@ -614,6 +614,8 @@ <intent-filter> <action android:name="android.intent.action.DOCK_EVENT" /> <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" /> <action android:name="android.bluetooth.headset.action.STATE_CHANGED" /> <action android:name="android.bluetooth.a2dp.action.SINK_STATE_CHANGED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> Loading src/com/android/settings/bluetooth/DockEventReceiver.java +53 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading src/com/android/settings/bluetooth/DockService.java +90 −9 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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 Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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); Loading Loading @@ -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)); Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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; } Loading Loading @@ -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(); } Loading Loading
AndroidManifest.xml +3 −1 Original line number Diff line number Diff line Loading @@ -614,6 +614,8 @@ <intent-filter> <action android:name="android.intent.action.DOCK_EVENT" /> <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" /> <action android:name="android.bluetooth.headset.action.STATE_CHANGED" /> <action android:name="android.bluetooth.a2dp.action.SINK_STATE_CHANGED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </receiver> Loading
src/com/android/settings/bluetooth/DockEventReceiver.java +53 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading
src/com/android/settings/bluetooth/DockService.java +90 −9 Original line number Diff line number Diff line Loading @@ -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() Loading Loading @@ -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 Loading @@ -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); Loading Loading @@ -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"); Loading Loading @@ -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); Loading Loading @@ -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)); Loading @@ -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); Loading Loading @@ -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(); Loading Loading @@ -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; } Loading Loading @@ -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(); } Loading