b/2314560 Prevent PIN dialog from showing up on undocked docks

If unpaired while undocked, device will be removed from the BT device list.
If unpaired while docked, the user can do pair and connect. No PIN dialog will pop up.
If undocked after unpaired, device will be removed from the BT device list.

Change-Id: Id587a517999e08641451f78dec8696a06028cf16
diff --git a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
index 6c40834..f283a67 100644
--- a/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
+++ b/src/com/android/settings/bluetooth/BluetoothEventRedirector.java
@@ -75,10 +75,23 @@
             } else if (action.equals(BluetoothDevice.ACTION_BOND_STATE_CHANGED)) {
                 int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
                                                    BluetoothDevice.ERROR);
-                mManager.getCachedDeviceManager().onBondingStateChanged(device, bondState);
+                CachedBluetoothDeviceManager cachedDeviceMgr = mManager.getCachedDeviceManager();
+                cachedDeviceMgr.onBondingStateChanged(device, bondState);
                 if (bondState == BluetoothDevice.BOND_NONE) {
-                    int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON, BluetoothDevice.ERROR);
-                    mManager.getCachedDeviceManager().showUnbondMessage(device, reason);
+                    if (device.isBluetoothDock()) {
+                        // After a dock is unpaired, we will forget the
+                        // setttings
+                        mManager.removeDockAutoConnectSetting(device.getAddress());
+
+                        // if the device is undocked, remove it from the list as
+                        // well
+                        if (!device.getAddress().equals(getDockedDeviceAddress(context))) {
+                            cachedDeviceMgr.onDeviceDisappeared(device);
+                        }
+                    }
+                    int reason = intent.getIntExtra(BluetoothDevice.EXTRA_REASON,
+                            BluetoothDevice.ERROR);
+                    cachedDeviceMgr.showUnbondMessage(device, reason);
                 }
 
             } else if (action.equals(BluetoothHeadset.ACTION_STATE_CHANGED)) {
@@ -112,6 +125,16 @@
             } else if (action.equals(BluetoothDevice.ACTION_PAIRING_CANCEL)) {
                 int errorMsg = R.string.bluetooth_pairing_error_message;
                 mManager.showError(device, R.string.bluetooth_error_title, errorMsg);
+
+            } else if (action.equals(Intent.ACTION_DOCK_EVENT)) {
+                // Remove if unpair device upon undocking
+                int anythingButUnDocked = Intent.EXTRA_DOCK_STATE_UNDOCKED + 1;
+                int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, anythingButUnDocked);
+                if (state == Intent.EXTRA_DOCK_STATE_UNDOCKED) {
+                    if (device.getBondState() == BluetoothDevice.BOND_NONE) {
+                        mManager.getCachedDeviceManager().onDeviceDisappeared(device);
+                    }
+                }
             }
         }
     };
@@ -143,10 +166,29 @@
         filter.addAction(BluetoothDevice.ACTION_CLASS_CHANGED);
         filter.addAction(BluetoothDevice.ACTION_UUID);
 
+        // Dock event broadcasts
+        filter.addAction(Intent.ACTION_DOCK_EVENT);
+
         mManager.getContext().registerReceiver(mBroadcastReceiver, filter);
     }
 
     public void stop() {
         mManager.getContext().unregisterReceiver(mBroadcastReceiver);
     }
+
+    // This can't be called from a broadcast receiver where the filter is set in the Manifest.
+    private String getDockedDeviceAddress(Context context) {
+        // This works only because these broadcast intents are "sticky"
+        Intent i = context.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 device = i.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+                if (device != null) {
+                    return device.getAddress();
+                }
+            }
+        }
+        return null;
+    }
 }
diff --git a/src/com/android/settings/bluetooth/DockService.java b/src/com/android/settings/bluetooth/DockService.java
index 87a82b4..6da8fd9 100644
--- a/src/com/android/settings/bluetooth/DockService.java
+++ b/src/com/android/settings/bluetooth/DockService.java
@@ -30,7 +30,6 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.SharedPreferences;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -58,8 +57,6 @@
     // TODO clean up logs. Disable DEBUG flag for this file and receiver's too
     private static final boolean DEBUG = true;
 
-    private static final String SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK = "auto_connect_to_dock";
-
     // Time allowed for the device to be undocked and redocked without severing
     // the bluetooth connection
     private static final long UNDOCKED_GRACE_PERIOD = 1000;
@@ -214,7 +211,7 @@
                     }
 
                     mDevice = device;
