Merge "Fix settings crash"
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index 86b72ec..2e4654c 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -96,7 +96,6 @@
         }
 
         mCachedDevice = cachedDevice;
-        mCachedDevice.registerCallback(this);
         mCurrentTime = System.currentTimeMillis();
         mType = type;
 
@@ -127,13 +126,24 @@
     @Override
     protected void onPrepareForRemoval() {
         super.onPrepareForRemoval();
-        mCachedDevice.unregisterCallback(this);
         if (mDisconnectDialog != null) {
             mDisconnectDialog.dismiss();
             mDisconnectDialog = null;
         }
     }
 
+    @Override
+    public void onAttached() {
+        super.onAttached();
+        mCachedDevice.registerCallback(this);
+    }
+
+    @Override
+    public void onDetached() {
+        super.onDetached();
+        mCachedDevice.unregisterCallback(this);
+    }
+
     public CachedBluetoothDevice getBluetoothDevice() {
         return mCachedDevice;
     }
diff --git a/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java b/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
index 78791d4..438a381 100644
--- a/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
+++ b/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceController.java
@@ -51,14 +51,15 @@
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private static final int MAX_DEVICE_NUM = 3;
+    private static final int DOCK_DEVICE_INDEX = 9;
     private static final String KEY_SEE_ALL = "previously_connected_devices_see_all";
 
     private final List<Preference> mDevicesList = new ArrayList<>();
+    private final List<Preference> mDockDevicesList = new ArrayList<>();
 
     private PreferenceGroup mPreferenceGroup;
     private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
     private DockUpdater mSavedDockUpdater;
-    private int mPreferenceSize;
     private BluetoothAdapter mBluetoothAdapter;
 
     @VisibleForTesting
@@ -126,33 +127,38 @@
 
     @Override
     public void onDeviceAdded(Preference preference) {
-        mPreferenceSize++;
         final List<BluetoothDevice> bluetoothDevices =
                 mBluetoothAdapter.getMostRecentlyConnectedDevices();
-        final int index = bluetoothDevices.indexOf(((BluetoothDevicePreference) preference)
-                .getBluetoothDevice().getDevice());
+        final int index = preference instanceof BluetoothDevicePreference
+                ? bluetoothDevices.indexOf(((BluetoothDevicePreference) preference)
+                .getBluetoothDevice().getDevice()) : DOCK_DEVICE_INDEX;
         if (DEBUG) {
             Log.d(TAG, "onDeviceAdded() " + preference.getTitle() + ", index of : " + index);
             for (BluetoothDevice device : bluetoothDevices) {
                 Log.d(TAG, "onDeviceAdded() most recently device : " + device.getName());
             }
         }
-        if (mPreferenceSize <= MAX_DEVICE_NUM) {
-            addPreference(mPreferenceSize, index, preference);
-        } else {
-            addPreference(MAX_DEVICE_NUM, index, preference);
-        }
+        addPreference(index, preference);
         updatePreferenceVisibility();
     }
 
