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);