-                    if (getAutoConnectSetting(mBtManager, device.getAddress())) {
+                    if (mBtManager.getDockAutoConnectSetting(device.getAddress())) {
                         // Setting == auto connect
                         initBtSettings(mContext, device, state, false);
                         applyBtSettings(mDevice, startId);
@@ -291,7 +288,7 @@
         startForeground(0, new Notification());
 
         // Device in a new dock.
-        boolean firstTime = !hasAutoConnectSetting(mBtManager, device.getAddress());
+        boolean firstTime = !mBtManager.hasDockAutoConnectSetting(device.getAddress());
 
         CharSequence[] items = initBtSettings(service, device, state, firstTime);
 
@@ -309,14 +306,15 @@
         CheckBox rememberCheckbox = (CheckBox) view.findViewById(R.id.remember);
 
         // check "Remember setting" by default if no value was saved
-        boolean checked = firstTime || getAutoConnectSetting(mBtManager, device.getAddress());
+        boolean checked = firstTime || mBtManager.getDockAutoConnectSetting(device.getAddress());
         rememberCheckbox.setChecked(checked);
         rememberCheckbox.setOnCheckedChangeListener(this);
         int viewSpacingLeft = (int) (14 * pixelScaleFactor);
         int viewSpacingRight = (int) (14 * pixelScaleFactor);
         ab.setView(view, viewSpacingLeft, 0 /* top */, viewSpacingRight, 0 /* bottom */);
         if (DEBUG) {
-            Log.d(TAG, "Auto connect = " + getAutoConnectSetting(mBtManager, device.getAddress()));
+            Log.d(TAG, "Auto connect = "
+                    + mBtManager.getDockAutoConnectSetting(device.getAddress()));
         }
 
         // Ok Button
@@ -339,7 +337,7 @@
     // Called when the "Remember" Checkbox is clicked
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
         if (DEBUG) Log.d(TAG, "onCheckedChanged: Remember Settings = " + isChecked);
-        saveAutoConnectSetting(mBtManager, mDevice.getAddress(), isChecked);
+        mBtManager.saveDockAutoConnectSetting(mDevice.getAddress(), isChecked);
     }
 
     // Called when the dialog is dismissed
@@ -355,8 +353,8 @@
     // Called when clicked on the OK button
     public void onClick(DialogInterface dialog, int which) {
         if (which == DialogInterface.BUTTON_POSITIVE) {
-            if (!hasAutoConnectSetting(mBtManager, mDevice.getAddress())) {
-                saveAutoConnectSetting(mBtManager, mDevice.getAddress(), true);
+            if (!mBtManager.hasDockAutoConnectSetting(mDevice.getAddress())) {
+                mBtManager.saveDockAutoConnectSetting(mDevice.getAddress(), true);
             }
 
             applyBtSettings(mDevice, mStartIdAssociatedWithDialog);
@@ -514,23 +512,6 @@
         return cachedBluetoothDevice;
     }
 
-    public static boolean hasAutoConnectSetting(LocalBluetoothManager localManager, String addr) {
-        return localManager.getSharedPreferences().contains(
-                SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK + addr);
-    }
-
-    public static boolean getAutoConnectSetting(LocalBluetoothManager localManager, String addr) {
-        return localManager.getSharedPreferences().getBoolean(
-                SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK + addr, false);
-    }
-
-    public static void saveAutoConnectSetting(LocalBluetoothManager localManager, String addr,
-            boolean autoConnect) {
-        SharedPreferences.Editor editor = localManager.getSharedPreferences().edit();
-        editor.putBoolean(SHARED_PREFERENCE_KEY_AUTO_CONNECT_TO_DOCK + addr, autoConnect);
-        editor.commit();
-    }
-
     // TODO Delete this method if not needed.
     private Notification getNotification(Service service) {
         CharSequence title = service.getString(R.string.dock_settings_title);
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothManager.java b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
index acab88c..ec5c6bc 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothManager.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothManager.java
@@ -78,6 +78,8 @@
     private static final String SHARED_PREFERENCES_KEY_LAST_SELECTED_DEVICE_TIME =
         "last_selected_device_time";
 
+    private static final String SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT = "auto_connect_to_dock";
+
     private long mLastScan;
 
     public static LocalBluetoothManager getInstance(Context context) {
@@ -339,4 +341,25 @@
                 System.currentTimeMillis());
         editor.commit();
     }
+
+    public boolean hasDockAutoConnectSetting(String addr) {
+        return getSharedPreferences().contains(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr);
+    }
+
+    public boolean getDockAutoConnectSetting(String addr) {
+        return getSharedPreferences().getBoolean(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr,
+                false);
+    }
+
+    public void saveDockAutoConnectSetting(String addr, boolean autoConnect) {
+        SharedPreferences.Editor editor = getSharedPreferences().edit();
+        editor.putBoolean(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr, autoConnect);
+        editor.commit();
+    }
+
+    public void removeDockAutoConnectSetting(String addr) {
+        SharedPreferences.Editor editor = getSharedPreferences().edit();
+        editor.remove(SHARED_PREFERENCES_KEY_DOCK_AUTO_CONNECT + addr);
+        editor.commit();
+    }
 }