Merge "Show only 1 entry for hearing aid devices without killing the activity." into pi-dev
diff --git a/res/layout-sw320dp/settings_entity_header.xml b/res/layout-sw320dp/settings_entity_header.xml
index 481a9c4..79e12a9 100644
--- a/res/layout-sw320dp/settings_entity_header.xml
+++ b/res/layout-sw320dp/settings_entity_header.xml
@@ -81,6 +81,17 @@
                 android:textAppearance="@android:style/TextAppearance.Material.Body1"
                 android:textColor="?android:attr/textColorSecondary" />
 
+            <TextView
+                android:id="@+id/entity_header_second_summary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="start"
+                android:singleLine="true"
+                android:ellipsize="marquee"
+                android:textAlignment="viewStart"
+                android:textAppearance="@android:style/TextAppearance.Material.Body1"
+                android:textColor="?android:attr/textColorSecondary" />
+
         </LinearLayout>
     </LinearLayout>
 
diff --git a/res/layout/settings_entity_header.xml b/res/layout/settings_entity_header.xml
index 2660ef0..b534c5e 100644
--- a/res/layout/settings_entity_header.xml
+++ b/res/layout/settings_entity_header.xml
@@ -75,6 +75,17 @@
             android:textAppearance="@android:style/TextAppearance.Material.Body1"
             android:textColor="?android:attr/textColorSecondary" />
 
