[Battery] Ensure we always update the text and content description when

necessary.

When writing some tests for the new dock defend icon, I came across
some existing issues when we don't correctly update the text or content
description. This CL adds tests that would've been failing, and updates
BatteryMeterView to make them pass.

Bug: 255625888
Test: atest BatteryMeterViewTest
Change-Id: I3485a50c6471dd75dce64a3daf414208afa8d25e
This commit is contained in:
Caitlin Shkuratov
2022-11-11 17:00:47 +00:00
parent 7d779b689d
commit 29eb2d1276
3 changed files with 103 additions and 19 deletions

View File

@@ -439,7 +439,7 @@
<string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
<!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$s</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage</string>
<string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$d</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage</string>
<!-- Content description of the battery level icon for accessibility while the device is charging (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>

View File

@@ -76,6 +76,7 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
private int mLevel;
private int mShowPercentMode = MODE_DEFAULT;
private boolean mShowPercentAvailable;
private String mEstimateText = null;
private boolean mCharging;
private boolean mDisplayShield;
private boolean mDisplayShieldEnabled;
@@ -171,6 +172,7 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
if (mode == mShowPercentMode) return;
mShowPercentMode = mode;
updateShowPercent();
updatePercentText();
}
@Override
@@ -247,11 +249,11 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
void updatePercentText() {
if (mBatteryStateUnknown) {
setContentDescription(getContext().getString(R.string.accessibility_battery_unknown));
return;
}
if (mBatteryEstimateFetcher == null) {
setPercentTextAtCurrentLevel();
return;
}
@@ -263,10 +265,9 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
return;
}
if (estimate != null && mShowPercentMode == MODE_ESTIMATE) {
mEstimateText = estimate;
mBatteryPercentView.setText(estimate);
setContentDescription(getContext().getString(
R.string.accessibility_battery_level_with_estimate,
mLevel, estimate));
updateContentDescription();
} else {
setPercentTextAtCurrentLevel();
}
@@ -275,28 +276,44 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
setPercentTextAtCurrentLevel();
}
} else {
setContentDescription(
getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
: R.string.accessibility_battery_level, mLevel));
updateContentDescription();
}
}
private void setPercentTextAtCurrentLevel() {
if (mBatteryPercentView == null) {
return;
if (mBatteryPercentView != null) {
mEstimateText = null;
String percentText = NumberFormat.getPercentInstance().format(mLevel / 100f);
// Setting text actually triggers a layout pass (because the text view is set to
// wrap_content width and TextView always relayouts for this). Avoid needless
// relayout if the text didn't actually change.
if (!TextUtils.equals(mBatteryPercentView.getText(), percentText)) {
mBatteryPercentView.setText(percentText);
}
}
String percentText = NumberFormat.getPercentInstance().format(mLevel / 100f);
// Setting text actually triggers a layout pass (because the text view is set to
// wrap_content width and TextView always relayouts for this). Avoid needless
// relayout if the text didn't actually change.
if (!TextUtils.equals(mBatteryPercentView.getText(), percentText)) {
mBatteryPercentView.setText(percentText);
updateContentDescription();
}
private void updateContentDescription() {
Context context = getContext();
String contentDescription;
if (mBatteryStateUnknown) {
contentDescription = context.getString(R.string.accessibility_battery_unknown);
} else if (mShowPercentMode == MODE_ESTIMATE && !TextUtils.isEmpty(mEstimateText)) {
contentDescription = context.getString(
R.string.accessibility_battery_level_with_estimate,
mLevel,
mEstimateText);
} else if (mCharging) {
contentDescription =
context.getString(R.string.accessibility_battery_level_charging, mLevel);
} else {
contentDescription = context.getString(R.string.accessibility_battery_level, mLevel);
}
setContentDescription(
getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
: R.string.accessibility_battery_level, mLevel));
setContentDescription(contentDescription);
}
void updateShowPercent() {
@@ -347,6 +364,7 @@ public class BatteryMeterView extends LinearLayout implements DarkReceiver {
}
mBatteryStateUnknown = isUnknown;
updateContentDescription();
if (mBatteryStateUnknown) {
mBatteryIconView.setImageDrawable(getUnknownStateDrawable());

View File

@@ -19,6 +19,7 @@ import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.widget.ImageView
import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.battery.BatteryMeterView.BatteryEstimateFetcher
import com.android.systemui.statusbar.policy.BatteryController.EstimateFetchCompletion
@@ -59,6 +60,71 @@ class BatteryMeterViewTest : SysuiTestCase() {
// No assert needed
}
@Test
fun contentDescription_unknown() {
mBatteryMeterView.onBatteryUnknownStateChanged(true)
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
context.getString(R.string.accessibility_battery_unknown)
)
}
@Test
fun contentDescription_estimate() {
mBatteryMeterView.onBatteryLevelChanged(15, false)
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
mBatteryMeterView.updatePercentText()
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
context.getString(
R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
)
)
}
@Test
fun contentDescription_charging() {
mBatteryMeterView.onBatteryLevelChanged(45, true)
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
context.getString(R.string.accessibility_battery_level_charging, 45)
)
}
@Test
fun contentDescription_notCharging() {
mBatteryMeterView.onBatteryLevelChanged(45, false)
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
context.getString(R.string.accessibility_battery_level, 45)
)
}
@Test
fun changesFromEstimateToPercent_textAndContentDescriptionChanges() {
mBatteryMeterView.onBatteryLevelChanged(15, false)
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE)
mBatteryMeterView.setBatteryEstimateFetcher(Fetcher())
mBatteryMeterView.updatePercentText()
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
context.getString(
R.string.accessibility_battery_level_with_estimate, 15, ESTIMATE
)
)
// Update the show mode from estimate to percent
mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON)
assertThat(mBatteryMeterView.batteryPercentViewText).isEqualTo("15%")
assertThat(mBatteryMeterView.contentDescription).isEqualTo(
context.getString(R.string.accessibility_battery_level, 15)
)
}
@Test
fun isOverheatedChanged_true_drawableGetsTrue() {
mBatteryMeterView.setDisplayShieldEnabled(true)