blob: f8213086855490545d4b82e97a72aedf81db362c [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
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040018import android.content.Context;
Jason Monkaa573e92017-01-27 17:00:29 -050019import android.content.res.Configuration;
20import android.content.res.Resources;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040021import android.content.res.TypedArray;
Jason Monkaa573e92017-01-27 17:00:29 -050022import android.graphics.Rect;
Jason Monk3e189872016-01-12 09:10:34 -050023import android.util.ArraySet;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040024import android.util.AttributeSet;
Jason Monkaa573e92017-01-27 17:00:29 -050025import android.util.TypedValue;
Dan Sandler055bb612017-02-08 16:21:49 -080026import android.database.ContentObserver;
27import android.net.Uri;
28import android.os.Handler;
29import android.provider.Settings;
30import android.util.ArraySet;
31import android.util.AttributeSet;
32import android.view.Gravity;
33import android.view.LayoutInflater;
Jason Monk3e189872016-01-12 09:10:34 -050034import android.view.View;
Dan Sandler055bb612017-02-08 16:21:49 -080035import android.view.ViewGroup;
Jason Monkabe19742015-09-29 09:47:06 -040036import android.widget.ImageView;
Jason Monkaa573e92017-01-27 17:00:29 -050037import android.widget.LinearLayout;
Winsonc0d70582016-01-29 10:24:39 -080038
Dan Sandler055bb612017-02-08 16:21:49 -080039import android.widget.LinearLayout;
40import android.widget.TextView;
41import com.android.settingslib.graph.BatteryMeterDrawableBase;
Jason Monk3e189872016-01-12 09:10:34 -050042import com.android.systemui.statusbar.phone.StatusBarIconController;
Jorim Jaggi708f7722014-08-20 17:30:38 +020043import com.android.systemui.statusbar.policy.BatteryController;
Jason Monkaa573e92017-01-27 17:00:29 -050044import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback;
45import com.android.systemui.statusbar.policy.ConfigurationController;
46import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
47import com.android.systemui.statusbar.policy.DarkIconDispatcher;
48import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
Jason Monk3e189872016-01-12 09:10:34 -050049import com.android.systemui.tuner.TunerService;
Jason Monkaa573e92017-01-27 17:00:29 -050050import com.android.systemui.tuner.TunerService.Tunable;
Jorim Jaggi708f7722014-08-20 17:30:38 +020051
Dan Sandler055bb612017-02-08 16:21:49 -080052import java.text.NumberFormat;
53
54public class BatteryMeterView extends LinearLayout implements
Jason Monkaa573e92017-01-27 17:00:29 -050055 BatteryStateChangeCallback, Tunable, DarkReceiver, ConfigurationListener {
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040056
Dan Sandler055bb612017-02-08 16:21:49 -080057 public static final String SHOW_PERCENT_SETTING = "status_bar_show_battery_percent";
58
59 private final BatteryMeterDrawableBase mDrawable;
Jason Monk3e189872016-01-12 09:10:34 -050060 private final String mSlotBattery;
Dan Sandler055bb612017-02-08 16:21:49 -080061 private final ImageView mBatteryIconView;
62 private TextView mBatteryPercentView;
63
Jorim Jaggi708f7722014-08-20 17:30:38 +020064 private BatteryController mBatteryController;
Dan Sandler055bb612017-02-08 16:21:49 -080065 private SettingObserver mSettingObserver;
66 private int mTextColor;
67 private int mLevel;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040068
69 public BatteryMeterView(Context context) {
70 this(context, null, 0);
71 }
72
73 public BatteryMeterView(Context context, AttributeSet attrs) {
74 this(context, attrs, 0);
75 }
76
77 public BatteryMeterView(Context context, AttributeSet attrs, int defStyle) {
78 super(context, attrs, defStyle);
79
Dan Sandler055bb612017-02-08 16:21:49 -080080 setOrientation(LinearLayout.HORIZONTAL);
81 setGravity(Gravity.CENTER_VERTICAL | Gravity.START);
82
John Spurlock29786fc2014-02-04 17:55:47 -050083 TypedArray atts = context.obtainStyledAttributes(attrs, R.styleable.BatteryMeterView,
84 defStyle, 0);
85 final int frameColor = atts.getColor(R.styleable.BatteryMeterView_frameColor,
Alan Viverette4a357cd2015-03-18 18:37:18 -070086 context.getColor(R.color.batterymeter_frame_color));
Dan Sandler055bb612017-02-08 16:21:49 -080087 mDrawable = new BatteryMeterDrawableBase(context, frameColor);
John Spurlock29786fc2014-02-04 17:55:47 -050088 atts.recycle();
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -040089
Dan Sandler055bb612017-02-08 16:21:49 -080090 mSettingObserver = new SettingObserver(new Handler(context.getMainLooper()));
91
Jason Monk3e189872016-01-12 09:10:34 -050092 mSlotBattery = context.getString(
93 com.android.internal.R.string.status_bar_battery);
Dan Sandler055bb612017-02-08 16:21:49 -080094 mBatteryIconView = new ImageView(context);
95 mBatteryIconView.setImageDrawable(mDrawable);
96 final MarginLayoutParams mlp = new MarginLayoutParams(
97 getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_width),
98 getResources().getDimensionPixelSize(R.dimen.status_bar_battery_icon_height));
99 mlp.setMargins(0, 0, 0,
100 getResources().getDimensionPixelOffset(R.dimen.battery_margin_bottom));
101 addView(mBatteryIconView, mlp);
102
103 updateShowPercent();
104 }
105
106 // StatusBarIconController reaches in here and adjusts the layout parameters of the icon
107 public ImageView getBatteryIconView() {
108 return mBatteryIconView;
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400109 }
John Spurlock3c875662013-08-31 15:07:25 -0400110
Jorim Jaggi0d266892014-07-28 14:49:13 +0200111 @Override
112 public boolean hasOverlappingRendering() {
113 return false;
114 }
115
Jason Monkabe19742015-09-29 09:47:06 -0400116 @Override
Jason Monk3e189872016-01-12 09:10:34 -0500117 public void onTuningChanged(String key, String newValue) {
118 if (StatusBarIconController.ICON_BLACKLIST.equals(key)) {
119 ArraySet<String> icons = StatusBarIconController.getIconBlacklist(newValue);
120 setVisibility(icons.contains(mSlotBattery) ? View.GONE : View.VISIBLE);
121 }
122 }
123
124 @Override
Jason Monkabe19742015-09-29 09:47:06 -0400125 public void onAttachedToWindow() {
126 super.onAttachedToWindow();
Jason Monk9c7844c2017-01-18 15:21:53 -0500127 mBatteryController = Dependency.get(BatteryController.class);
Jason Monk9c7844c2017-01-18 15:21:53 -0500128 mBatteryController.addCallback(this);
Dan Sandler055bb612017-02-08 16:21:49 -0800129 getContext().getContentResolver().registerContentObserver(
130 Settings.System.getUriFor(SHOW_PERCENT_SETTING), false, mSettingObserver);
131 updateShowPercent();
Jason Monkde850bb2017-02-01 19:26:30 -0500132 Dependency.get(TunerService.class).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Jason Monkaa573e92017-01-27 17:00:29 -0500133 Dependency.get(ConfigurationController.class).addCallback(this);
Jason Monkabe19742015-09-29 09:47:06 -0400134 }
John Spurlock3c875662013-08-31 15:07:25 -0400135
136 @Override
Jason Monkabe19742015-09-29 09:47:06 -0400137 public void onDetachedFromWindow() {
138 super.onDetachedFromWindow();
Jason Monk88529052016-11-04 13:29:58 -0400139 mBatteryController.removeCallback(this);
Dan Sandler055bb612017-02-08 16:21:49 -0800140 getContext().getContentResolver().unregisterContentObserver(mSettingObserver);
Jason Monkde850bb2017-02-01 19:26:30 -0500141 Dependency.get(TunerService.class).removeTunable(this);
Jason Monkaa573e92017-01-27 17:00:29 -0500142 Dependency.get(ConfigurationController.class).removeCallback(this);
John Spurlock3c875662013-08-31 15:07:25 -0400143 }
John Spurlockf40d08f2015-05-29 10:48:22 -0400144
Jason Monkabe19742015-09-29 09:47:06 -0400145 @Override
146 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
Dan Sandler055bb612017-02-08 16:21:49 -0800147 mDrawable.setBatteryLevel(level);
148 mDrawable.setPluggedIn(pluggedIn);
149 mLevel = level;
150 updatePercentText();
Jason Monkabe19742015-09-29 09:47:06 -0400151 setContentDescription(
Adrian Roos70dcf832016-04-20 15:51:42 -0700152 getContext().getString(charging ? R.string.accessibility_battery_level_charging
153 : R.string.accessibility_battery_level, level));
John Spurlockf40d08f2015-05-29 10:48:22 -0400154 }
155
Jason Monkabe19742015-09-29 09:47:06 -0400156 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500157 public void onPowerSaveChanged(boolean isPowerSave) {
Dan Sandler055bb612017-02-08 16:21:49 -0800158 mDrawable.setPowerSave(isPowerSave);
159 }
John Spurlockf40d08f2015-05-29 10:48:22 -0400160
Dan Sandler055bb612017-02-08 16:21:49 -0800161 private TextView loadPercentView() {
162 return (TextView) LayoutInflater.from(getContext())
163 .inflate(R.layout.battery_percentage_view, null);
164 }
165
166 private void updatePercentText() {
167 if (mBatteryPercentView != null) {
168 mBatteryPercentView.setText(
169 NumberFormat.getPercentInstance().format(mLevel/100f));
170 }
171 }
172
173 private void updateShowPercent() {
174 final boolean showing = mBatteryPercentView != null;
175 if (0 != Settings.System.getInt(getContext().getContentResolver(),
176 BatteryMeterView.SHOW_PERCENT_SETTING, 0)) {
177 if (!showing) {
178 mBatteryPercentView = loadPercentView();
179 if (mTextColor != 0) mBatteryPercentView.setTextColor(mTextColor);
180 updatePercentText();
181 addView(mBatteryPercentView,
182 0,
183 new ViewGroup.LayoutParams(
184 LayoutParams.WRAP_CONTENT,
185 LayoutParams.MATCH_PARENT));
186 }
187 } else {
188 if (showing) {
189 removeView(mBatteryPercentView);
190 mBatteryPercentView = null;
191 }
192 }
John Spurlockf40d08f2015-05-29 10:48:22 -0400193 }
194
Jason Monkaa573e92017-01-27 17:00:29 -0500195 @Override
196 public void onDensityOrFontScaleChanged() {
197 scaleBatteryMeterViews();
198 }
199
200 /**
201 * Looks up the scale factor for status bar icons and scales the battery view by that amount.
202 */
203 private void scaleBatteryMeterViews() {
204 Resources res = getContext().getResources();
205 TypedValue typedValue = new TypedValue();
206
207 res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
208 float iconScaleFactor = typedValue.getFloat();
209
210 int batteryHeight = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_height);
211 int batteryWidth = res.getDimensionPixelSize(R.dimen.status_bar_battery_icon_width);
212 int marginBottom = res.getDimensionPixelSize(R.dimen.battery_margin_bottom);
213
214 LinearLayout.LayoutParams scaledLayoutParams = new LinearLayout.LayoutParams(
215 (int) (batteryWidth * iconScaleFactor), (int) (batteryHeight * iconScaleFactor));
Dan Sandler055bb612017-02-08 16:21:49 -0800216 scaledLayoutParams.setMargins(0, 0, 0, marginBottom);
Jason Monkaa573e92017-01-27 17:00:29 -0500217
Dan Sandler055bb612017-02-08 16:21:49 -0800218 mBatteryIconView.setLayoutParams(scaledLayoutParams);
Jason Monkaa573e92017-01-27 17:00:29 -0500219 }
220
221 @Override
222 public void onDarkChanged(Rect area, float darkIntensity, int tint) {
223 mDrawable.setDarkIntensity(DarkIconDispatcher.isInArea(area, this) ? darkIntensity : 0);
Dan Sandler055bb612017-02-08 16:21:49 -0800224 setTextColor(DarkIconDispatcher.getTint(area, this, tint));
225 }
226
227 public void setTextColor(int color) {
228 mTextColor = color;
229 if (mBatteryPercentView != null) {
230 mBatteryPercentView.setTextColor(color);
231 }
Jason Monkabe19742015-09-29 09:47:06 -0400232 }
Jason Monk32508852017-01-18 09:17:13 -0500233
234 public void setRawColors(int fgColor, int bgColor) {
235 mDrawable.setColors(fgColor, bgColor);
236 }
Dan Sandler055bb612017-02-08 16:21:49 -0800237
238 private final class SettingObserver extends ContentObserver {
239 public SettingObserver(Handler handler) {
240 super(handler);
241 }
242
243 @Override
244 public void onChange(boolean selfChange, Uri uri) {
245 super.onChange(selfChange, uri);
246 updateShowPercent();
247 }
248 }
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400249}