+        <TextView
+            android:id="@+id/entity_header_second_summary"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="start"
+            android:singleLine="true"
+            android:ellipsize="marquee"
+            android:textAlignment="viewStart"
+            android:textAppearance="@android:style/TextAppearance.Material.Body1"
+            android:textColor="?android:attr/textColorSecondary" />
+
     </LinearLayout>
 
     <LinearLayout
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
index df7b601..8679b55 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
@@ -22,11 +22,14 @@
 import android.support.v7.preference.PreferenceScreen;
 import android.util.Pair;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.applications.LayoutPreference;
 import com.android.settings.widget.EntityHeaderController;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
 
 /**
  * This class adds a header with device name and status (connected/disconnected, etc.).
@@ -35,10 +38,15 @@
     private static final String KEY_DEVICE_HEADER = "bluetooth_device_header";
 
     private EntityHeaderController mHeaderController;
+    private LocalBluetoothManager mLocalManager;
+    private CachedBluetoothDeviceManager mDeviceManager;
 
     public BluetoothDetailsHeaderController(Context context, PreferenceFragment fragment,
-            CachedBluetoothDevice device, Lifecycle lifecycle) {
+            CachedBluetoothDevice device, Lifecycle lifecycle,
+            LocalBluetoothManager bluetoothManager) {
         super(context, fragment, device, lifecycle);
+        mLocalManager = bluetoothManager;
+        mDeviceManager = mLocalManager.getCachedDeviceManager();
     }
 
     @Override
@@ -55,6 +63,12 @@
                 .getBtClassDrawableWithDescription(mContext, mCachedDevice,
                 mContext.getResources().getFraction(R.fraction.bt_battery_scale_fraction, 1, 1));
         String summaryText = mCachedDevice.getConnectionSummary();
+        // If both the hearing aids are connected, two battery status should be shown.
+        final String pairDeviceSummary = mDeviceManager
+            .getHearingAidPairDeviceSummary(mCachedDevice);
+        if (pairDeviceSummary != null) {
+            mHeaderController.setSecondSummary(pairDeviceSummary);
+        }
         mHeaderController.setLabel(mCachedDevice.getName());
         mHeaderController.setIcon(pair.first);
         mHeaderController.setIconContentDescription(pair.second);
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index b9cfa00..1e82889 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -142,7 +142,7 @@
         if (mCachedDevice != null) {
             Lifecycle lifecycle = getLifecycle();
             controllers.add(new BluetoothDetailsHeaderController(context, this, mCachedDevice,
-                    lifecycle));
+                    lifecycle, mManager));
             controllers.add(new BluetoothDetailsButtonsController(context, this, mCachedDevice,
                     lifecycle));
             controllers.add(new BluetoothDetailsProfilesController(context, this, mManager,
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
index 67cf299..f71d27a 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceUpdater.java
@@ -152,7 +152,12 @@
     }
 
     @Override
-    public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {}
+    public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
+        // Used to combine the hearing aid entries just after pairing. Once both the hearing aids
+        // get connected and their hiSyncId gets populated, this gets called for one of the
+        // 2 hearing aids so that only one entry in the connected devices list will be seen.
+        removePreference(cachedDevice);
+    }
 
     @Override
     public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
diff --git a/src/com/android/settings/widget/EntityHeaderController.java b/src/com/android/settings/widget/EntityHeaderController.java
index 4ebc369..5131159 100644
--- a/src/com/android/settings/widget/EntityHeaderController.java
+++ b/src/com/android/settings/widget/EntityHeaderController.java
@@ -85,6 +85,8 @@
     private String mIconContentDescription;
     private CharSequence mLabel;
     private CharSequence mSummary;
+    // Required for hearing aid devices.
+    private CharSequence mSecondSummary;
     private String mPackageName;
     private Intent mAppNotifPrefIntent;
     @UserIdInt
@@ -181,6 +183,18 @@
         return this;
     }
 
+    public EntityHeaderController setSecondSummary(CharSequence summary) {
+        mSecondSummary = summary;
+        return this;
+    }
+
+    public EntityHeaderController setSecondSummary(PackageInfo packageInfo) {
+        if (packageInfo != null) {
+            mSummary = packageInfo.versionName;
+        }
+        return this;
+    }
+
     public EntityHeaderController setHasAppInfoLink(boolean hasAppInfoLink) {
         mHasAppInfoLink = hasAppInfoLink;
         return this;
@@ -242,6 +256,7 @@
         }
         setText(R.id.entity_header_title, mLabel);
         setText(R.id.entity_header_summary, mSummary);
+        setText(R.id.entity_header_second_summary, mSecondSummary);
         if (mIsInstantApp) {
             setText(R.id.install_type,
                     mHeader.getResources().getString(R.string.install_type_instant));
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
index 39ec535..2567f53 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
@@ -32,6 +32,9 @@
 import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
 import com.android.settings.widget.EntityHeaderController;
 
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+
 import org.junit.After;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -50,14 +53,21 @@
 
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private EntityHeaderController mHeaderController;
+    @Mock
+    private LocalBluetoothManager mBluetoothManager;
+    @Mock
+    private CachedBluetoothDeviceManager mCachedDeviceManager;
 
     @Override
     public void setUp() {
         super.setUp();
         FakeFeatureFactory.setupForTest();
         ShadowEntityHeaderController.setUseMock(mHeaderController);
+        when(mBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
+        when(mCachedDeviceManager.getHearingAidPairDeviceSummary(mCachedDevice)).thenReturn("abc");
         mController =
-            new BluetoothDetailsHeaderController(mContext, mFragment, mCachedDevice, mLifecycle);
+            new BluetoothDetailsHeaderController(mContext, mFragment, mCachedDevice, mLifecycle,
+                mBluetoothManager);
         mPreference = new LayoutPreference(mContext, R.layout.settings_entity_header);
         mPreference.setKey(mController.getPreferenceKey());
         mScreen.addPreference(mPreference);
@@ -86,6 +96,7 @@
         verify(mHeaderController).setIcon(any(Drawable.class));
         verify(mHeaderController).setIconContentDescription(any(String.class));
         verify(mHeaderController).setSummary(any(String.class));
+        verify(mHeaderController).setSecondSummary(any(String.class));
         verify(mHeaderController).done(mActivity, true);
     }
 
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
index 5334833..905924d 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceUpdaterTest.java
@@ -107,6 +107,16 @@
     }
 
     @Test
+    public void testOnDeviceDeleted_deviceExists_removePreference() {
+        mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, mPreference);
+
+        mBluetoothDeviceUpdater.onDeviceDeleted(mCachedBluetoothDevice);
+
+        verify(mDevicePreferenceCallback).onDeviceRemoved(mPreference);
+        assertThat(mBluetoothDeviceUpdater.mPreferenceMap.containsKey(mBluetoothDevice)).isFalse();
+    }
+
+    @Test
     public void testRemovePreference_deviceNotExist_doNothing() {
         mBluetoothDeviceUpdater.removePreference(mCachedBluetoothDevice);
 
diff --git a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
index 0d294d5..e32ef77 100644
--- a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
@@ -115,18 +115,22 @@
         final View header =
             mLayoutInflater.inflate(R.layout.settings_entity_header, null /* root */);
         final TextView label = header.findViewById(R.id.entity_header_title);
-        final TextView version = header.findViewById(R.id.entity_header_summary);
+        final TextView summary = header.findViewById(R.id.entity_header_summary);
+        final TextView secondSummary = header.findViewById(R.id.entity_header_second_summary);
 
         mController = EntityHeaderController.newInstance(mActivity, mFragment, header);
         mController.setLabel(testString);
         mController.setSummary(testString);
+        mController.setSecondSummary(testString);
         mController.setIcon(mShadowContext.getDrawable(R.drawable.ic_add));
         mController.done(mActivity);
 
         assertThat(label).isNotNull();
         assertThat(label.getText()).isEqualTo(testString);
-        assertThat(version).isNotNull();
-        assertThat(version.getText()).isEqualTo(testString);
+        assertThat(summary).isNotNull();
+        assertThat(summary.getText()).isEqualTo(testString);
+        assertThat(secondSummary).isNotNull();
+        assertThat(secondSummary.getText()).isEqualTo(testString);
     }
 
     @Test