From 055bb6142626786302c4e0fdbcbc4f49fb0a2d1a Mon Sep 17 00:00:00 2001 From: Dan Sandler Date: Wed, 8 Feb 2017 16:21:49 -0800 Subject: [PATCH] Percentage text now sits alongside the battery icon. The old embedded percentage (introduced in change I6a3e7409) is hard to read at status bar size, so we now draw it in a separate TextView to the left (start) of the battery gauge. (The embedded code remains so that it can be used by other places where the battery is drawn larger.) The old system setting "status_bar_show_battery_percent" is still used to control whether this percentage is shown, but note that it now applies only to BatteryMeterView (i.e., the status bar) and not other usages of BatteryMeterDrawable. Bug: 32539932 Test: (manual) adb shell settings put system status_bar_show_battery_percent 1 Change-Id: Id298dba544f594b11269539284a2e8042fd4780b --- .../res/layout/battery_percentage_view.xml | 29 +++++ packages/SystemUI/res/layout/system_icons.xml | 7 +- .../systemui/BatteryMeterDrawable.java | 87 ------------- .../android/systemui/BatteryMeterView.java | 118 ++++++++++++++++-- .../systemui/qs/tiles/BatteryTile.java | 13 +- .../systemui/tuner/BatteryPreference.java | 2 +- .../android/systemui/tuner/TunerService.java | 2 +- .../systemui/BatteryMeterDrawableTest.java | 22 ++-- 8 files changed, 165 insertions(+), 115 deletions(-) create mode 100644 packages/SystemUI/res/layout/battery_percentage_view.xml delete mode 100644 packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java diff --git a/packages/SystemUI/res/layout/battery_percentage_view.xml b/packages/SystemUI/res/layout/battery_percentage_view.xml new file mode 100644 index 0000000000000..d6abc47c5af38 --- /dev/null +++ b/packages/SystemUI/res/layout/battery_percentage_view.xml @@ -0,0 +1,29 @@ + + + + + diff --git a/packages/SystemUI/res/layout/system_icons.xml b/packages/SystemUI/res/layout/system_icons.xml index 3a339920618df..bfa92ad89a1e8 100644 --- a/packages/SystemUI/res/layout/system_icons.xml +++ b/packages/SystemUI/res/layout/system_icons.xml @@ -31,9 +31,8 @@ android:layout_height="wrap_content" android:layout_marginStart="@dimen/signal_cluster_margin_start"/> - + android:layout_height="match_parent" + android:layout_width="wrap_content" + /> \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java deleted file mode 100644 index 9068079fd6cf5..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterDrawable.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -package com.android.systemui; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.provider.Settings; -import com.android.settingslib.graph.BatteryMeterDrawableBase; -import com.android.systemui.statusbar.policy.BatteryController; - -public class BatteryMeterDrawable extends BatteryMeterDrawableBase implements - BatteryController.BatteryStateChangeCallback { - - public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent"; - - private BatteryController mBatteryController; - private SettingObserver mSettingObserver; - - public BatteryMeterDrawable(Context context, int frameColor) { - super(context, frameColor); - - mSettingObserver = new SettingObserver(new Handler(mContext.getMainLooper())); - } - - @Override - public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { - setBatteryLevel(level); - setPluggedIn(pluggedIn); - } - - @Override - public void onPowerSaveChanged(boolean isPowerSave) { - setPowerSave(isPowerSave); - } - - public void startListening() { - mContext.getContentResolver().registerContentObserver( - Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); - updateShowPercent(); - mBatteryController.addCallback(this); - } - - public void stopListening() { - mContext.getContentResolver().unregisterContentObserver(mSettingObserver); - mBatteryController.removeCallback(this); - } - - protected void updateShowPercent() { - setShowPercent(0 != Settings.System.getInt(mContext.getContentResolver(), - SHOW_PERCENT_SETTING, 0)); - } - - public void setBatteryController(BatteryController batteryController) { - mBatteryController = batteryController; - setPowerSave(mBatteryController.isPowerSave()); - } - - private final class SettingObserver extends ContentObserver { - public SettingObserver(Handler handler) { - super(handler); - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); - updateShowPercent(); - postInvalidate(); - } - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java index 69e38745f23b9..f821308685549 100644 --- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java +++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java @@ -23,10 +23,22 @@ import android.graphics.Rect; import android.util.ArraySet; import android.util.AttributeSet; import android.util.TypedValue; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.provider.Settings; +import android.util.ArraySet; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; import android.view.View; +import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.LinearLayout; +import android.widget.TextView; +import com.android.settingslib.graph.BatteryMeterDrawableBase; import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; @@ -37,12 +49,22 @@ import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver; import com.android.systemui.tuner.TunerService; import com.android.systemui.tuner.TunerService.Tunable; -public class BatteryMeterView extends ImageView implements +import java.text.NumberFormat; + +public class BatteryMeterView extends LinearLayout implements BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener { - private final BatteryMeterDrawable mDrawable; + public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent"; + + private final BatteryMeterDrawableBase mDrawable; private final String mSlotBattery; + private final ImageView mBatteryIconView; + private TextView mBatteryPercentView; + private BatteryController mBatteryController; + private SettingObserver mSettingObserver; + private int mTextColor; + private int mLevel; public BatteryMeterView(Context context) { this(context, null, 0); @@ -55,16 +77,35 @@ public class BatteryMeterView extends ImageView implements public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.CENTER_VERTICAL | Gravity.START); + TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView, defStyle, 0); final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor, context.getColor(R.color.batterymeter_frame_color)); - mDrawable = new BatteryMeterDrawable(context, frameColor); + mDrawable = new BatteryMeterDrawableBase(context, frameColor); atts.recycle(); + mSettingObserver = new SettingObserver(new Handler(context.getMainLooper())); + mSlotBattery = context.getString( com.android.internal.R.string.status_bar_battery); - setImageDrawable(mDrawable); + mBatteryIconView = new ImageView(context); + mBatteryIconView.setImageDrawable(mDrawable); + final MarginLayoutParams mlp = new MarginLayoutParams( + getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_width), + getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_height)); + mlp.setMargins(0, 0, 0, + getResources().getDimensionPixelOffset(R.dimen.battery_margin_bottom)); + addView(mBatteryIconView, mlp); + + updateShowPercent(); + } + + // StatusBarIconController reaches in here and adjusts the layout parameters of the icon + public ImageView getBatteryIconView() { + return mBatteryIconView; } @Override @@ -84,9 +125,10 @@ public class BatteryMeterView extends ImageView implements public void onAttachedToWindow() { super.onAttachedToWindow(); mBatteryController = Dependency.get(BatteryController.class); - mDrawable.setBatteryController(mBatteryController); mBatteryController.addCallback(this); - mDrawable.startListening(); + getContext().getContentResolver().registerContentObserver( + Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver); + updateShowPercent(); Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST); Dependency.get(ConfigurationController.class).addCallback(this); } @@ -95,13 +137,17 @@ public class BatteryMeterView extends ImageView implements public void onDetachedFromWindow() { super.onDetachedFromWindow(); mBatteryController.removeCallback(this); - mDrawable.stopListening(); + getContext().getContentResolver().unregisterContentObserver(mSettingObserver); Dependency.get(TunerService.class).removeTunable(this); Dependency.get(ConfigurationController.class).removeCallback(this); } @Override public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) { + mDrawable.setBatteryLevel(level); + mDrawable.setPluggedIn(pluggedIn); + mLevel = level; + updatePercentText(); setContentDescription( getContext().getString(charging ? R.string.accessibility_battery_level_charging : R.string.accessibility_battery_level, level)); @@ -109,7 +155,41 @@ public class BatteryMeterView extends ImageView implements @Override public void onPowerSaveChanged(boolean isPowerSave) { + mDrawable.setPowerSave(isPowerSave); + } + private TextView loadPercentView() { + return (TextView) LayoutInflater.from(getContext()) + .inflate(R.layout.battery_percentage_view, null); + } + + private void updatePercentText() { + if (mBatteryPercentView != null) { + mBatteryPercentView.setText( + NumberFormat.getPercentInstance().format(mLevel/100f)); + } + } + + private void updateShowPercent() { + final boolean showing = mBatteryPercentView != null; + if (0 != Settings.System.getInt(getContext().getContentResolver(), + BatteryMeterView.SHOW_PERCENT_SETTING, 0)) { + if (!showing) { + mBatteryPercentView = loadPercentView(); + if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor); + updatePercentText(); + addView(mBatteryPercentView, + 0, + new ViewGroup.LayoutParams( + LayoutParams.WRAP_CONTENT, + LayoutParams.MATCH_PARENT)); + } + } else { + if (showing) { + removeView(mBatteryPercentView); + mBatteryPercentView = null; + } + } } @Override @@ -133,17 +213,37 @@ public class BatteryMeterView extends ImageView implements LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams( (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor)); - scaledLayoutParams.setMarginsRelative(0, 0, 0, marginBottom); + scaledLayoutParams.setMargins(0, 0, 0, marginBottom); - setLayoutParams(scaledLayoutParams); + mBatteryIconView.setLayoutParams(scaledLayoutParams); } @Override public void onDarkChanged(Rect area, float darkIntensity, int tint) { mDrawable.setDarkIntensity(DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0); + setTextColor(DarkIconDispatcher.getTint(area, this, tint)); + } + + public void setTextColor(int color) { + mTextColor = color; + if (mBatteryPercentView != null) { + mBatteryPercentView.setTextColor(color); + } } public void setRawColors(int fgColor, int bgColor) { mDrawable.setColors(fgColor, bgColor); } + + private final class SettingObserver extends ContentObserver { + public SettingObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + updateShowPercent(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java index fff830560c149..8227f8f63cebb 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatteryTile.java @@ -35,8 +35,8 @@ import android.widget.ImageView; import android.widget.TextView; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.settingslib.BatteryInfo; +import com.android.settingslib.graph.BatteryMeterDrawableBase; import com.android.settingslib.graph.UsageView; -import com.android.systemui.BatteryMeterDrawable; import com.android.systemui.Dependency; import com.android.systemui.R; import com.android.systemui.plugins.qs.QS.DetailAdapter; @@ -155,8 +155,10 @@ public class BatteryTile extends QSTile implements BatteryControll private final class BatteryDetail implements DetailAdapter, OnClickListener, OnAttachStateChangeListener { - private final BatteryMeterDrawable mDrawable = new BatteryMeterDrawable(mHost.getContext(), - mHost.getContext().getColor(R.color.batterymeter_frame_color)); + private final BatteryMeterDrawableBase mDrawable + = new BatteryMeterDrawableBase( + mHost.getContext(), + mHost.getContext().getColor(R.color.batterymeter_frame_color)); private View mCurrentView; @Override @@ -195,8 +197,9 @@ public class BatteryTile extends QSTile implements BatteryControll if (mCurrentView == null) { return; } - mDrawable.onBatteryLevelChanged(100, false, false); - mDrawable.onPowerSaveChanged(true); + mDrawable.setBatteryLevel(100); + mDrawable.setPluggedIn(false); + mDrawable.setPowerSave(true); mDrawable.setShowPercent(false); ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable); Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle); diff --git a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java index 3058c0a1e739a..1df12acde4a50 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/BatteryPreference.java @@ -25,7 +25,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.systemui.Dependency; import com.android.systemui.statusbar.phone.StatusBarIconController; -import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING; +import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING; public class BatteryPreference extends DropDownPreference implements TunerService.Tunable { diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java index 85be4d79d64f7..6a92b2f91c5c3 100644 --- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java +++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java @@ -38,7 +38,7 @@ import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; -import static com.android.systemui.BatteryMeterDrawable.SHOW_PERCENT_SETTING; +import static com.android.systemui.BatteryMeterView.SHOW_PERCENT_SETTING; import com.android.systemui.DemoMode; import com.android.systemui.Dependency; import com.android.systemui.R; diff --git a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java index 09808d47a995a..6b47ada8fea7e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/BatteryMeterDrawableTest.java @@ -16,6 +16,7 @@ package com.android.systemui; +import com.android.settingslib.graph.BatteryMeterDrawableBase; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyFloat; @@ -41,17 +42,18 @@ import org.junit.runner.RunWith; public class BatteryMeterDrawableTest extends SysuiTestCase { private Resources mResources; - private BatteryMeterDrawable mBatteryMeter; + private BatteryMeterDrawableBase mBatteryMeter; @Before public void setUp() throws Exception { mResources = mContext.getResources(); - mBatteryMeter = new BatteryMeterDrawable(mContext, 0); + mBatteryMeter = new BatteryMeterDrawableBase(mContext, 0); } @Test public void testDrawImageButNoTextIfPluggedIn() { - mBatteryMeter.onBatteryLevelChanged(0, true, true); + mBatteryMeter.setBatteryLevel(0); + mBatteryMeter.setPluggedIn(true); final Canvas canvas = mock(Canvas.class); mBatteryMeter.draw(canvas); verify(canvas, atLeastOnce()).drawPath(any(), any()); @@ -60,7 +62,8 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { @Test public void testDrawTextIfNotPluggedIn() { - mBatteryMeter.onBatteryLevelChanged(0, false, false); + mBatteryMeter.setBatteryLevel(0); + mBatteryMeter.setPluggedIn(false); final Canvas canvas = mock(Canvas.class); mBatteryMeter.draw(canvas); verify(canvas, times(1)).drawText(anyString(), anyFloat(), anyFloat(), any()); @@ -68,8 +71,9 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { @Test public void testDrawNoTextIfPowerSaveEnabled() { - mBatteryMeter.onBatteryLevelChanged(0, false, false); - mBatteryMeter.onPowerSaveChanged(true); + mBatteryMeter.setBatteryLevel(0); + mBatteryMeter.setPluggedIn(false); + mBatteryMeter.setPowerSave(true); final Canvas canvas = mock(Canvas.class); mBatteryMeter.draw(canvas); verify(canvas, never()).drawText(anyString(), anyFloat(), anyFloat(), any()); @@ -79,7 +83,8 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { public void testDrawTextWarningAtCriticalLevel() { int criticalLevel = mResources.getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); - mBatteryMeter.onBatteryLevelChanged(criticalLevel, false, false); + mBatteryMeter.setBatteryLevel(criticalLevel); + mBatteryMeter.setPluggedIn(false); final Canvas canvas = mock(Canvas.class); mBatteryMeter.draw(canvas); String warningString = mResources.getString(R.string.battery_meter_very_low_overlay_symbol); @@ -90,7 +95,8 @@ public class BatteryMeterDrawableTest extends SysuiTestCase { public void testDrawTextNoWarningAboveCriticalLevel() { int criticalLevel = mResources.getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); - mBatteryMeter.onBatteryLevelChanged(criticalLevel + 1, false, false); + mBatteryMeter.setBatteryLevel(criticalLevel + 1); + mBatteryMeter.setPluggedIn(false); final Canvas canvas = mock(Canvas.class); mBatteryMeter.draw(canvas); String warningString = mResources.getString(R.string.battery_meter_very_low_overlay_symbol);