-    private void addPreference(int size, int index, Preference preference) {
-        if (mDevicesList.size() >= index) {
-            mDevicesList.add(index, preference);
+    private void addPreference(int index, Preference preference) {
+        if (preference instanceof BluetoothDevicePreference) {
+            if (mDevicesList.size() >= index) {
+                mDevicesList.add(index, preference);
+            } else {
+                mDevicesList.add(preference);
+            }
         } else {
-            mDevicesList.add(preference);
+            mDockDevicesList.add(preference);
         }
+        addPreference();
+    }
+
+    private void addPreference() {
         mPreferenceGroup.removeAll();
         mPreferenceGroup.addPreference(mSeeAllPreference);
+        final int size = getDeviceListSize();
         for (int i = 0; i < size; i++) {
             if (DEBUG) {
                 Log.d(TAG, "addPreference() add device : " + mDevicesList.get(i).getTitle());
@@ -160,23 +166,37 @@
             mDevicesList.get(i).setOrder(i);
             mPreferenceGroup.addPreference(mDevicesList.get(i));
         }
+        if (mDockDevicesList.size() > 0) {
+            for (int i = 0; i < getDockDeviceListSize(MAX_DEVICE_NUM - size); i++) {
+                if (DEBUG) {
+                    Log.d(TAG, "addPreference() add dock device : "
+                            + mDockDevicesList.get(i).getTitle());
+                }
+                mDockDevicesList.get(i).setOrder(DOCK_DEVICE_INDEX);
+                mPreferenceGroup.addPreference(mDockDevicesList.get(i));
+            }
+        }
+    }
+
+    private int getDeviceListSize() {
+        return mDevicesList.size() >= MAX_DEVICE_NUM
+                ? MAX_DEVICE_NUM : mDevicesList.size();
+    }
+
+    private int getDockDeviceListSize(int availableSize) {
+        return mDockDevicesList.size() >= availableSize
+                ? availableSize : mDockDevicesList.size();
     }
 
     @Override
     public void onDeviceRemoved(Preference preference) {
-        mPreferenceSize--;
-        mDevicesList.remove(preference);
-        mPreferenceGroup.removeAll();
-        mPreferenceGroup.addPreference(mSeeAllPreference);
-        final int size = mDevicesList.size() >= MAX_DEVICE_NUM
-                ? MAX_DEVICE_NUM : mDevicesList.size();
-        for (int i = 0; i < size; i++) {
-            if (DEBUG) {
-                Log.d(TAG, "onDeviceRemoved() add device : " + mDevicesList.get(i).getTitle());
-            }
-            mDevicesList.get(i).setOrder(i);
-            mPreferenceGroup.addPreference(mDevicesList.get(i));
+        if (preference instanceof BluetoothDevicePreference) {
+            mDevicesList.remove(preference);
+        } else {
+            mDockDevicesList.remove(preference);
         }
+
+        addPreference();
         updatePreferenceVisibility();
     }
 
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
index 3363ff5..d73471f 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/PreviouslyConnectedDevicePreferenceControllerTest.java
@@ -41,6 +41,7 @@
 import com.android.settings.connecteddevice.dock.DockUpdater;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
+import com.android.settings.widget.SingleTargetGearPreference;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 
 import org.junit.Before;
@@ -188,6 +189,16 @@
     }
 
     @Test
+    public void onDeviceAdded_addDockDevicePreference_displayIt() {
+        final SingleTargetGearPreference dockPreference = new SingleTargetGearPreference(
+                mContext, null /* AttributeSet */);
+
+        mPreConnectedDeviceController.onDeviceAdded(dockPreference);
+
+        assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(2);
+    }
+
+    @Test
     public void onDeviceAdded_addFourDevicePreference_onlyDisplayThree() {
         final BluetoothDevicePreference preference1 = new BluetoothDevicePreference(
                 mContext, mCachedDevice1, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
@@ -197,11 +208,14 @@
                 mContext, mCachedDevice3, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
         final BluetoothDevicePreference preference4 = new BluetoothDevicePreference(
                 mContext, mCachedDevice4, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
+        final SingleTargetGearPreference dockPreference = new SingleTargetGearPreference(
+                mContext, null /* AttributeSet */);
 
         mPreConnectedDeviceController.onDeviceAdded(preference1);
         mPreConnectedDeviceController.onDeviceAdded(preference2);
         mPreConnectedDeviceController.onDeviceAdded(preference3);
         mPreConnectedDeviceController.onDeviceAdded(preference4);
+        mPreConnectedDeviceController.onDeviceAdded(dockPreference);
 
         // 3 BluetoothDevicePreference and 1 see all preference
         assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(4);
@@ -211,9 +225,13 @@
     public void onDeviceRemoved_removeLastDevice_showSeeAllPreference() {
         final BluetoothDevicePreference preference1 = new BluetoothDevicePreference(
                 mContext, mCachedDevice1, true, BluetoothDevicePreference.SortType.TYPE_NO_SORT);
+        final SingleTargetGearPreference dockPreference = new SingleTargetGearPreference(
+                mContext, null /* AttributeSet */);
         mPreferenceGroup.addPreference(preference1);
+        mPreferenceGroup.addPreference(dockPreference);
 
         mPreConnectedDeviceController.onDeviceRemoved(preference1);
+        mPreConnectedDeviceController.onDeviceRemoved(dockPreference);
 
         assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
     }