Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40957958 authored by Cody Liu's avatar Cody Liu Committed by Android (Google) Code Review
Browse files

Merge "Generate battery info from a disconnected device" into main

parents 6f1ce3a0 6a6d3830
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -214,6 +214,17 @@
    <string name="bluetooth_battery_level_untethered_left">Left: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
    <!-- Connected devices settings. Message when Bluetooth is connected but not in use, showing remote device battery level for the right part of the untethered headset. [CHAR LIMIT=NONE] -->
    <string name="bluetooth_battery_level_untethered_right">Right: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
    <!-- Connected devices settings. Message when bluetooth device is disconnected, showing battery level for the left part of the BATT device. [CHAR LIMIT=NONE] -->
    <string name="bluetooth_battery_level_untethered_case">Case: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g> battery</string>
    <!-- Connected devices settings. Message when bluetooth device is discoonected, showing remote device status and battery level for the left part and case of the BATT device. [CHAR LIMIT=NONE] -->
    <string name="bluetooth_battery_level_untethered_left_case">Left: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, Case: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
    <!-- Connected devices settings. Message when bluetooth device is discoonected, showing remote device status and battery level for the right part and case of the BATT device. [CHAR LIMIT=NONE] -->
    <string name="bluetooth_battery_level_untethered_right_case">Right: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, Case: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
    <!-- Connected devices settings. Message when bluetooth device is discoonected, showing remote device status and battery level for the left and right parts of the BATT device. [CHAR LIMIT=NONE] -->
    <string name="bluetooth_battery_level_untethered_left_right">Left: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, Right: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g> battery</string>
    <!-- Connected devices settings. Message when bluetooth device is discoonected, showing remote device status and battery level for the left, case, and right parts of the BATT device. [CHAR LIMIT=NONE] -->
    <string name="bluetooth_battery_level_untethered_left_case_right">L: <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g>, C: <xliff:g id="battery_level_as_percentage" example="25%">%2$s</xliff:g>, R: <xliff:g id="battery_level_as_percentage" example="25%">%3$s</xliff:g> battery</string>

    <!-- Connected devices settings. Message when Bluetooth is connected, showing remote device battery level for the left part of the untethered headset. [CHAR LIMIT=NONE] -->
    <string name="tv_bluetooth_battery_level_untethered_left">Left <xliff:g id="battery_level_as_percentage" example="25%">%1$s</xliff:g></string>
    <!-- Connected devices settings. Message when Bluetooth is connected, showing remote device battery level for the right part of the untethered headset. [CHAR LIMIT=NONE] -->
