diff --git a/res/color/battery_icon_color_error.xml b/res/color/battery_icon_color_error.xml new file mode 100644 index 00000000000..3a71aaef891 --- /dev/null +++ b/res/color/battery_icon_color_error.xml @@ -0,0 +1,19 @@ + + + + + \ 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 7b89fb1f4de..8588f7756a1 100644 --- a/src/com/android/settings/fuelgauge/BatteryHistoryChart.java +++ b/src/com/android/settings/fuelgauge/BatteryHistoryChart.java @@ -511,7 +511,7 @@ public class BatteryHistoryChart extends View { elapsedRealtimeUs); mDrainString = ""; mChargeDurationString = ""; - setContentDescription(mInfo.mChargeLabelString); + setContentDescription(mInfo.chargeLabelString); int pos = 0; int lastInteresting = 0; @@ -589,7 +589,7 @@ public class BatteryHistoryChart extends View { 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 @@ public class BatteryHistoryChart extends View { } } } - + i++; } mStats.finishIteratingHistoryLocked(); @@ -983,9 +983,9 @@ public class BatteryHistoryChart extends View { 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 @@ public class BatteryHistoryChart extends View { 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 @@ public class BatteryHistoryChart extends View { 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 dcbf4724ccd..c450b900cb2 100644 --- a/src/com/android/settings/fuelgauge/BatteryMeterView.java +++ b/src/com/android/settings/fuelgauge/BatteryMeterView.java @@ -18,17 +18,25 @@ package com.android.settings.fuelgauge; 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 @@ public class BatteryMeterView extends ImageView { 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 class BatteryMeterView extends ImageView { 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 b23f9e34177..2657d9ee32c 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java +++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java @@ -568,14 +568,15 @@ public class PowerUsageSummary extends PowerUsageBase { .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 @@ public class PowerUsageSummary extends PowerUsageBase { 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 85b893ae493..cb37a6e23a6 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.mockito.MockitoAnnotations; 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 @@ import static org.mockito.Mockito.verify; }) 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 @@ public class BatteryMeterViewTest { 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 7f59b18671b..da04ab2c774 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.TestConfig; 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 @@ import static org.mockito.Mockito.when; */ // 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 @@ public class PowerUsageSummaryTest { @Mock private LayoutPreference mBatteryLayoutPref; @Mock - private BatteryMeterView mBatteryMeterView; - @Mock private TextView mBatteryPercentText; @Mock private TextView mSummary1; @@ -145,6 +151,7 @@ public class PowerUsageSummaryTest { private Context mRealContext; private TestFragment mFragment; private FakeFeatureFactory mFeatureFactory; + private BatteryMeterView mBatteryMeterView; @Before public void setUp() { @@ -157,6 +164,8 @@ public class PowerUsageSummaryTest { 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 @@ public class PowerUsageSummaryTest { mFragment.mScreenUsagePref = mScreenUsagePref; mFragment.mLastFullChargePref = mLastFullChargePref; - mBatteryInfo.mBatteryLevel = BATTERY_LEVEL; + mBatteryInfo.batteryLevel = BATTERY_LEVEL; } @Test @@ -411,6 +420,18 @@ public class PowerUsageSummaryTest { verify(mSummary1).setText(mBatteryInfo.remainingLabel); } + @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 e87e9c53025..724909df7c0 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; 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; @@ -52,6 +55,14 @@ public class SettingsShadowResources extends ShadowResources { return directlyOn(realResources, Resources.class).getDimensionPixelSize(id); } + @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 {