blob: 2e8752561f86e7b80b81b7c4e0040f75de3a6782 [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 Monk96ab6362016-02-11 11:33:09 -050024import android.text.SpannableStringBuilder;
25import android.text.Spanned;
26import android.text.style.RelativeSizeSpan;
Jason Monkc06fbb12016-01-08 14:12:18 -050027import android.view.LayoutInflater;
28import android.view.View;
Jason Monkf12cfb72016-02-22 15:46:12 -050029import android.view.View.OnAttachStateChangeListener;
30import android.view.View.OnClickListener;
Jason Monkc06fbb12016-01-08 14:12:18 -050031import android.view.ViewGroup;
32import android.widget.Checkable;
33import android.widget.ImageView;
34import android.widget.TextView;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050035import com.android.internal.logging.MetricsProto.MetricsEvent;
Jason Monkc06fbb12016-01-08 14:12:18 -050036import com.android.settingslib.BatteryInfo;
Jason Monk96ab6362016-02-11 11:33:09 -050037import com.android.settingslib.graph.UsageView;
Jason Monkabe19742015-09-29 09:47:06 -040038import com.android.systemui.BatteryMeterDrawable;
39import com.android.systemui.R;
40import com.android.systemui.qs.QSTile;
41import com.android.systemui.statusbar.policy.BatteryController;
42
43import java.text.NumberFormat;
44
45public class BatteryTile extends QSTile<QSTile.State> implements BatteryController.BatteryStateChangeCallback {
46
47 private final BatteryMeterDrawable mDrawable;
48 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 Monkabe19742015-09-29 09:47:06 -040055
56 public BatteryTile(Host host) {
57 super(host);
58 mBatteryController = host.getBatteryController();
59 mDrawable = new BatteryMeterDrawable(host.getContext(), new Handler(),
60 host.getContext().getColor(R.color.batterymeter_frame_color));
61 mDrawable.setBatteryController(mBatteryController);
62 }
63
64 @Override
Jason Monk62b63a02016-02-02 15:15:31 -050065 public State newTileState() {
Jason Monkabe19742015-09-29 09:47:06 -040066 return new QSTile.State();
67 }
68
69 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -050070 public DetailAdapter getDetailAdapter() {
71 return mBatteryDetail;
72 }
73
74 @Override
Jason Monkabe19742015-09-29 09:47:06 -040075 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -050076 return MetricsEvent.QS_BATTERY_TILE;
Jason Monkabe19742015-09-29 09:47:06 -040077 }
78
79 @Override
80 public void setListening(boolean listening) {
81 if (listening) {
82 mDrawable.startListening();
83 mBatteryController.addStateChangedCallback(this);
84 } else {
85 mDrawable.stopListening();
86 mBatteryController.removeStateChangedCallback(this);
87 }
88 }
89
90 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -050091 public void setDetailListening(boolean listening) {
92 super.setDetailListening(listening);
93 if (!listening) {
94 mBatteryDetail.mCurrentView = null;
95 }
96 }
97
98 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -050099 public Intent getLongClickIntent() {
100 return new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
101 }
102
103 @Override
Jason Monkabe19742015-09-29 09:47:06 -0400104 protected void handleClick() {
Jason Monkc06fbb12016-01-08 14:12:18 -0500105 showDetail(true);
Jason Monkabe19742015-09-29 09:47:06 -0400106 }
107
108 @Override
109 protected void handleUpdateState(State state, Object arg) {
110 int level = (arg != null) ? (Integer) arg : mLevel;
111 String percentage = NumberFormat.getPercentInstance().format((double) level / 100.0);
112
Jason Monkabe19742015-09-29 09:47:06 -0400113 state.icon = new Icon() {
114 @Override
115 public Drawable getDrawable(Context context) {
116 return mDrawable;
117 }
Jason Monkb53b6c52016-02-24 17:25:49 -0500118
119 @Override
120 public int getPadding() {
121 return mHost.getContext().getResources().getDimensionPixelSize(
122 R.dimen.qs_battery_padding);
123 }
Jason Monkabe19742015-09-29 09:47:06 -0400124 };
125 state.label = percentage;
126 }
127
128 @Override
129 public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
130 mLevel = level;
Jason Monkc06fbb12016-01-08 14:12:18 -0500131 mCharging = charging;
Jason Monkabe19742015-09-29 09:47:06 -0400132 refreshState((Integer) level);
Jason Monkf12cfb72016-02-22 15:46:12 -0500133 if (mDetailShown) {
134 mBatteryDetail.postBindView();
Jason Monkc06fbb12016-01-08 14:12:18 -0500135 }
Jason Monkabe19742015-09-29 09:47:06 -0400136 }
137
138 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500139 public void onPowerSaveChanged(boolean isPowerSave) {
140 mPowerSave = isPowerSave;
Jason Monkf12cfb72016-02-22 15:46:12 -0500141 if (mDetailShown) {
142 mBatteryDetail.postBindView();
Jason Monkc06fbb12016-01-08 14:12:18 -0500143 }
144 }
Jason Monkabe19742015-09-29 09:47:06 -0400145
Jason Monkf12cfb72016-02-22 15:46:12 -0500146 private final class BatteryDetail implements DetailAdapter, OnClickListener,
147 OnAttachStateChangeListener {
Jason Monkc06fbb12016-01-08 14:12:18 -0500148 private final BatteryMeterDrawable mDrawable = new BatteryMeterDrawable(mHost.getContext(),
149 new Handler(), mHost.getContext().getColor(R.color.batterymeter_frame_color));
150 private View mCurrentView;
151
152 @Override
153 public CharSequence getTitle() {
154 return mContext.getString(R.string.battery_panel_title, mLevel);
155 }
156
157 @Override
158 public Boolean getToggleState() {
159 return null;
160 }
161
162 @Override
163 public View createDetailView(Context context, View convertView, ViewGroup parent) {
164 if (convertView == null) {
165 convertView = LayoutInflater.from(mContext).inflate(R.layout.battery_detail, parent,
166 false);
167 }
168 mCurrentView = convertView;
Jason Monkf12cfb72016-02-22 15:46:12 -0500169 mCurrentView.addOnAttachStateChangeListener(this);
Jason Monkc06fbb12016-01-08 14:12:18 -0500170 bindView();
171 return convertView;
172 }
173
Jason Monkf12cfb72016-02-22 15:46:12 -0500174 private void postBindView() {
Jason Monk6cb90122016-03-02 12:40:43 -0500175 if (mCurrentView == null) return;
Jason Monkf12cfb72016-02-22 15:46:12 -0500176 mCurrentView.post(new Runnable() {
177 @Override
178 public void run() {
179 bindView();
180 }
181 });
182 }
183
Jason Monkc06fbb12016-01-08 14:12:18 -0500184 private void bindView() {
Jason Monk2462a502016-03-02 16:04:39 -0500185 if (mCurrentView == null) {
186 return;
187 }
Jason Monkc06fbb12016-01-08 14:12:18 -0500188 mDrawable.onBatteryLevelChanged(100, false, false);
189 mDrawable.onPowerSaveChanged(true);
Jason Monk5c404c82016-02-05 15:54:10 -0500190 mDrawable.disableShowPercent();
Jason Monkc06fbb12016-01-08 14:12:18 -0500191 ((ImageView) mCurrentView.findViewById(android.R.id.icon)).setImageDrawable(mDrawable);
192 Checkable checkbox = (Checkable) mCurrentView.findViewById(android.R.id.toggle);
193 checkbox.setChecked(mPowerSave);
Jason Monkf12cfb72016-02-22 15:46:12 -0500194 BatteryInfo.getBatteryInfo(mContext, new BatteryInfo.Callback() {
195 @Override
196 public void onBatteryInfoLoaded(BatteryInfo info) {
197 if (mCurrentView != null) {
198 bindBatteryInfo(info);
Jason Monkc06fbb12016-01-08 14:12:18 -0500199 }
Jason Monkf12cfb72016-02-22 15:46:12 -0500200 }
201 });
202 if (mCharging) {
Jason Monk96ab6362016-02-11 11:33:09 -0500203 ((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
Jason Monkc06fbb12016-01-08 14:12:18 -0500204 R.string.battery_detail_charging_summary);
Jason Monkc06fbb12016-01-08 14:12:18 -0500205 mCurrentView.findViewById(android.R.id.icon).setVisibility(View.INVISIBLE);
Jason Monk96ab6362016-02-11 11:33:09 -0500206 mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.GONE);
207 mCurrentView.findViewById(R.id.switch_container).setClickable(false);
Jason Monkc06fbb12016-01-08 14:12:18 -0500208 } else {
209 ((TextView) mCurrentView.findViewById(android.R.id.title)).setText(
210 R.string.battery_detail_switch_title);
211 ((TextView) mCurrentView.findViewById(android.R.id.summary)).setText(
212 R.string.battery_detail_switch_summary);
Jason Monkc06fbb12016-01-08 14:12:18 -0500213 mCurrentView.findViewById(android.R.id.icon).setVisibility(View.VISIBLE);
214 mCurrentView.findViewById(android.R.id.toggle).setVisibility(View.VISIBLE);
Jason Monk96ab6362016-02-11 11:33:09 -0500215 mCurrentView.findViewById(R.id.switch_container).setClickable(true);
216 mCurrentView.findViewById(R.id.switch_container).setOnClickListener(this);
Jason Monkc06fbb12016-01-08 14:12:18 -0500217 }
218 }
219
Jason Monk96ab6362016-02-11 11:33:09 -0500220 private void bindBatteryInfo(BatteryInfo info) {
221 SpannableStringBuilder builder = new SpannableStringBuilder();
222 builder.append(info.batteryPercentString, new RelativeSizeSpan(2),
223 Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
224 if (info.remainingLabel != null) {
225 if (mContext.getResources().getBoolean(R.bool.quick_settings_wide)) {
226 builder.append(' ');
227 } else {
228 builder.append('\n');
229 }
230 builder.append(info.remainingLabel);
231 }
232 ((TextView) mCurrentView.findViewById(R.id.charge_and_estimation)).setText(builder);
233
234 info.bindHistory((UsageView) mCurrentView.findViewById(R.id.battery_usage));
235 }
236
Jason Monkc06fbb12016-01-08 14:12:18 -0500237 @Override
238 public void onClick(View v) {
239 mBatteryController.setPowerSaveMode(!mPowerSave);
240 }
241
242 @Override
243 public Intent getSettingsIntent() {
244 return new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
245 }
246
247 @Override
248 public void setToggleState(boolean state) {
249 // No toggle state.
250 }
251
252 @Override
253 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500254 return MetricsEvent.QS_BATTERY_DETAIL;
Jason Monkc06fbb12016-01-08 14:12:18 -0500255 }
Jason Monkf12cfb72016-02-22 15:46:12 -0500256
257 @Override
258 public void onViewAttachedToWindow(View v) {
259 if (!mDetailShown) {
260 mDetailShown = true;
261 v.getContext().registerReceiver(mReceiver,
262 new IntentFilter(Intent.ACTION_TIME_TICK));
263 }
264 }
265
266 @Override
267 public void onViewDetachedFromWindow(View v) {
268 if (mDetailShown) {
269 mDetailShown = false;
270 v.getContext().unregisterReceiver(mReceiver);
271 }
272 }
273
274 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
275 @Override
276 public void onReceive(Context context, Intent intent) {
277 postBindView();
278 }
279 };
Jason Monkabe19742015-09-29 09:47:06 -0400280 }
281}