blob: d57e88cce351e0ab287d66a607ea8f9cd56d5ccb [file] [log] [blame]
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -04001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040016package com.android.systemui;
17
Evan Lairdbcf631d2017-03-10 10:56:45 -050018import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
19
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040020import android.content.Context;
Jason Monkaa573e92017-01-27 17:00:29 -050021import android.content.res.Resources;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040022import android.content.res.TypedArray;
Jason Monkaa573e92017-01-27 17:00:29 -050023import android.graphics.Rect;
Jason Monk3e189872016-01-12 09:10:34 -050024import android.util.ArraySet;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040025import android.util.AttributeSet;
Jason Monkaa573e92017-01-27 17:00:29 -050026import android.util.TypedValue;
Dan Sandler055bb612017-02-08 16:21:49 -080027import android.database.ContentObserver;
28import android.net.Uri;
29import android.os.Handler;
30import android.provider.Settings;
Dan Sandler055bb612017-02-08 16:21:49 -080031import android.view.Gravity;
32import android.view.LayoutInflater;
Jason Monk3e189872016-01-12 09:10:34 -050033import android.view.View;
Dan Sandler055bb612017-02-08 16:21:49 -080034import android.view.ViewGroup;
Jason Monkabe19742015-09-29 09:47:06 -040035import android.widget.ImageView;
Jason Monkaa573e92017-01-27 17:00:29 -050036import android.widget.LinearLayout;
Winsonc0d70582016-01-29 10:24:39 -080037
Dan Sandler055bb612017-02-08 16:21:49 -080038import android.widget.TextView;
39import com.android.settingslib.graph.BatteryMeterDrawableBase;
Jason Monk3e189872016-01-12 09:10:34 -050040import com.android.systemui.statusbar.phone.StatusBarIconController;
Jorim Jaggi708f7722014-08-20 17:30:38 +020041import com.android.systemui.statusbar.policy.BatteryController;
Jason Monkaa573e92017-01-27 17:00:29 -050042import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
43import com.android.systemui.statusbar.policy.ConfigurationController;
44import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
45import com.android.systemui.statusbar.policy.DarkIconDispatcher;
46import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
Jason Monk3e189872016-01-12 09:10:34 -050047import com.android.systemui.tuner.TunerService;
Jason Monkaa573e92017-01-27 17:00:29 -050048import com.android.systemui.tuner.TunerService.Tunable;
Jorim Jaggi708f7722014-08-20 17:30:38 +020049
Dan Sandler055bb612017-02-08 16:21:49 -080050import java.text.NumberFormat;
51
52public class BatteryMeterView extends LinearLayout implements
Jason Monkaa573e92017-01-27 17:00:29 -050053 BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040054
Dan Sandler055bb612017-02-08 16:21:49 -080055 private final BatteryMeterDrawableBase mDrawable;
Jason Monk3e189872016-01-12 09:10:34 -050056 private final String mSlotBattery;
Dan Sandler055bb612017-02-08 16:21:49 -080057 private final ImageView mBatteryIconView;
58 private TextView mBatteryPercentView;
59
Jorim Jaggi708f7722014-08-20 17:30:38 +020060 private BatteryController mBatteryController;
Dan Sandler055bb612017-02-08 16:21:49 -080061 private SettingObserver mSettingObserver;
62 private int mTextColor;
63 private int mLevel;
Jason Monkf13413e2017-02-15 15:49:32 -050064 private boolean mForceShowPercent;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040065
66 public BatteryMeterView(Context context) {
67 this(context, null, 0);
68 }
69
70 public BatteryMeterView(Context context, AttributeSet attrs) {
71 this(context, attrs, 0);
72 }
73
74 public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
75 super(context, attrs, defStyle);
76
Dan Sandler055bb612017-02-08 16:21:49 -080077 setOrientation(LinearLayout.HORIZONTAL);
78 setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
79
John Spurlock29786fc2014-02-04 17:55:47 -050080 TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView,
81 defStyle, 0);
82 final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
Alan Viverette4a357cd2015-03-18 18:37:18 -070083 context.getColor(R.color.batterymeter_frame_color));
Dan Sandler055bb612017-02-08 16:21:49 -080084 mDrawable = new BatteryMeterDrawableBase(context, frameColor);
John Spurlock29786fc2014-02-04 17:55:47 -050085 atts.recycle();
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040086
Dan Sandler055bb612017-02-08 16:21:49 -080087 mSettingObserver = new SettingObserver(new Handler(context.getMainLooper()));
88
Jason Monk3e189872016-01-12 09:10:34 -050089 mSlotBattery = context.getString(
90 com.android.internal.R.string.status_bar_battery);
Dan Sandler055bb612017-02-08 16:21:49 -080091 mBatteryIconView = new ImageView(context);
92 mBatteryIconView.setImageDrawable(mDrawable);
93 final MarginLayoutParams mlp = new MarginLayoutParams(
94 getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_width),
95 getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_height));
96 mlp.setMargins(0, 0, 0,
97 getResources().getDimensionPixelOffset(R.dimen.battery_margin_bottom));
98 addView(mBatteryIconView, mlp);
99
100 updateShowPercent();
Jason Monkd866b8a2017-03-29 15:30:44 -0400101 // Init to not dark at all.
102 onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
Dan Sandler055bb612017-02-08 16:21:49 -0800103 }
104
Dan Sandlerdf14c202017-02-21 14:51:11 -0500105 public void setForceShowPercent(boolean show) {
106 mForceShowPercent = show;
Jason Monkf13413e2017-02-15 15:49:32 -0500107 updateShowPercent();
108 }
109
Dan Sandler055bb612017-02-08 16:21:49 -0800110 // StatusBarIconController reaches in here and adjusts the layout parameters of the icon
111 public ImageView getBatteryIconView() {
112 return mBatteryIconView;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400113 }
John Spurlock3c875662013-08-31 15:07:25 -0400114
Jorim Jaggi0d266892014-07-28 14:49:13 +0200115 @Override
116 public boolean hasOverlappingRendering() {
117 return false;
118 }
119
Jason Monkabe19742015-09-29 09:47:06 -0400120 @Override
Jason Monk3e189872016-01-12 09:10:34 -0500121 public void onTuningChanged(String key, String newValue) {
122 if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
123 ArraySet<String> icons = StatusBarIconController.getIconBlacklist(newValue);
124 setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
125 }
126 }
127
128 @Override
Jason Monkabe19742015-09-29 09:47:06 -0400129 public void onAttachedToWindow() {
130 super.onAttachedToWindow();
Jason Monk9c7844c2017-01-18 15:21:53 -0500131 mBatteryController = Dependency.get(BatteryController.class);
Jason Monk9c7844c2017-01-18 15:21:53 -0500132 mBatteryController.addCallback(this);
Dan Sandler055bb612017-02-08 16:21:49 -0800133 getContext().getContentResolver().registerContentObserver(
Evan Lairdbcf631d2017-03-10 10:56:45 -0500134 Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mSettingObserver);
Dan Sandler055bb612017-02-08 16:21:49 -0800135 updateShowPercent();
Jason Monkde850bb2017-02-01 19:26:30 -0500136 Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Jason Monkaa573e92017-01-27 17:00:29 -0500137 Dependency.get(ConfigurationController.class).addCallback(this);
Jason Monkabe19742015-09-29 09:47:06 -0400138 }
John Spurlock3c875662013-08-31 15:07:25 -0400139
140 @Override
Jason Monkabe19742015-09-29 09:47:06 -0400141 public void onDetachedFromWindow() {
142 super.onDetachedFromWindow();
Jason Monk88529052016-11-04 13:29:58 -0400143 mBatteryController.removeCallback(this);
Dan Sandler055bb612017-02-08 16:21:49 -0800144 getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
Jason Monkde850bb2017-02-01 19:26:30 -0500145 Dependency.get(TunerService.class).removeTunable(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500146 Dependency.get(ConfigurationController.class).removeCallback(this);
John Spurlock3c875662013-08-31 15:07:25 -0400147 }
John Spurlockf40d08f2015-05-29 10:48:22 -0400148
Jason Monkabe19742015-09-29 09:47:06 -0400149 @Override
150 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
Dan Sandler055bb612017-02-08 16:21:49 -0800151 mDrawable.setBatteryLevel(level);
152 mDrawable.setPluggedIn(pluggedIn);
153 mLevel = level;
154 updatePercentText();
Jason Monkabe19742015-09-29 09:47:06 -0400155 setContentDescription(
Adrian Roos70dcf832016-04-20 15:51:42 -0700156 getContext().getString(charging ? R.string.accessibility_battery_level_charging
157 : R.string.accessibility_battery_level, level));
John Spurlockf40d08f2015-05-29 10:48:22 -0400158 }
159
Jason Monkabe19742015-09-29 09:47:06 -0400160 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500161 public void onPowerSaveChanged(boolean isPowerSave) {
Dan Sandler055bb612017-02-08 16:21:49 -0800162 mDrawable.setPowerSave(isPowerSave);
163 }
John Spurlockf40d08f2015-05-29 10:48:22 -0400164
Dan Sandler055bb612017-02-08 16:21:49 -0800165 private TextView loadPercentView() {
166 return (TextView) LayoutInflater.from(getContext())
167 .inflate(R.layout.battery_percentage_view, null);
168 }
169
170 private void updatePercentText() {
171 if (mBatteryPercentView != null) {
172 mBatteryPercentView.setText(
173 NumberFormat.getPercentInstance().format(mLevel/100f));
174 }
175 }
176
177 private void updateShowPercent() {
178 final boolean showing = mBatteryPercentView != null;
179 if (0 != Settings.System.getInt(getContext().getContentResolver(),
Evan Lairdbcf631d2017-03-10 10:56:45 -0500180 SHOW_BATTERY_PERCENT, 0) || mForceShowPercent) {
Dan Sandler055bb612017-02-08 16:21:49 -0800181 if (!showing) {
182 mBatteryPercentView = loadPercentView();
183 if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
184 updatePercentText();
185 addView(mBatteryPercentView,
Evan Laird09ebefd2017-03-24 10:55:29 -0400186 0,
Dan Sandler055bb612017-02-08 16:21:49 -0800187 new ViewGroup.LayoutParams(
188 LayoutParams.WRAP_CONTENT,
189 LayoutParams.MATCH_PARENT));
190 }
191 } else {
192 if (showing) {
193 removeView(mBatteryPercentView);
194 mBatteryPercentView = null;
195 }
196 }
John Spurlockf40d08f2015-05-29 10:48:22 -0400197 }
198
Jason Monkaa573e92017-01-27 17:00:29 -0500199 @Override
200 public void onDensityOrFontScaleChanged() {
201 scaleBatteryMeterViews();
202 }
203
204 /**
205 * Looks up the scale factor for status bar icons and scales the battery view by that amount.
206 */
207 private void scaleBatteryMeterViews() {
208 Resources res = getContext().getResources();
209 TypedValue typedValue = new TypedValue();
210
211 res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
212 float iconScaleFactor = typedValue.getFloat();
213
214 int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
215 int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
216 int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
217
218 LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
219 (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
Dan Sandler055bb612017-02-08 16:21:49 -0800220 scaledLayoutParams.setMargins(0, 0, 0, marginBottom);
Jason Monkaa573e92017-01-27 17:00:29 -0500221
Dan Sandler055bb612017-02-08 16:21:49 -0800222 mBatteryIconView.setLayoutParams(scaledLayoutParams);
Jason Monkaa573e92017-01-27 17:00:29 -0500223 }
224
225 @Override
226 public void onDarkChanged(Rect area, float darkIntensity, int tint) {
227 mDrawable.setDarkIntensity(DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0);
Dan Sandler055bb612017-02-08 16:21:49 -0800228 setTextColor(DarkIconDispatcher.getTint(area, this, tint));
229 }
230
231 public void setTextColor(int color) {
232 mTextColor = color;
233 if (mBatteryPercentView != null) {
234 mBatteryPercentView.setTextColor(color);
235 }
Jason Monkabe19742015-09-29 09:47:06 -0400236 }
Jason Monk32508852017-01-18 09:17:13 -0500237
238 public void setRawColors(int fgColor, int bgColor) {
239 mDrawable.setColors(fgColor, bgColor);
240 }
Dan Sandler055bb612017-02-08 16:21:49 -0800241
242 private final class SettingObserver extends ContentObserver {
243 public SettingObserver(Handler handler) {
244 super(handler);
245 }
246
247 @Override
248 public void onChange(boolean selfChange, Uri uri) {
249 super.onChange(selfChange, uri);
250 updateShowPercent();
251 }
252 }
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400253}