OSDN Git Service

Revamp battery Ui in low battery mode
authorjackqdyulei <jackqdyulei@google.com>
Tue, 4 Apr 2017 17:03:14 +0000 (10:03 -0700)
committerjackqdyulei <jackqdyulei@google.com>
Wed, 12 Apr 2017 19:47:52 +0000 (12:47 -0700)
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

res/color/battery_icon_color_error.xml [new file with mode: 0644]
src/com/android/settings/fuelgauge/BatteryHistoryChart.java
src/com/android/settings/fuelgauge/BatteryMeterView.java
src/com/android/settings/fuelgauge/PowerUsageSummary.java
tests/robotests/src/com/android/settings/fuelgauge/BatteryMeterViewTest.java
tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
tests/robotests/src/com/android/settings/testutils/shadow/SettingsShadowResources.java

diff --git a/res/color/battery_icon_color_error.xml b/res/color/battery_icon_color_error.xml
new file mode 100644 (file)
index 0000000..3a71aae
--- /dev/null
@@ -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
index 7b89fb1..8588f77 100644 (file)
@@ -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)
index dcbf472..c450b90 100644 (file)
@@ -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);
+        }
     }
 
 }
index b23f9e3..2657d9e 100644 (file)
@@ -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);
                     }
                 });
             }
index 85b893a..cb37a6e 100644 (file)
  */
 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.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_SetCorrectly() {
-        mBatteryMeterView.setBatteryInfo(BATTERY_LEVEL);
+    public void testSetBatteryInfo_levelNormal_setNormalColor() {
+        mBatteryMeterView.setBatteryLevel(BATTERY_LEVEL);
 
-        verify(mDrawable).setBatteryLevel(BATTERY_LEVEL);
+        verify(mDrawable).setBatteryColorFilter(mAccentColorFilter);
     }
 }
index 7f59b18..da04ab2 100644 (file)
@@ -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
@@ -412,6 +421,18 @@ public class PowerUsageSummaryTest {
     }
 
     @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;
 
index e87e9c5..724909d 100644 (file)
@@ -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;
 
@@ -53,6 +56,14 @@ public class SettingsShadowResources extends ShadowResources {
     }
 
     @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