Merge "Accommodate BATT protocol modifications." into main
diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
index ab0ed45..d0962be 100644
--- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java
@@ -91,6 +91,7 @@
     private static final String ESTIMATE_READY = "estimate_ready";
     private static final String DATABASE_ID = "id";
     private static final String DATABASE_BLUETOOTH = "Bluetooth";
+    private static final String TAG_BATT = "BATT";
     private static final long TIME_OF_HOUR = TimeUnit.SECONDS.toMillis(3600);
     private static final long TIME_OF_MINUTE = TimeUnit.SECONDS.toMillis(60);
     private static final int LEFT_DEVICE_ID = 1;
@@ -268,6 +269,30 @@
                                                         BluetoothDevice.METADATA_MAIN_BATTERY)
                                                 != BluetoothUtils.META_INT_ERROR);
                             });
+            Supplier<Boolean> isBattEnabled =
+                    Suppliers.memoize(
+                            () ->
+                                    Boolean.valueOf(
+                                            BluetoothUtils.getFastPairCustomizedField(
+                                                    mCachedDevice.getDevice(), TAG_BATT)));
+            Supplier<Integer> leftBatteryLevel =
+                    Suppliers.memoize(
+                            () ->
+                                    BluetoothUtils.getIntMetaData(
+                                            mCachedDevice.getDevice(),
+                                            BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY));
+            Supplier<Integer> rightBatteryLevel =
+                    Suppliers.memoize(
+                            () ->
+                                    BluetoothUtils.getIntMetaData(
+                                            mCachedDevice.getDevice(),
+                                            BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY));
+            Supplier<Integer> caseBatteryLevel =
+                    Suppliers.memoize(
+                            () ->
+                                    BluetoothUtils.getIntMetaData(
+                                            mCachedDevice.getDevice(),
+                                            BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY));
             preloadAndRun(
                     List.of(deviceName, disconnected, isUntetheredHeadset, summaryText),
                     () -> {
@@ -277,7 +302,16 @@
                         final TextView summary =
                                 mLayoutPreference.findViewById(R.id.entity_header_summary);
 
-                        if (disconnected.get()) {
+                        final boolean isBatteryLevelAvailable =
+                                Flags.enableBatteryLevelDisplay()
+                                        && isBattEnabled.get()
+                                        && (leftBatteryLevel.get() > BluetoothUtils.META_INT_ERROR
+                                                || rightBatteryLevel.get()
+                                                        > BluetoothUtils.META_INT_ERROR
+                                                || caseBatteryLevel.get()
+                                                        > BluetoothUtils.META_INT_ERROR);
+
+                        if (disconnected.get() && !isBatteryLevelAvailable) {
                             summary.setText(summaryText.get());
                             updateDisconnectLayout();
                             return;
diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
index 53a8f5d..8880e2c 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java
@@ -28,6 +28,7 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
+import android.platform.test.annotations.DisableFlags;
 import android.platform.test.annotations.EnableFlags;
 import android.platform.test.flag.junit.SetFlagsRule;
 import android.view.LayoutInflater;
@@ -551,6 +552,104 @@
         assertThat(button.getVisibility()).isEqualTo(View.GONE);
     }
 
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_BATTERY_LEVEL_DISPLAY)
+    public void enableBatt_budsDisconnected_batteryLevelShown() {
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE))
+                .thenReturn(BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET.getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+                .thenReturn(String.valueOf(false).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_LEFT).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_RIGHT).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_MAIN).getBytes());
+        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
+                .thenReturn("<BATT>true</BATT>".getBytes());
+        when(mCachedDevice.isConnected()).thenReturn(false);
+
+        mController.refresh();
+
+        assertBatteryLevel(mLayoutPreference.findViewById(R.id.layout_left), BATTERY_LEVEL_LEFT);
+        assertBatteryLevel(mLayoutPreference.findViewById(R.id.layout_right), BATTERY_LEVEL_RIGHT);
+        assertBatteryLevel(mLayoutPreference.findViewById(R.id.layout_middle), BATTERY_LEVEL_MAIN);
+    }
+
+    @Test
+    @DisableFlags(Flags.FLAG_ENABLE_BATTERY_LEVEL_DISPLAY)
+    public void disableBatt_budsDisconnected_batteryLevelNotShown() {
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE))
+                .thenReturn(BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET.getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+                .thenReturn(String.valueOf(false).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_LEFT).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_RIGHT).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_MAIN).getBytes());
+        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
+                .thenReturn("<BATT>true</BATT>".getBytes());
+        when(mCachedDevice.isConnected()).thenReturn(false);
+
+        mController.refresh();
+
+        assertThat(mLayoutPreference.findViewById(R.id.layout_left).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(mLayoutPreference.findViewById(R.id.layout_right).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(
+                        mLayoutPreference
+                                .findViewById(R.id.layout_middle)
+                                .findViewById(R.id.bt_battery_summary)
+                                .getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(
+                        mLayoutPreference
+                                .findViewById(R.id.layout_middle)
+                                .findViewById(R.id.bt_battery_icon)
+                                .getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_BATTERY_LEVEL_DISPLAY)
+    public void disableFastPairBatt_budsDisconnected_batteryLevelNotShown() {
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_DEVICE_TYPE))
+                .thenReturn(BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET.getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+                .thenReturn(String.valueOf(false).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_LEFT).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_RIGHT).getBytes());
+        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY))
+                .thenReturn(String.valueOf(BATTERY_LEVEL_MAIN).getBytes());
+        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
+                .thenReturn("<BATT>false</BATT>".getBytes());
+        when(mCachedDevice.isConnected()).thenReturn(false);
+
+        mController.refresh();
+
+        assertThat(mLayoutPreference.findViewById(R.id.layout_left).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(mLayoutPreference.findViewById(R.id.layout_right).getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(
+                mLayoutPreference
+                        .findViewById(R.id.layout_middle)
+                        .findViewById(R.id.bt_battery_summary)
+                        .getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+        assertThat(
+                mLayoutPreference
+                        .findViewById(R.id.layout_middle)
+                        .findViewById(R.id.bt_battery_icon)
+                        .getVisibility())
+                .isNotEqualTo(View.VISIBLE);
+    }
+
     private void assertBatteryPredictionVisible(LinearLayout linearLayout, int visible) {
         final TextView textView = linearLayout.findViewById(R.id.bt_battery_prediction);
         assertThat(textView.getVisibility()).isEqualTo(visible);