Revamp battery Ui in low battery mode
This cl refine battery icon ui in low battery mode:
1. Should show indicator(fixed in ag/2035178)
2. Show bolt icon when charging
3. When battery is low, set battery background as red and indicator
as white.
This cl also includes the field updates for battery.
Bug: 36862496
Test: RunSettingsRoboTests
Change-Id: Ifb2ed339742119bbff78712df09288b895756b1f
diff --git a/res/color/battery_icon_color_error.xml b/res/color/battery_icon_color_error.xml
new file mode 100644
index 0000000..3a71aae
--- /dev/null
+++ b/res/color/battery_icon_color_error.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:alpha="@*android:dimen/secondary_content_alpha_material_dark"
+ android:color="?android:attr/colorError"/>
+</selector>
\ No newline at end of file
diff --git a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
index 7b89fb1..8588f77 100644
--- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
+++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java
@@ -511,7 +511,7 @@
elapsedRealtimeUs);
mDrainString = "";
mChargeDurationString = "";
- setContentDescription(mInfo.mChargeLabelString);
+ setContentDescription(mInfo.chargeLabelString);
int pos = 0;
int lastInteresting = 0;
@@ -589,7 +589,7 @@
mMaxPercentLabelStringWidth = (int)mTextPaint.measureText(mMaxPercentLabelString);
mMinPercentLabelStringWidth = (int)mTextPaint.measureText(mMinPercentLabelString);
mDrainStringWidth = (int)mHeaderTextPaint.measureText(mDrainString);
- mChargeLabelStringWidth = (int)mHeaderTextPaint.measureText(mInfo.mChargeLabelString);
+ mChargeLabelStringWidth = (int)mHeaderTextPaint.measureText(mInfo.chargeLabelString);
mChargeDurationStringWidth = (int)mHeaderTextPaint.measureText(mChargeDurationString);
mTextAscent = (int)mTextPaint.ascent();
mTextDescent = (int)mTextPaint.descent();
@@ -974,7 +974,7 @@
}
}
}
-
+
i++;
}
mStats.finishIteratingHistoryLocked();
@@ -983,9 +983,9 @@
if (lastY < 0 || lastX < 0) {
// Didn't get any data...
x = lastX = mLevelLeft;
- y = lastY = mLevelTop + levelh - ((mInfo.mBatteryLevel-batLow)*(levelh-1))/batChange;
+ y = lastY = mLevelTop + levelh - ((mInfo.batteryLevel -batLow)*(levelh-1))/batChange;
Path path;
- byte value = (byte)mInfo.mBatteryLevel;
+ byte value = (byte)mInfo.batteryLevel;
if (value <= mBatteryCriticalLevel) path = mBatCriticalPath;
else if (value <= mBatteryWarnLevel) path = mBatWarnPath;
else path = null; //mBatGoodPath;
@@ -1014,7 +1014,7 @@
mTimeRemainPath.moveTo(x, lastY);
int fullY = mLevelTop + levelh - ((100-batLow)*(levelh-1))/batChange;
int emptyY = mLevelTop + levelh - ((0-batLow)*(levelh-1))/batChange;
- if (mInfo.mDischarging) {
+ if (mInfo.discharging) {
mTimeRemainPath.lineTo(mLevelRight, emptyY);
} else {
mTimeRemainPath.lineTo(mLevelRight, fullY);
@@ -1211,8 +1211,8 @@
int headerTop = -mHeaderTextAscent + (mHeaderTextDescent-mHeaderTextAscent)/3;
mHeaderTextPaint.setTextAlign(textAlignLeft);
- if (DEBUG) Log.d(TAG, "Drawing charge label string: " + mInfo.mChargeLabelString);
- canvas.drawText(mInfo.mChargeLabelString, textStartX, headerTop, mHeaderTextPaint);
+ if (DEBUG) Log.d(TAG, "Drawing charge label string: " + mInfo.chargeLabelString);
+ canvas.drawText(mInfo.chargeLabelString, textStartX, headerTop, mHeaderTextPaint);
int stringHalfWidth = mChargeDurationStringWidth / 2;
if (layoutRtl) stringHalfWidth = -stringHalfWidth;
int headerCenter = ((width-mChargeDurationStringWidth-mDrainStringWidth)/2)
diff --git a/src/com/android/settings/fuelgauge/BatteryMeterView.java b/src/com/android/settings/fuelgauge/BatteryMeterView.java
index dcbf472..c450b90 100644
--- a/src/com/android/settings/fuelgauge/BatteryMeterView.java
+++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java
@@ -18,17 +18,25 @@
import android.annotation.Nullable;
import android.content.Context;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.support.annotation.VisibleForTesting;
import android.util.AttributeSet;
import android.widget.ImageView;
+
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.graph.BatteryMeterDrawableBase;
public class BatteryMeterView extends ImageView {
- private BatteryMeterDrawable mDrawable;
+ @VisibleForTesting
+ BatteryMeterDrawable mDrawable;
+ @VisibleForTesting
+ ColorFilter mErrorColorFilter;
+ @VisibleForTesting
+ ColorFilter mAccentColorFilter;
public BatteryMeterView(Context context) {
this(context, null, 0);
@@ -42,21 +50,30 @@
super(context, attrs, defStyleAttr);
final int frameColor = context.getColor(R.color.batterymeter_frame_color);
- final int tintColor = Utils.getColorAttr(context, android.R.attr.colorAccent);
+ mAccentColorFilter = new PorterDuffColorFilter(
+ Utils.getColorAttr(context, android.R.attr.colorAccent), PorterDuff.Mode.SRC_IN);
+ mErrorColorFilter = new PorterDuffColorFilter(
+ context.getColor(R.color.battery_icon_color_error), PorterDuff.Mode.SRC_IN);
mDrawable = new BatteryMeterDrawable(context, frameColor);
- mDrawable.setColorFilter(new PorterDuffColorFilter(tintColor, PorterDuff.Mode.SRC_IN));
mDrawable.setShowPercent(false);
+ mDrawable.setBatteryColorFilter(mAccentColorFilter);
+ mDrawable.setWarningColorFilter(
+ new PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN));
setImageDrawable(mDrawable);
}
- public void setBatteryInfo(int level) {
+ public void setBatteryLevel(int level) {
mDrawable.setBatteryLevel(level);
+ if (level < mDrawable.getCriticalLevel()) {
+ mDrawable.setBatteryColorFilter(mErrorColorFilter);
+ } else {
+ mDrawable.setBatteryColorFilter(mAccentColorFilter);
+ }
}
- @VisibleForTesting
- void setBatteryDrawable(BatteryMeterDrawable drawable) {
- mDrawable = drawable;
+ public void setCharging(boolean charging) {
+ mDrawable.setCharging(charging);
}
public static class BatteryMeterDrawable extends BatteryMeterDrawableBase {
@@ -81,6 +98,16 @@
public int getIntrinsicHeight() {
return mIntrinsicHeight;
}
+
+ public void setWarningColorFilter(@Nullable ColorFilter colorFilter) {
+ mWarningTextPaint.setColorFilter(colorFilter);
+ }
+
+ public void setBatteryColorFilter(@Nullable ColorFilter colorFilter) {
+ mFramePaint.setColorFilter(colorFilter);
+ mBatteryPaint.setColorFilter(colorFilter);
+ mBoltPaint.setColorFilter(colorFilter);
+ }
}
}
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index b23f9e3..2657d9e 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -568,14 +568,15 @@
.findViewById(R.id.battery_header_icon);
final TextView timeText = (TextView) mBatteryLayoutPref.findViewById(R.id.battery_percent);
final TextView summary1 = (TextView) mBatteryLayoutPref.findViewById(R.id.summary1);
- timeText.setText(Utils.formatPercentage(info.mBatteryLevel));
+ timeText.setText(Utils.formatPercentage(info.batteryLevel));
if (info.remainingLabel == null ) {
summary1.setText(info.statusLabel);
} else {
summary1.setText(info.remainingLabel);
}
- batteryView.setBatteryInfo(info.mBatteryLevel);
+ batteryView.setBatteryLevel(info.batteryLevel);
+ batteryView.setCharging(!info.discharging);
}
@VisibleForTesting
@@ -736,7 +737,7 @@
BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
@Override
public void onBatteryInfoLoaded(BatteryInfo info) {
- mLoader.setSummary(SummaryProvider.this, info.mChargeLabelString);
+ mLoader.setSummary(SummaryProvider.this, info.chargeLabelString);
}
});
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
index 85b893a..cb37a6e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
@@ -15,12 +15,17 @@
*/
package com.android.settings.fuelgauge;
+import static com.google.common.truth.Truth.assertThat;
+
import android.content.Context;
+import android.graphics.ColorFilter;
+
import com.android.settings.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.SettingsShadowResources.SettingsShadowTheme;
import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,6 +34,8 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@RunWith(SettingsRobolectricTestRunner.class)
@@ -42,10 +49,15 @@
})
public class BatteryMeterViewTest {
private static final int BATTERY_LEVEL = 100;
+ private static final int BATTERY_CRITICAL_LEVEL = 15;
+ private static final int BATTERY_LOW_LEVEL = 3;
@Mock
- private BatteryMeterView.BatteryMeterDrawable mDrawable;
+ private ColorFilter mErrorColorFilter;
+ @Mock
+ private ColorFilter mAccentColorFilter;
private Context mContext;
private BatteryMeterView mBatteryMeterView;
+ private BatteryMeterView.BatteryMeterDrawable mDrawable;
@Before
public void setUp() {
@@ -53,13 +65,33 @@
mContext = RuntimeEnvironment.application;
mBatteryMeterView = new BatteryMeterView(mContext);
- mBatteryMeterView.setBatteryDrawable(mDrawable);
+ mDrawable = spy(new BatteryMeterView.BatteryMeterDrawable(mContext, 0));
+
+ mBatteryMeterView.mDrawable = mDrawable;
+ mBatteryMeterView.mAccentColorFilter = mAccentColorFilter;
+ mBatteryMeterView.mErrorColorFilter = mErrorColorFilter;
+
+ doReturn(BATTERY_CRITICAL_LEVEL).when(mDrawable).getCriticalLevel();
}
@Test
- public void testSetBatteryInfo_SetCorrectly() {
- mBatteryMeterView.setBatteryInfo(BATTERY_LEVEL);
+ public void testSetBatteryInfo_setCorrectly() {
+ mBatteryMeterView.setBatteryLevel(BATTERY_LEVEL);
- verify(mDrawable).setBatteryLevel(BATTERY_LEVEL);
+ assertThat(mDrawable.getBatteryLevel()).isEqualTo(BATTERY_LEVEL);
+ }
+
+ @Test
+ public void testSetBatteryInfo_levelLow_setErrorColor() {
+ mBatteryMeterView.setBatteryLevel(BATTERY_LOW_LEVEL);
+
+ verify(mDrawable).setBatteryColorFilter(mErrorColorFilter);
+ }
+
+ @Test
+ public void testSetBatteryInfo_levelNormal_setNormalColor() {
+ mBatteryMeterView.setBatteryLevel(BATTERY_LEVEL);
+
+ verify(mDrawable).setBatteryColorFilter(mAccentColorFilter);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 7f59b18..da04ab2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -37,6 +37,8 @@
import com.android.settings.Utils;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowDynamicIndexableContentMonitor;
import com.android.settingslib.BatteryInfo;
import org.junit.Before;
@@ -74,7 +76,13 @@
*/
// TODO: Improve this test class so that it starts up the real activity and fragment.
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+@Config(manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ SettingsShadowResources.class,
+ SettingsShadowResources.SettingsShadowTheme.class,
+ ShadowDynamicIndexableContentMonitor.class
+ })
public class PowerUsageSummaryTest {
private static final String[] PACKAGE_NAMES = {"com.app1", "com.app2"};
private static final String TIME_LEFT = "2h30min";
@@ -123,8 +131,6 @@
@Mock
private LayoutPreference mBatteryLayoutPref;
@Mock
- private BatteryMeterView mBatteryMeterView;
- @Mock
private TextView mBatteryPercentText;
@Mock
private TextView mSummary1;
@@ -145,6 +151,7 @@
private Context mRealContext;
private TestFragment mFragment;
private FakeFeatureFactory mFeatureFactory;
+ private BatteryMeterView mBatteryMeterView;
@Before
public void setUp() {
@@ -157,6 +164,8 @@
mFragment = spy(new TestFragment(mContext));
mFragment.initFeatureProvider();
+ mBatteryMeterView = new BatteryMeterView(mRealContext);
+ mBatteryMeterView.mDrawable = new BatteryMeterView.BatteryMeterDrawable(mRealContext, 0);
when(mFragment.getActivity()).thenReturn(mSettingsActivity);
when(mAdditionalBatteryInfoMenu.getItemId())
@@ -204,7 +213,7 @@
mFragment.mScreenUsagePref = mScreenUsagePref;
mFragment.mLastFullChargePref = mLastFullChargePref;
- mBatteryInfo.mBatteryLevel = BATTERY_LEVEL;
+ mBatteryInfo.batteryLevel = BATTERY_LEVEL;
}
@Test
@@ -412,6 +421,18 @@
}
@Test
+ public void testUpdatePreference_updateBatteryInfo() {
+ mBatteryInfo.remainingLabel = TIME_LEFT;
+ mBatteryInfo.batteryLevel = BATTERY_LEVEL;
+ mBatteryInfo.discharging = true;
+
+ mFragment.updateHeaderPreference(mBatteryInfo);
+
+ assertThat(mBatteryMeterView.mDrawable.getBatteryLevel()).isEqualTo(BATTERY_LEVEL);
+ assertThat(mBatteryMeterView.mDrawable.getCharging()).isEqualTo(false);
+ }
+
+ @Test
public void testUpdatePreference_noRemainingTime_showStatusLabel() {
mBatteryInfo.remainingLabel = null;
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
index e87e9c5..724909d 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java
@@ -5,9 +5,12 @@
import android.content.res.Resources.NotFoundException;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
+import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.ArrayRes;
+import android.support.annotation.ColorRes;
+import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.TypedValue;
@@ -53,6 +56,14 @@
}
@Implementation
+ public int getColor(@ColorRes int id, @Nullable Theme theme) throws NotFoundException {
+ if (id == R.color.battery_icon_color_error) {
+ return Color.WHITE;
+ }
+ return directlyOn(realResources, Resources.class).getColor(id, theme);
+ }
+
+ @Implementation
public Drawable loadDrawable(TypedValue value, int id, Theme theme)
throws NotFoundException {
// The drawable item in switchbar_background.xml refers to a very recent color attribute