blob: 20327830091491674393c510191f95900e2f2cd2 [file] [log] [blame]
Jason Monkabe19742015-09-29 09:47:06 -04001/*
2 * Copyright (C) 2015 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 */
16package com.android.systemui.qs.tiles;
17
Jason Monkf12cfb72016-02-22 15:46:12 -050018import android.content.BroadcastReceiver;
Jason Monkabe19742015-09-29 09:47:06 -040019import android.content.Context;
20import android.content.Intent;
Jason Monkf12cfb72016-02-22 15:46:12 -050021import android.content.IntentFilter;
Jason Monkabe19742015-09-29 09:47:06 -040022import android.graphics.drawable.Drawable;
23import android.os.Handler;
Jason Monk8b2ce602016-03-31 11:30:41 -040024import android.os.Looper;
Jason Monk96ab6362016-02-11 11:33:09 -050025import android.text.SpannableStringBuilder;
26import android.text.Spanned;
27import android.text.style.RelativeSizeSpan;
Jason Monkc06fbb12016-01-08 14:12:18 -050028import android.view.LayoutInflater;
29import android.view.View;
Jason Monkf12cfb72016-02-22 15:46:12 -050030import android.view.View.OnAttachStateChangeListener;
31import android.view.View.OnClickListener;
Jason Monkc06fbb12016-01-08 14:12:18 -050032import android.view.ViewGroup;
33import android.widget.Checkable;
34import android.widget.ImageView;
35import android.widget.TextView;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050036import com.android.internal.logging.MetricsProto.MetricsEvent;
Jason Monkc06fbb12016-01-08 14:12:18 -050037import com.android.settingslib.BatteryInfo;
Jason Monk96ab6362016-02-11 11:33:09 -050038import com.android.settingslib.graph.UsageView;
Jason Monkabe19742015-09-29 09:47:06 -040039import com.android.systemui.BatteryMeterDrawable;
40import com.android.systemui.R;
41import com.android.systemui.qs.QSTile;
42import com.android.systemui.statusbar.policy.BatteryController;
43
44import java.text.NumberFormat;
45
46public class BatteryTile extends QSTile<QSTile.State> implements BatteryController.BatteryStateChangeCallback {
47
Jason Monkabe19742015-09-29 09:47:06 -040048 private final BatteryController mBatteryController;
Jason Monkc06fbb12016-01-08 14:12:18 -050049 private final BatteryDetail mBatteryDetail = new BatteryDetail();
Jason Monkabe19742015-09-29 09:47:06 -040050
51 private int mLevel;
Jason Monkc06fbb12016-01-08 14:12:18 -050052 private boolean mPowerSave;
53 private boolean mCharging;
Jason Monkf12cfb72016-02-22 15:46:12 -050054 private boolean mDetailShown;
Jason Monk8b2ce602016-03-31 11:30:41 -040055 private boolean mPluggedIn;
Jason Monkabe19742015-09-29 09:47:06 -040056
57 public BatteryTile(Host host) {
58 super(host);
59 mBatteryController = host.getBatteryController();
Jason Monkabe19742015-09-29 09:47:06 -040060 }
61
62 @Override
Jason Monk62b63a02016-02-02 15:15:31 -050063 public State newTileState() {
Jason Monkabe19742015-09-29 09:47:06 -040064 return new QSTile.State();
65 }
66
67 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -050068 public DetailAdapter getDetailAdapter() {
69 return mBatteryDetail;
70 }
71
72 @Override
Jason Monkabe19742015-09-29 09:47:06 -040073 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -050074 return MetricsEvent.QS_BATTERY_TILE;
Jason Monkabe19742015-09-29 09:47:06 -040075 }
76
77 @Override
78 public void setListening(boolean listening) {
79 if (listening) {
Jason Monkabe19742015-09-29 09:47:06 -040080 mBatteryController.addStateChangedCallback(this);
81 } else {
Jason Monkabe19742015-09-29 09:47:06 -040082 mBatteryController.removeStateChangedCallback(this);
83 }
84 }
85
86 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -050087 public void setDetailListening(boolean listening) {
88 super.setDetailListening(listening);
89 if (!listening) {
90 mBatteryDetail.mCurrentView = null;
91 }
92 }
93
94 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -050095 public Intent getLongClickIntent() {
96 return new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
97 }
98
99 @Override
Jason Monkabe19742015-09-29 09:47:06 -0400100 protected void handleClick() {
Jason Monkc06fbb12016-01-08 14:12:18 -0500101 showDetail(true);
Jason Monkabe19742015-09-29 09:47:06 -0400102 }
103
104 @Override
Jason Monk39c98e62016-03-16 09:18:35 -0400105 public CharSequence getTileLabel() {
106 return mContext.getString(R.string.battery);
107 }
108
109 @Override
Jason Monkabe19742015-09-29 09:47:06 -0400110 protected void handleUpdateState(State state, Object arg) {
111 int level = (arg != null) ? (Integer) arg : mLevel;
112 String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
113
Jason Monkabe19742015-09-29 09:47:06 -0400114 state.icon = new Icon() {
115 @Override
116 public Drawable getDrawable(Context context) {
Jason Monk8b2ce602016-03-31 11:30:41 -0400117 BatteryMeterDrawable drawable =
118 new BatteryMeterDrawable(context, new Handler(Looper.getMainLooper()),
119 context.getColor(R.color.batterymeter_frame_color));
120 drawable.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
121 drawable.onPowerSaveChanged(mPowerSave);
122 return drawable;
Jason Monkabe19742015-09-29 09:47:06 -0400123 }
Jason Monkb53b6c52016-02-24 17:25:49 -0500124
125 @Override
126 public int getPadding() {
127 return mHost.getContext().getResources().getDimensionPixelSize(
128 R.dimen.qs_battery_padding);
129 }
Jason Monkabe19742015-09-29 09:47:06 -0400130 };
131 state.label = percentage;
132 }
133
134 @Override
135 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
136 mLevel = level;
Jason Monk8b2ce602016-03-31 11:30:41 -0400137 mPluggedIn = pluggedIn;
Jason Monkc06fbb12016-01-08 14:12:18 -0500138 mCharging = charging;
Jason Monkabe19742015-09-29 09:47:06 -0400139 refreshState((Integer) level);
Jason Monkf12cfb72016-02-22 15:46:12 -0500140 if (mDetailShown) {
141 mBatteryDetail.postBindView();
Jason Monkc06fbb12016-01-08 14:12:18 -0500142 }
Jason Monkabe19742015-09-29 09:47:06 -0400143 }
144
145 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500146 public void onPowerSaveChanged(boolean isPowerSave) {
147 mPowerSave = isPowerSave;
Jason Monk8b2ce602016-03-31 11:30:41 -0400148 refreshState(null);
Jason Monkf12cfb72016-02-22 15:46:12 -0500149 if (mDetailShown) {
150 mBatteryDetail.postBindView();
Jason Monkc06fbb12016-01-08 14:12:18 -0500151 }
152 }
Jason Monkabe19742015-09-29 09:47:06 -0400153
Jason Monkf12cfb72016-02-22 15:46:12 -0500154 private final class BatteryDetail implements DetailAdapter, OnClickListener,
155 OnAttachStateChangeListener {
Jason Monkc06fbb12016-01-08 14:12:18 -0500156 private final BatteryMeterDrawable mDrawable = new BatteryMeterDrawable(mHost.getContext(),
157 new Handler(), mHost.getContext().getColor(R.color.batterymeter_frame_color));
158 private View mCurrentView;
159
160 @Override
161 public CharSequence getTitle() {
162 return mContext.getString(R.string.battery_panel_title, mLevel);
163 }
164
165 @Override
166 public Boolean getToggleState() {
167 return null;
168 }
169
170 @Override
171 public View createDetailView(Context context, View convertView, ViewGroup parent) {
172 if (convertView == null) {
173 convertView = LayoutInflater.from(mContext).inflate(R.layout.battery_detail, parent,
174 false);
175 }
176 mCurrentView = convertView;
Jason Monkf12cfb72016-02-22 15:46:12 -0500177 mCurrentView.addOnAttachStateChangeListener(this);
Jason Monkc06fbb12016-01-08 14:12:18 -0500178 bindView();
179 return convertView;
180 }
181
Jason Monkf12cfb72016-02-22 15:46:12 -0500182 private void postBindView() {
Jason Monk6cb90122016-03-02 12:40:43 -0500183 if (mCurrentView == null) return;
Jason Monkf12cfb72016-02-22 15:46:12 -0500184 mCurrentView.post(new Runnable() {
185 @Override
186 public void run() {
187 bindView();
188 }
189 });
190 }
191
Jason Monkc06fbb12016-01-08 14:12:18 -0500192 private void bindView() {
Jason Monk2462a502016-03-02 16:04:39 -0500193 if (mCurrentView == null) {
194 return;
195 }
Jason Monkc06fbb12016-01-08 14:12:18 -0500196 mDrawable.onBatteryLevelChanged(100, false, false);
197 mDrawable.onPowerSaveChanged(true);
Jason Monk5c404c82016-02-05 15:54:10 -0500198 mDrawable.disableShowPercent();
Jason Monkc06fbb12016-01-08 14:12:18 -0500199 ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
200 Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
201 checkbox.setChecked(mPowerSave);
Jason Monkf12cfb72016-02-22 15:46:12 -0500202 BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
203 @Override
204 public void onBatteryInfoLoaded(BatteryInfo info) {
205 if (mCurrentView != null) {
206 bindBatteryInfo(info);
Jason Monkc06fbb12016-01-08 14:12:18 -0500207 }
Jason Monkf12cfb72016-02-22 15:46:12 -0500208 }
209 });
210 if (mCharging) {
Jason Monk96ab6362016-02-11 11:33:09 -0500211 ((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
Jason Monkc06fbb12016-01-08 14:12:18 -0500212 R.string.battery_detail_charging_summary);
Jason Monkc06fbb12016-01-08 14:12:18 -0500213 mCurrentView.findViewById(android.R.id.icon).setVisibility(View.INVISIBLE);
Jason Monk96ab6362016-02-11 11:33:09 -0500214 mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.GONE);
215 mCurrentView.findViewById(R.id.switch_container).setClickable(false);
Jason Monkc06fbb12016-01-08 14:12:18 -0500216 } else {
217 ((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
218 R.string.battery_detail_switch_title);
219 ((TextView) mCurrentView.findViewById(android.R.id.summary)).setText(
220 R.string.battery_detail_switch_summary);
Jason Monkc06fbb12016-01-08 14:12:18 -0500221 mCurrentView.findViewById(android.R.id.icon).setVisibility(View.VISIBLE);
222 mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.VISIBLE);
Jason Monk96ab6362016-02-11 11:33:09 -0500223 mCurrentView.findViewById(R.id.switch_container).setClickable(true);
224 mCurrentView.findViewById(R.id.switch_container).setOnClickListener(this);
Jason Monkc06fbb12016-01-08 14:12:18 -0500225 }
226 }
227
Jason Monk96ab6362016-02-11 11:33:09 -0500228 private void bindBatteryInfo(BatteryInfo info) {
229 SpannableStringBuilder builder = new SpannableStringBuilder();
230 builder.append(info.batteryPercentString, new RelativeSizeSpan(2),
231 Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
232 if (info.remainingLabel != null) {
233 if (mContext.getResources().getBoolean(R.bool.quick_settings_wide)) {
234 builder.append(' ');
235 } else {
236 builder.append('\n');
237 }
238 builder.append(info.remainingLabel);
239 }
240 ((TextView) mCurrentView.findViewById(R.id.charge_and_estimation)).setText(builder);
241
242 info.bindHistory((UsageView) mCurrentView.findViewById(R.id.battery_usage));
243 }
244
Jason Monkc06fbb12016-01-08 14:12:18 -0500245 @Override
246 public void onClick(View v) {
247 mBatteryController.setPowerSaveMode(!mPowerSave);
248 }
249
250 @Override
251 public Intent getSettingsIntent() {
252 return new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
253 }
254
255 @Override
256 public void setToggleState(boolean state) {
257 // No toggle state.
258 }
259
260 @Override
261 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500262 return MetricsEvent.QS_BATTERY_DETAIL;
Jason Monkc06fbb12016-01-08 14:12:18 -0500263 }
Jason Monkf12cfb72016-02-22 15:46:12 -0500264
265 @Override
266 public void onViewAttachedToWindow(View v) {
267 if (!mDetailShown) {
268 mDetailShown = true;
269 v.getContext().registerReceiver(mReceiver,
270 new IntentFilter(Intent.ACTION_TIME_TICK));
271 }
272 }
273
274 @Override
275 public void onViewDetachedFromWindow(View v) {
276 if (mDetailShown) {
277 mDetailShown = false;
278 v.getContext().unregisterReceiver(mReceiver);
279 }
280 }
281
282 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
283 @Override
284 public void onReceive(Context context, Intent intent) {
285 postBindView();
286 }
287 };
Jason Monkabe19742015-09-29 09:47:06 -0400288 }
289}