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

Commit 534998ed authored by Andrew Cheng's avatar Andrew Cheng
Browse files

Remote device battery level reported incorrectly

Per HFP specs, the AG reports battery level via CIND/CIEV with value
ranging from 0 to 5. RemoteDevices#updateBatteryLevel expects battery
level to be a percentage (i.e., an integer from 0 to 100).

In onAgIndicatorValueChanged, the integer from
BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL is passed directly into
updateBatteryLevel. It needs to be converted into a percentage first.
For example, if the remote device has a full charge,
BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL returns a 5, but this then
gets reported as 5% instead of 100%.

onHfIndicatorValueChanged will be left unchanged. Per HFP specs, the HF
reports battery level via BIND/BIEV with value ranging from 0 to 100.

Tag: #refactor
Bug: 219517423
Test: atest RemoteDevicesTest
Test: atest BluetoothInstrumentationTests
Test: manually verify a full battery is reported as 100% instead of 5%
Ignore-AOSP-First: see 16809739
Change-Id: I0c0453537905b33c78e405d3889f2de5d3e6cc57
parent 0a3715b1
Loading
Loading
Loading
Loading
+51 −1
Original line number Diff line number Diff line
@@ -72,6 +72,24 @@ final class RemoteDevices {
    private final HashMap<String, String> mDualDevicesMap;
    private Queue<String> mDeviceQueue;

    /**
     * Bluetooth HFP v1.8 specifies the Battery Charge indicator of AG can take values from
     * {@code 0} to {@code 5}, but it does not specify how to map the values back to percentages.
     * The following mapping is used:
     *   - Level 0:                 0%
     *   - Level 1: midpoint of  1-25%
     *   - Level 2: midpoint of 26-50%
     *   - Level 3: midpoint of 51-75%
     *   - Level 4: midpoint of 76-99%
     *   - Level 5:               100%
     */
    private static final int HFP_BATTERY_CHARGE_INDICATOR_0 = 0;
    private static final int HFP_BATTERY_CHARGE_INDICATOR_1 = 13;
    private static final int HFP_BATTERY_CHARGE_INDICATOR_2 = 38;
    private static final int HFP_BATTERY_CHARGE_INDICATOR_3 = 63;
    private static final int HFP_BATTERY_CHARGE_INDICATOR_4 = 88;
    private static final int HFP_BATTERY_CHARGE_INDICATOR_5 = 100;

    private final Handler mHandler;
    private class RemoteDevicesHandler extends Handler {

@@ -574,6 +592,38 @@ final class RemoteDevices {
                Utils.getTempAllowlistBroadcastOptions());
    }

    /**
     * Converts HFP's Battery Charge indicator values of {@code 0 -- 5} to an integer percentage.
     */
    @VisibleForTesting
    static int batteryChargeIndicatorToPercentge(int indicator) {
        int percent;
        switch (indicator) {
            case 5:
                percent = HFP_BATTERY_CHARGE_INDICATOR_5;
                break;
            case 4:
                percent = HFP_BATTERY_CHARGE_INDICATOR_4;
                break;
            case 3:
                percent = HFP_BATTERY_CHARGE_INDICATOR_3;
                break;
            case 2:
                percent = HFP_BATTERY_CHARGE_INDICATOR_2;
                break;
            case 1:
                percent = HFP_BATTERY_CHARGE_INDICATOR_1;
                break;
            case 0:
                percent = HFP_BATTERY_CHARGE_INDICATOR_0;
                break;
            default:
                percent = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
        }
        Log.d(TAG, "Battery charge indicator: " + indicator + "; converted to: " + percent + "%");
        return percent;
    }

    private static boolean areUuidsEqual(ParcelUuid[] uuids1, ParcelUuid[] uuids2) {
        final int length1 = uuids1 == null ? 0 : uuids1.length;
        final int length2 = uuids2 == null ? 0 : uuids2.length;
@@ -1079,7 +1129,7 @@ final class RemoteDevices {

        if (intent.hasExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL)) {
            int batteryLevel = intent.getIntExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, -1);
            updateBatteryLevel(device, batteryLevel);
            updateBatteryLevel(device, batteryChargeIndicatorToPercentge(batteryLevel));
        }
    }

+3 −2
Original line number Diff line number Diff line
@@ -487,7 +487,7 @@ public class RemoteDevicesTest {

    @Test
    public void testAGIndicatorParser_testCorrectValue() {
        int batteryLevel = 10;
        int batteryLevel = 3;

        // Verify that device property is null initially
        Assert.assertNull(mRemoteDevices.getDeviceProperties(mDevice1));
@@ -497,7 +497,8 @@ public class RemoteDevicesTest {
                getAgIndicatorIntent(mDevice1, null, null, null, new Integer(batteryLevel), null));
        verify(mAdapterService).sendBroadcast(mIntentArgument.capture(), mStringArgument.capture(),
                any(Bundle.class));
        verifyBatteryLevelChangedIntent(mDevice1, batteryLevel, mIntentArgument);
        verifyBatteryLevelChangedIntent(mDevice1,
                RemoteDevices.batteryChargeIndicatorToPercentge(batteryLevel), mIntentArgument);
        Assert.assertEquals(BLUETOOTH_CONNECT, mStringArgument.getValue());
    }