+13 −0
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ public class BluetoothUtils {
            "bluetooth_le_audio_sharing_ui_preview_enabled";
    private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
    private static final String KEY_HEARABLE_CONTROL_SLICE = "HEARABLE_CONTROL_SLICE_WITH_WIDTH";
    private static final String KEY_BATTERY_ALL_THE_TIME = "BATT";
    private static final Set<Integer> SA_PROFILES =
            ImmutableSet.of(
                    BluetoothProfile.A2DP, BluetoothProfile.LE_AUDIO);
@@ -562,6 +563,18 @@ public class BluetoothUtils {
        return getFastPairCustomizedField(bluetoothDevice, KEY_HEARABLE_CONTROL_SLICE);
    }

    /**
     * Check if battery all the time is supported for the given Bluetooth device.
     *
     * @param bluetoothDevice the BluetoothDevice to check
     * @return true if battery all the time is supported, false otherwise
     */
    public static boolean isBatteryAllTheTimeSupported(@Nullable BluetoothDevice bluetoothDevice) {
        String value = getFastPairCustomizedField(bluetoothDevice, KEY_BATTERY_ALL_THE_TIME);
        Log.d(TAG, "Is BATT supported: " + value);
        return Boolean.parseBoolean(value);
    }

    /**
     * Check if the Bluetooth device is an AvailableMediaBluetoothDevice, which means: 1) currently
     * connected 2) is Hearing Aid or LE Audio OR 3) connected profile matches currentAudioProfile
+60 −0
Original line number Diff line number Diff line
@@ -1720,6 +1720,12 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
                    stringRes = getHearingDeviceSummaryRes(leftBattery, rightBattery, shortSummary);
                }
            }
        } else if (Flags.fixBatteryLevelInConnectionSummary()
                && BluetoothUtils.isBatteryAllTheTimeSupported(mDevice)) {
            batteryLevelsInfo = getBatteryLevelsInfo();
            if (batteryLevelsInfo != null) {
                return getBatteryAllTheTimeInfo(batteryLevelsInfo);
            }
        }

        if (stringRes == R.string.bluetooth_pairing
@@ -1757,6 +1763,60 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
        }
    }

    @VisibleForTesting
    String getBatteryAllTheTimeInfo(BatteryLevelsInfo batteryLevels) {
        Log.d(TAG, "Battery levels: " + batteryLevels);

        final int leftLevel = batteryLevels.getLeftBatteryLevel();
        final int caseLevel = batteryLevels.getCaseBatteryLevel();
        final int rightLevel = batteryLevels.getRightBatteryLevel();

        final boolean isLeftKnown = leftLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
        final boolean isCaseKnown = caseLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
        final boolean isRightKnown = rightLevel > BluetoothDevice.BATTERY_LEVEL_UNKNOWN;

        // Case 1: All three battery levels are known
        if (isLeftKnown && isCaseKnown && isRightKnown) {
            return mContext.getString(
                    R.string.bluetooth_battery_level_untethered_left_case_right,
                    Utils.formatPercentage(leftLevel),
                    Utils.formatPercentage(caseLevel),
                    Utils.formatPercentage(rightLevel));
        }

        // Case 2: Two battery levels are known
        if (isLeftKnown && isCaseKnown) {
            return mContext.getString(R.string.bluetooth_battery_level_untethered_left_case,
                    Utils.formatPercentage(leftLevel),
                    Utils.formatPercentage(caseLevel));
        }
        if (isLeftKnown && isRightKnown) {
            return mContext.getString(R.string.bluetooth_battery_level_untethered_left_right,
                    Utils.formatPercentage(leftLevel),
                    Utils.formatPercentage(rightLevel));
        }
        if (isCaseKnown && isRightKnown) {
            return mContext.getString(R.string.bluetooth_battery_level_untethered_right_case,
                    Utils.formatPercentage(rightLevel), // Assuming R.string expects right then case
                    Utils.formatPercentage(caseLevel));
        }

        // Case 3: Only one battery level is known
        if (isLeftKnown) {
            return mContext.getString(R.string.bluetooth_battery_level_untethered_left,
                    Utils.formatPercentage(leftLevel));
        }
        if (isCaseKnown) {
            return mContext.getString(R.string.bluetooth_battery_level_untethered_case,
                    Utils.formatPercentage(caseLevel));
        }
        if (isRightKnown) {
            return mContext.getString(R.string.bluetooth_battery_level_untethered_right,
                    Utils.formatPercentage(rightLevel));
        }
        return "";
    }

    /**
     * Returns the battery levels of all components of the bluetooth device. If no battery info is
     * available then returns null.
+83 −0
Original line number Diff line number Diff line
@@ -318,6 +318,89 @@ public class BluetoothUtilsTest {
                .isEqualTo(STRING_METADATA);
    }

    @Test
    public void isBatteryAllTheTimeSupported_nullDevice_returnsFalse() {
        assertFalse(BluetoothUtils.isBatteryAllTheTimeSupported(null));
    }

    @Test
    public void isBatteryAllTheTimeSupported_noMetadata_returnsFalse() {
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(null);

        assertFalse(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_emptyMetadataString_returnsFalse() {
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn("".getBytes());

        assertFalse(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_metadataWithoutBattTag_returnsFalse() {
        String metadata = "<OTHERTAG>someValue</OTHERTAG>";
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(metadata.getBytes());

        assertFalse(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_metadataWithBattTagTrue_returnsTrue() {
        String metadata = "<BATT>true</BATT>";
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(metadata.getBytes());

        assertTrue(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_metadataWithBattTagTRUECaseInsensitive_returnsTrue() {
        String metadata = "<BATT>TRUE</BATT>";
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(metadata.getBytes());

        assertTrue(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_metadataWithBattTagFalse_returnsFalse() {
        String metadata = "<BATT>false</BATT>";
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(metadata.getBytes());

        assertFalse(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_metadataWithBattTagEmptyValue_returnsFalse() {
        String metadata = "<BATT></BATT>";
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(metadata.getBytes());

        assertFalse(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_metadataWithBattTagOtherString_returnsFalse() {
        String metadata = "<BATT>someOtherValue</BATT>";
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(metadata.getBytes());

        assertFalse(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }

    @Test
    public void isBatteryAllTheTimeSupported_metadataWithBattTagAndOtherTags_returnsTrue() {
        String metadata = "<OTHER>info</OTHER><BATT>true</BATT><MORE>data</MORE>";
        when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(metadata.getBytes());

        assertTrue(BluetoothUtils.isBatteryAllTheTimeSupported(mBluetoothDevice));
    }
    @Test
    public void isAdvancedDetailsHeader_untetheredHeadset_returnTrue() {
        when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET))
+262 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.util.LruCache;
import android.view.InputDevice;

import com.android.settingslib.R;
import com.android.settingslib.Utils;
import com.android.settingslib.media.flags.Flags;
import com.android.settingslib.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settingslib.utils.ThreadUtils;
@@ -89,6 +90,10 @@ public class CachedBluetoothDeviceTest {
    private static final String MAIN_BATTERY = "80";
    private static final String TEMP_BOND_METADATA =
            "<TEMP_BOND_TYPE>le_audio_sharing</TEMP_BOND_TYPE>";
    private static final String BATTERY_ALL_THE_TIME_METADATA_SUPPORTED =
            "<BATT>true</BATT>";
    private static final String BATTERY_ALL_THE_TIME_METADATA_NOT_SUPPORTED =
            "<BATT>false</BATT>";
    private static final short RSSI_1 = 10;
    private static final short RSSI_2 = 11;
    private static final boolean JUSTDISCOVERED_1 = true;
@@ -2631,6 +2636,263 @@ public class CachedBluetoothDeviceTest {
        verify(mBluetoothAdapter).addOnMetadataChangedListener(eq(mSubDevice), any(), any());
    }

    @Test
    public void getBatteryAllTheTimeInfo_allKnown_returnsAllThree() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                50,
                60,
                70,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_left_case_right,
                Utils.formatPercentage(50),
                Utils.formatPercentage(70),
                Utils.formatPercentage(60));

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEqualTo(expectedSummary);
    }

    @Test
    public void getBatteryAllTheTimeInfo_leftAndCaseKnown_returnsLeftAndCase() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                50,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                70,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_left_case,
                Utils.formatPercentage(50),
                Utils.formatPercentage(70));

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEqualTo(expectedSummary);
    }

    @Test
    public void getBatteryAllTheTimeInfo_leftAndRightKnown_returnsLeftAndRight() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                50,
                60,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_left_right,
                Utils.formatPercentage(50),
                Utils.formatPercentage(60));

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEqualTo(expectedSummary);
    }

    @Test
    public void getBatteryAllTheTimeInfo_rightAndCaseKnown_returnsRightAndCase() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                60,
                70,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_right_case,
                Utils.formatPercentage(60),
                Utils.formatPercentage(70));

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEqualTo(expectedSummary);
    }

    @Test
    public void getBatteryAllTheTimeInfo_onlyLeftKnown_returnsLeft() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                50,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_left,
                Utils.formatPercentage(50));

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEqualTo(expectedSummary);
    }

    @Test
    public void getBatteryAllTheTimeInfo_onlyCaseKnown_returnsCase() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                70,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_case,
                Utils.formatPercentage(70));

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEqualTo(expectedSummary);
    }

    @Test
    public void getBatteryAllTheTimeInfo_onlyRightKnown_returnsRight() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                60,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_right,
                Utils.formatPercentage(60));

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEqualTo(expectedSummary);
    }

    @Test
    public void getBatteryAllTheTimeInfo_allUnknown_returnsEmptyString() {
        // Arrange
        BatteryLevelsInfo batteryLevelsInfo = new BatteryLevelsInfo(
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN,
                BluetoothDevice.BATTERY_LEVEL_UNKNOWN
        );

        // Act
        String actualSummary = mCachedDevice.getBatteryAllTheTimeInfo(batteryLevelsInfo);

        // Assert
        assertThat(actualSummary).isEmpty();
    }

    @Test
    @EnableFlags(com.android.settingslib.flags.Flags.FLAG_FIX_BATTERY_LEVEL_IN_CONNECTION_SUMMARY)
    public void getConnectionSummary_notConnectedWithAllTimeBattery_returnsAllTimeBatteryInfo() {
        // Arrange: device is not connected, supports battery all the time, and has battery info
        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
        when(mDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(BATTERY_ALL_THE_TIME_METADATA_SUPPORTED.getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
                "true".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
                "50".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
                "60".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY)).thenReturn(
                "70".getBytes());
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered_left_case_right,
                Utils.formatPercentage(50),
                Utils.formatPercentage(70),
                Utils.formatPercentage(60));

        // Act
        CharSequence summary = mCachedDevice.getConnectionSummary();

        // Assert
        assertThat(summary.toString()).isEqualTo(expectedSummary);
    }

    @Test
    @EnableFlags(com.android.settingslib.flags.Flags.FLAG_FIX_BATTERY_LEVEL_IN_CONNECTION_SUMMARY)
    public void getConnectionSummary_connectedWithAllTimeBattery_returnsStandardSummary() {
        // Arrange
        updateProfileStatus(mLeAudioProfile, BluetoothProfile.STATE_CONNECTED);
        String expectedSummary = mContext.getString(
                R.string.bluetooth_battery_level_untethered, "50%", "60%");
        when(mDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(BATTERY_ALL_THE_TIME_METADATA_SUPPORTED.getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
                "true".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
                "50".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
                "60".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY)).thenReturn(
                "70".getBytes());

        // Act
        CharSequence summary = mCachedDevice.getConnectionSummary();

        // Assert
        assertThat(summary.toString()).isEqualTo(expectedSummary);
    }

    @Test
    @EnableFlags(com.android.settingslib.flags.Flags.FLAG_FIX_BATTERY_LEVEL_IN_CONNECTION_SUMMARY)
    public void getConnectionSummary_notConnectedAndNotSupportAllTimeBattery_returnsNull() {
        // Arrange
        when(mCachedDevice.getProfiles()).thenReturn(new ArrayList<>());
        when(mDevice.isConnected()).thenReturn(false);
        when(mDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(BATTERY_ALL_THE_TIME_METADATA_NOT_SUPPORTED.getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
                "true".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY)).thenReturn(
                "50".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_RIGHT_BATTERY)).thenReturn(
                "60".getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_UNTETHERED_CASE_BATTERY)).thenReturn(
                "70".getBytes());


        // Act
        CharSequence summary = mCachedDevice.getConnectionSummary();

        // Assert
        assertThat(summary).isNull();
    }

    @Test
    @EnableFlags(com.android.settingslib.flags.Flags.FLAG_FIX_BATTERY_LEVEL_IN_CONNECTION_SUMMARY)
    public void getConnectionSummary_notConnectedWithAllTimeBatteryButNoLevels_returnsNull() {
        // Arrange
        updateProfileStatus(mPanProfile, BluetoothProfile.STATE_DISCONNECTED);
        when(mDevice.isConnected()).thenReturn(false);
        when(mDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
                .thenReturn(BATTERY_ALL_THE_TIME_METADATA_SUPPORTED.getBytes());
        when(mDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)).thenReturn(
                "true".getBytes());
        // Act
        CharSequence summary = mCachedDevice.getConnectionSummary();

        // Assert
        assertThat(summary).isNull();
    }

    private void updateProfileStatus(LocalBluetoothProfile profile, int status) {
        doReturn(status).when(profile).getConnectionStatus(mDevice);
        mCachedDevice.onProfileStateChanged(profile, status);