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
This commit is contained in:
19
res/color/battery_icon_color_error.xml
Normal file
19
res/color/battery_icon_color_error.xml
Normal file
@@ -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>
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user