blob: 736286f21bfe7e6a26c5de45ddbbf6061eaff9c7 [file] [log] [blame]
John Spurlock3332ba52014-03-10 17:44:07 -04001/*
2 * Copyright (C) 2014 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 */
16
17package com.android.systemui.power;
18
John Spurlock3332ba52014-03-10 17:44:07 -040019import android.app.Notification;
20import android.app.NotificationManager;
21import android.app.PendingIntent;
22import android.content.BroadcastReceiver;
John Spurlock3332ba52014-03-10 17:44:07 -040023import android.content.Context;
24import android.content.DialogInterface;
25import android.content.DialogInterface.OnClickListener;
John Spurlock1bb480a2014-08-02 17:12:43 -040026import android.content.DialogInterface.OnDismissListener;
John Spurlock3332ba52014-03-10 17:44:07 -040027import android.content.Intent;
28import android.content.IntentFilter;
Salvador Martinezf9e47502018-01-04 13:45:48 -080029import android.icu.text.MeasureFormat;
30import android.icu.text.MeasureFormat.FormatWidth;
31import android.icu.util.Measure;
32import android.icu.util.MeasureUnit;
John Spurlock1bb480a2014-08-02 17:12:43 -040033import android.media.AudioAttributes;
John Spurlock3332ba52014-03-10 17:44:07 -040034import android.os.AsyncTask;
35import android.os.Handler;
Geoffrey Pitsch4a7931d2016-09-15 13:11:47 -040036import android.os.Looper;
John Spurlock8d4e6cb2014-09-14 11:10:22 -040037import android.os.PowerManager;
John Spurlock3332ba52014-03-10 17:44:07 -040038import android.os.UserHandle;
Salvador Martineza6f7b252017-04-10 10:46:15 -070039import android.support.annotation.VisibleForTesting;
Salvador Martinezf9e47502018-01-04 13:45:48 -080040import android.text.format.DateUtils;
John Spurlock3332ba52014-03-10 17:44:07 -040041import android.util.Slog;
John Spurlock3332ba52014-03-10 17:44:07 -040042
Chris Wren5e6c0ff2017-01-05 12:57:06 -050043import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
Jason Monk58be7a62017-02-01 20:17:51 -050044import com.android.settingslib.Utils;
John Spurlock3332ba52014-03-10 17:44:07 -040045import com.android.systemui.R;
Adrian Roose25c18d2016-06-17 15:59:49 -070046import com.android.systemui.SystemUI;
John Spurlock1bb480a2014-08-02 17:12:43 -040047import com.android.systemui.statusbar.phone.SystemUIDialog;
Dan Sandler8e032e12017-01-25 13:41:38 -050048import com.android.systemui.util.NotificationChannels;
John Spurlock3332ba52014-03-10 17:44:07 -040049
50import java.io.PrintWriter;
Elliott Hughes88d25512014-10-03 12:06:17 -070051import java.text.NumberFormat;
Salvador Martinezf9e47502018-01-04 13:45:48 -080052import java.util.Locale;
53import java.util.concurrent.TimeUnit;
John Spurlock3332ba52014-03-10 17:44:07 -040054
55public class PowerNotificationWarnings implements PowerUI.WarningsUI {
56 private static final String TAG = PowerUI.TAG + ".Notification";
57 private static final boolean DEBUG = PowerUI.DEBUG;
58
Chris Wren5e6c0ff2017-01-05 12:57:06 -050059 private static final String TAG_BATTERY = "low_battery";
60 private static final String TAG_TEMPERATURE = "high_temp";
John Spurlock3332ba52014-03-10 17:44:07 -040061
62 private static final int SHOWING_NOTHING = 0;
63 private static final int SHOWING_WARNING = 1;
John Spurlock3332ba52014-03-10 17:44:07 -040064 private static final int SHOWING_INVALID_CHARGER = 3;
65 private static final String[] SHOWING_STRINGS = {
66 "SHOWING_NOTHING",
67 "SHOWING_WARNING",
68 "SHOWING_SAVER",
69 "SHOWING_INVALID_CHARGER",
70 };
71
John Spurlock3332ba52014-03-10 17:44:07 -040072 private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings";
73 private static final String ACTION_START_SAVER = "PNW.startSaver";
John Spurlock42bfc9a2014-10-29 11:13:01 -040074 private static final String ACTION_DISMISSED_WARNING = "PNW.dismissedWarning";
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -080075 private static final String ACTION_CLICKED_TEMP_WARNING = "PNW.clickedTempWarning";
76 private static final String ACTION_DISMISSED_TEMP_WARNING = "PNW.dismissedTempWarning";
Salvador Martineza6f7b252017-04-10 10:46:15 -070077 private static final String ACTION_CLICKED_THERMAL_SHUTDOWN_WARNING =
78 "PNW.clickedThermalShutdownWarning";
79 private static final String ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING =
80 "PNW.dismissedThermalShutdownWarning";
John Spurlock1bb480a2014-08-02 17:12:43 -040081
82 private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder()
83 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
84 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
85 .build();
John Spurlock3332ba52014-03-10 17:44:07 -040086
87 private final Context mContext;
John Spurlock3332ba52014-03-10 17:44:07 -040088 private final NotificationManager mNoMan;
John Spurlock8d4e6cb2014-09-14 11:10:22 -040089 private final PowerManager mPowerMan;
Geoffrey Pitsch4a7931d2016-09-15 13:11:47 -040090 private final Handler mHandler = new Handler(Looper.getMainLooper());
John Spurlock3332ba52014-03-10 17:44:07 -040091 private final Receiver mReceiver = new Receiver();
92 private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
John Spurlock3332ba52014-03-10 17:44:07 -040093
94 private int mBatteryLevel;
95 private int mBucket;
96 private long mScreenOffTime;
97 private int mShowing;
98
Salvador Martinezf9e47502018-01-04 13:45:48 -080099 private long mWarningTriggerTimeMs;
Christoph Studer65fa0a92014-06-26 16:50:09 +0200100
Salvador Martinezf9e47502018-01-04 13:45:48 -0800101 private Estimate mEstimate;
John Spurlock3332ba52014-03-10 17:44:07 -0400102 private boolean mWarning;
103 private boolean mPlaySound;
104 private boolean mInvalidCharger;
John Spurlock1bb480a2014-08-02 17:12:43 -0400105 private SystemUIDialog mSaverConfirmation;
Salvador Martineza6f7b252017-04-10 10:46:15 -0700106 private boolean mHighTempWarning;
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800107 private SystemUIDialog mHighTempDialog;
Salvador Martineza6f7b252017-04-10 10:46:15 -0700108 private SystemUIDialog mThermalShutdownDialog;
John Spurlock3332ba52014-03-10 17:44:07 -0400109
Jason Monkd819c312017-08-11 12:53:36 -0400110 public PowerNotificationWarnings(Context context) {
John Spurlock3332ba52014-03-10 17:44:07 -0400111 mContext = context;
Jason Monkd819c312017-08-11 12:53:36 -0400112 mNoMan = mContext.getSystemService(NotificationManager.class);
John Spurlock8d4e6cb2014-09-14 11:10:22 -0400113 mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
John Spurlock3332ba52014-03-10 17:44:07 -0400114 mReceiver.init();
115 }
116
117 @Override
118 public void dump(PrintWriter pw) {
John Spurlock3332ba52014-03-10 17:44:07 -0400119 pw.print("mWarning="); pw.println(mWarning);
120 pw.print("mPlaySound="); pw.println(mPlaySound);
121 pw.print("mInvalidCharger="); pw.println(mInvalidCharger);
122 pw.print("mShowing="); pw.println(SHOWING_STRINGS[mShowing]);
John Spurlock1bb480a2014-08-02 17:12:43 -0400123 pw.print("mSaverConfirmation="); pw.println(mSaverConfirmation != null ? "not null" : null);
Salvador Martineza6f7b252017-04-10 10:46:15 -0700124 pw.print("mHighTempWarning="); pw.println(mHighTempWarning);
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800125 pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
Salvador Martineza6f7b252017-04-10 10:46:15 -0700126 pw.print("mThermalShutdownDialog=");
127 pw.println(mThermalShutdownDialog != null ? "not null" : null);
John Spurlock3332ba52014-03-10 17:44:07 -0400128 }
129
130 @Override
131 public void update(int batteryLevel, int bucket, long screenOffTime) {
132 mBatteryLevel = batteryLevel;
Christoph Studer65fa0a92014-06-26 16:50:09 +0200133 if (bucket >= 0) {
Salvador Martinezf9e47502018-01-04 13:45:48 -0800134 mWarningTriggerTimeMs = 0;
Christoph Studer65fa0a92014-06-26 16:50:09 +0200135 } else if (bucket < mBucket) {
Salvador Martinezf9e47502018-01-04 13:45:48 -0800136 mWarningTriggerTimeMs = System.currentTimeMillis();
Christoph Studer65fa0a92014-06-26 16:50:09 +0200137 }
John Spurlock3332ba52014-03-10 17:44:07 -0400138 mBucket = bucket;
139 mScreenOffTime = screenOffTime;
John Spurlock3332ba52014-03-10 17:44:07 -0400140 }
141
Salvador Martinezf9e47502018-01-04 13:45:48 -0800142 @Override
143 public void updateEstimate(Estimate estimate) {
144 mEstimate = estimate;
145 if (estimate.estimateMillis <= PowerUI.THREE_HOURS_IN_MILLIS) {
146 mWarningTriggerTimeMs = System.currentTimeMillis();
147 }
148 }
149
John Spurlock3332ba52014-03-10 17:44:07 -0400150 private void updateNotification() {
John Spurlock86c3de82014-08-19 13:37:44 -0400151 if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning + " mPlaySound="
Jason Monkc06fbb12016-01-08 14:12:18 -0500152 + mPlaySound + " mInvalidCharger=" + mInvalidCharger);
John Spurlock3332ba52014-03-10 17:44:07 -0400153 if (mInvalidCharger) {
John Spurlock3332ba52014-03-10 17:44:07 -0400154 showInvalidChargerNotification();
155 mShowing = SHOWING_INVALID_CHARGER;
156 } else if (mWarning) {
John Spurlock3332ba52014-03-10 17:44:07 -0400157 showWarningNotification();
158 mShowing = SHOWING_WARNING;
John Spurlock3332ba52014-03-10 17:44:07 -0400159 } else {
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500160 mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL);
161 mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, UserHandle.ALL);
John Spurlock3332ba52014-03-10 17:44:07 -0400162 mShowing = SHOWING_NOTHING;
163 }
164 }
165
166 private void showInvalidChargerNotification() {
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500167 final Notification.Builder nb =
168 new Notification.Builder(mContext, NotificationChannels.ALERTS)
169 .setSmallIcon(R.drawable.ic_power_low)
170 .setWhen(0)
171 .setShowWhen(false)
172 .setOngoing(true)
173 .setContentTitle(mContext.getString(R.string.invalid_charger_title))
174 .setContentText(mContext.getString(R.string.invalid_charger_text))
175 .setColor(mContext.getColor(
176 com.android.internal.R.color.system_notification_accent_color));
Adrian Roose25c18d2016-06-17 15:59:49 -0700177 SystemUI.overrideNotificationAppName(mContext, nb);
John Spurlock3332ba52014-03-10 17:44:07 -0400178 final Notification n = nb.build();
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500179 mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, UserHandle.ALL);
180 mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, n, UserHandle.ALL);
John Spurlock3332ba52014-03-10 17:44:07 -0400181 }
182
Salvador Martinezf9e47502018-01-04 13:45:48 -0800183 protected void showWarningNotification() {
Elliott Hughes88d25512014-10-03 12:06:17 -0700184 final String percentage = NumberFormat.getPercentInstance().format((double) mBatteryLevel / 100.0);
Beverly334bc5f2017-07-31 10:37:17 -0400185
Salvador Martinezf9e47502018-01-04 13:45:48 -0800186 // get standard notification copy
187 String title = mContext.getString(R.string.battery_low_title);
188 String contentText = mContext.getString(R.string.battery_low_percent_format, percentage);
189
190 // override notification copy if hybrid notification enabled
191 if (mEstimate != null) {
192 title = mContext.getString(R.string.battery_low_title_hybrid);
193 contentText = mContext.getString(
194 mEstimate.isBasedOnUsage
195 ? R.string.battery_low_percent_format_hybrid
196 : R.string.battery_low_percent_format_hybrid_short,
197 percentage,
198 getTimeRemainingFormatted());
199 }
200
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500201 final Notification.Builder nb =
Beverly334bc5f2017-07-31 10:37:17 -0400202 new Notification.Builder(mContext, NotificationChannels.BATTERY)
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500203 .setSmallIcon(R.drawable.ic_power_low)
204 // Bump the notification when the bucket dropped.
Salvador Martinezf9e47502018-01-04 13:45:48 -0800205 .setWhen(mWarningTriggerTimeMs)
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500206 .setShowWhen(false)
Salvador Martinezf9e47502018-01-04 13:45:48 -0800207 .setContentTitle(title)
208 .setContentText(contentText)
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500209 .setOnlyAlertOnce(true)
210 .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_WARNING))
Salvador Martinezf9e47502018-01-04 13:45:48 -0800211 .setVisibility(Notification.VISIBILITY_PUBLIC);
John Spurlock3332ba52014-03-10 17:44:07 -0400212 if (hasBatterySettings()) {
213 nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS));
214 }
Salvador Martinezf9e47502018-01-04 13:45:48 -0800215 // Make the notification red if the percentage goes below a certain amount or the time
216 // remaining estimate is disabled
217 if (mEstimate == null || mBucket < 0) {
218 nb.setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
219 }
Jason Monkc06fbb12016-01-08 14:12:18 -0500220 nb.addAction(0,
221 mContext.getString(R.string.battery_saver_start_action),
222 pendingBroadcast(ACTION_START_SAVER));
Beverly334bc5f2017-07-31 10:37:17 -0400223 nb.setOnlyAlertOnce(!mPlaySound);
224 mPlaySound = false;
Adrian Roose25c18d2016-06-17 15:59:49 -0700225 SystemUI.overrideNotificationAppName(mContext, nb);
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500226 final Notification n = nb.build();
227 mNoMan.cancelAsUser(TAG_BATTERY, SystemMessage.NOTE_BAD_CHARGER, UserHandle.ALL);
228 mNoMan.notifyAsUser(TAG_BATTERY, SystemMessage.NOTE_POWER_LOW, n, UserHandle.ALL);
John Spurlock3332ba52014-03-10 17:44:07 -0400229 }
230
Salvador Martinezf9e47502018-01-04 13:45:48 -0800231 @VisibleForTesting
232 String getTimeRemainingFormatted() {
233 final Locale currentLocale = mContext.getResources().getConfiguration().getLocales().get(0);
234 MeasureFormat frmt = MeasureFormat.getInstance(currentLocale, FormatWidth.NARROW);
235
236 final long remainder = mEstimate.estimateMillis % DateUtils.HOUR_IN_MILLIS;
237 final long hours = TimeUnit.MILLISECONDS.toHours(
238 mEstimate.estimateMillis - remainder);
239 // round down to the nearest 15 min for now to not appear overly precise
240 final long minutes = TimeUnit.MILLISECONDS.toMinutes(
241 remainder - (remainder % TimeUnit.MINUTES.toMillis(15)));
242 final Measure hoursMeasure = new Measure(hours, MeasureUnit.HOUR);
243 final Measure minutesMeasure = new Measure(minutes, MeasureUnit.MINUTE);
244
245 return frmt.formatMeasures(hoursMeasure, minutesMeasure);
246 }
247
John Spurlock3332ba52014-03-10 17:44:07 -0400248 private PendingIntent pendingBroadcast(String action) {
249 return PendingIntent.getBroadcastAsUser(mContext,
250 0, new Intent(action), 0, UserHandle.CURRENT);
251 }
252
253 private static Intent settings(String action) {
254 return new Intent(action).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
255 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
256 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
257 | Intent.FLAG_ACTIVITY_NO_HISTORY
258 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
259 }
260
261 @Override
262 public boolean isInvalidChargerWarningShowing() {
263 return mInvalidCharger;
264 }
265
266 @Override
Salvador Martineza6f7b252017-04-10 10:46:15 -0700267 public void dismissHighTemperatureWarning() {
268 if (!mHighTempWarning) {
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800269 return;
270 }
Salvador Martineza6f7b252017-04-10 10:46:15 -0700271 mHighTempWarning = false;
272 dismissHighTemperatureWarningInternal();
Andrew Sapperstein97bfa0f2017-01-24 16:38:50 -0800273 }
274
275 /**
Salvador Martineza6f7b252017-04-10 10:46:15 -0700276 * Internal only version of {@link #dismissHighTemperatureWarning()} that simply dismisses
Andrew Sapperstein97bfa0f2017-01-24 16:38:50 -0800277 * the notification. As such, the notification will not show again until
Salvador Martineza6f7b252017-04-10 10:46:15 -0700278 * {@link #dismissHighTemperatureWarning()} is called.
Andrew Sapperstein97bfa0f2017-01-24 16:38:50 -0800279 */
Salvador Martineza6f7b252017-04-10 10:46:15 -0700280 private void dismissHighTemperatureWarningInternal() {
Andrew Sapperstein97bfa0f2017-01-24 16:38:50 -0800281 mNoMan.cancelAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, UserHandle.ALL);
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800282 }
283
284 @Override
Salvador Martineza6f7b252017-04-10 10:46:15 -0700285 public void showHighTemperatureWarning() {
286 if (mHighTempWarning) {
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800287 return;
288 }
Salvador Martineza6f7b252017-04-10 10:46:15 -0700289 mHighTempWarning = true;
Geoffrey Pitsch1dc93bc2017-01-31 16:38:11 -0500290 final Notification.Builder nb =
291 new Notification.Builder(mContext, NotificationChannels.ALERTS)
292 .setSmallIcon(R.drawable.ic_device_thermostat_24)
293 .setWhen(0)
294 .setShowWhen(false)
295 .setContentTitle(mContext.getString(R.string.high_temp_title))
296 .setContentText(mContext.getString(R.string.high_temp_notif_message))
297 .setVisibility(Notification.VISIBILITY_PUBLIC)
298 .setContentIntent(pendingBroadcast(ACTION_CLICKED_TEMP_WARNING))
299 .setDeleteIntent(pendingBroadcast(ACTION_DISMISSED_TEMP_WARNING))
Jason Monk58be7a62017-02-01 20:17:51 -0500300 .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800301 SystemUI.overrideNotificationAppName(mContext, nb);
302 final Notification n = nb.build();
Chris Wren5e6c0ff2017-01-05 12:57:06 -0500303 mNoMan.notifyAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_HIGH_TEMP, n, UserHandle.ALL);
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800304 }
305
Salvador Martineza6f7b252017-04-10 10:46:15 -0700306 private void showHighTemperatureDialog() {
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800307 if (mHighTempDialog != null) return;
308 final SystemUIDialog d = new SystemUIDialog(mContext);
Andrew Sappersteine26dc3d2017-01-04 11:25:20 -0800309 d.setIconAttribute(android.R.attr.alertDialogIcon);
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800310 d.setTitle(R.string.high_temp_title);
311 d.setMessage(R.string.high_temp_dialog_message);
312 d.setPositiveButton(com.android.internal.R.string.ok, null);
313 d.setShowForAllUsers(true);
314 d.setOnDismissListener(dialog -> mHighTempDialog = null);
315 d.show();
316 mHighTempDialog = d;
317 }
318
Salvador Martineza6f7b252017-04-10 10:46:15 -0700319 @VisibleForTesting
320 void dismissThermalShutdownWarning() {
321 mNoMan.cancelAsUser(TAG_TEMPERATURE, SystemMessage.NOTE_THERMAL_SHUTDOWN, UserHandle.ALL);
322 }
323
324 private void showThermalShutdownDialog() {
325 if (mThermalShutdownDialog != null) return;
326 final SystemUIDialog d = new SystemUIDialog(mContext);
327 d.setIconAttribute(android.R.attr.alertDialogIcon);
328 d.setTitle(R.string.thermal_shutdown_title);
329 d.setMessage(R.string.thermal_shutdown_dialog_message);
330 d.setPositiveButton(com.android.internal.R.string.ok, null);
331 d.setShowForAllUsers(true);
332 d.setOnDismissListener(dialog -> mThermalShutdownDialog = null);
333 d.show();
334 mThermalShutdownDialog = d;
335 }
336
337 @Override
338 public void showThermalShutdownWarning() {
339 final Notification.Builder nb =
340 new Notification.Builder(mContext, NotificationChannels.ALERTS)
341 .setSmallIcon(R.drawable.ic_device_thermostat_24)
342 .setWhen(0)
343 .setShowWhen(false)
344 .setContentTitle(mContext.getString(R.string.thermal_shutdown_title))
345 .setContentText(mContext.getString(R.string.thermal_shutdown_message))
346 .setVisibility(Notification.VISIBILITY_PUBLIC)
347 .setContentIntent(pendingBroadcast(ACTION_CLICKED_THERMAL_SHUTDOWN_WARNING))
348 .setDeleteIntent(
349 pendingBroadcast(ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING))
350 .setColor(Utils.getColorAttr(mContext, android.R.attr.colorError));
351 SystemUI.overrideNotificationAppName(mContext, nb);
352 final Notification n = nb.build();
353 mNoMan.notifyAsUser(
354 TAG_TEMPERATURE, SystemMessage.NOTE_THERMAL_SHUTDOWN, n, UserHandle.ALL);
355 }
356
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800357 @Override
John Spurlock3332ba52014-03-10 17:44:07 -0400358 public void updateLowBatteryWarning() {
359 updateNotification();
John Spurlock3332ba52014-03-10 17:44:07 -0400360 }
361
362 @Override
363 public void dismissLowBatteryWarning() {
John Spurlock3ff2de62014-06-16 13:32:48 -0400364 if (DEBUG) Slog.d(TAG, "dismissing low battery warning: level=" + mBatteryLevel);
John Spurlock3332ba52014-03-10 17:44:07 -0400365 dismissLowBatteryNotification();
John Spurlock3332ba52014-03-10 17:44:07 -0400366 }
367
368 private void dismissLowBatteryNotification() {
John Spurlock3ff2de62014-06-16 13:32:48 -0400369 if (mWarning) Slog.i(TAG, "dismissing low battery notification");
John Spurlock3332ba52014-03-10 17:44:07 -0400370 mWarning = false;
371 updateNotification();
372 }
373
374 private boolean hasBatterySettings() {
375 return mOpenBatterySettings.resolveActivity(mContext.getPackageManager()) != null;
376 }
377
John Spurlock3332ba52014-03-10 17:44:07 -0400378 @Override
379 public void showLowBatteryWarning(boolean playSound) {
380 Slog.i(TAG,
381 "show low battery warning: level=" + mBatteryLevel
Beverly334bc5f2017-07-31 10:37:17 -0400382 + " [" + mBucket + "] playSound=" + playSound);
John Spurlock3332ba52014-03-10 17:44:07 -0400383 mPlaySound = playSound;
384 mWarning = true;
385 updateNotification();
John Spurlock3332ba52014-03-10 17:44:07 -0400386 }
387
John Spurlock3332ba52014-03-10 17:44:07 -0400388 @Override
389 public void dismissInvalidChargerWarning() {
John Spurlockeb44a7d2014-06-12 13:00:55 -0400390 dismissInvalidChargerNotification();
John Spurlockeb44a7d2014-06-12 13:00:55 -0400391 }
392
393 private void dismissInvalidChargerNotification() {
John Spurlock3ff2de62014-06-16 13:32:48 -0400394 if (mInvalidCharger) Slog.i(TAG, "dismissing invalid charger notification");
John Spurlock3332ba52014-03-10 17:44:07 -0400395 mInvalidCharger = false;
396 updateNotification();
397 }
398
399 @Override
400 public void showInvalidChargerWarning() {
401 mInvalidCharger = true;
402 updateNotification();
403 }
404
John Spurlockecbc5e82014-10-22 09:05:51 -0400405 @Override
406 public void userSwitched() {
407 updateNotification();
408 }
409
John Spurlock3332ba52014-03-10 17:44:07 -0400410 private void showStartSaverConfirmation() {
John Spurlock1bb480a2014-08-02 17:12:43 -0400411 if (mSaverConfirmation != null) return;
412 final SystemUIDialog d = new SystemUIDialog(mContext);
413 d.setTitle(R.string.battery_saver_confirmation_title);
414 d.setMessage(com.android.internal.R.string.battery_saver_description);
415 d.setNegativeButton(android.R.string.cancel, null);
416 d.setPositiveButton(R.string.battery_saver_confirmation_ok, mStartSaverMode);
417 d.setShowForAllUsers(true);
418 d.setOnDismissListener(new OnDismissListener() {
419 @Override
420 public void onDismiss(DialogInterface dialog) {
421 mSaverConfirmation = null;
422 }
423 });
John Spurlock3332ba52014-03-10 17:44:07 -0400424 d.show();
John Spurlock1bb480a2014-08-02 17:12:43 -0400425 mSaverConfirmation = d;
John Spurlock3332ba52014-03-10 17:44:07 -0400426 }
427
John Spurlock8d4e6cb2014-09-14 11:10:22 -0400428 private void setSaverMode(boolean mode) {
429 mPowerMan.setPowerSaveMode(mode);
John Spurlock3332ba52014-03-10 17:44:07 -0400430 }
431
432 private final class Receiver extends BroadcastReceiver {
433
434 public void init() {
435 IntentFilter filter = new IntentFilter();
John Spurlock3332ba52014-03-10 17:44:07 -0400436 filter.addAction(ACTION_SHOW_BATTERY_SETTINGS);
437 filter.addAction(ACTION_START_SAVER);
John Spurlock42bfc9a2014-10-29 11:13:01 -0400438 filter.addAction(ACTION_DISMISSED_WARNING);
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800439 filter.addAction(ACTION_CLICKED_TEMP_WARNING);
440 filter.addAction(ACTION_DISMISSED_TEMP_WARNING);
Salvador Martineza6f7b252017-04-10 10:46:15 -0700441 filter.addAction(ACTION_CLICKED_THERMAL_SHUTDOWN_WARNING);
442 filter.addAction(ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING);
John Spurlock05e07052015-06-01 10:56:42 -0400443 mContext.registerReceiverAsUser(this, UserHandle.ALL, filter,
444 android.Manifest.permission.STATUS_BAR_SERVICE, mHandler);
John Spurlock3332ba52014-03-10 17:44:07 -0400445 }
446
447 @Override
448 public void onReceive(Context context, Intent intent) {
449 final String action = intent.getAction();
John Spurlockeb44a7d2014-06-12 13:00:55 -0400450 Slog.i(TAG, "Received " + action);
John Spurlock86c3de82014-08-19 13:37:44 -0400451 if (action.equals(ACTION_SHOW_BATTERY_SETTINGS)) {
John Spurlock3332ba52014-03-10 17:44:07 -0400452 dismissLowBatteryNotification();
453 mContext.startActivityAsUser(mOpenBatterySettings, UserHandle.CURRENT);
454 } else if (action.equals(ACTION_START_SAVER)) {
455 dismissLowBatteryNotification();
456 showStartSaverConfirmation();
John Spurlock42bfc9a2014-10-29 11:13:01 -0400457 } else if (action.equals(ACTION_DISMISSED_WARNING)) {
458 dismissLowBatteryWarning();
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800459 } else if (ACTION_CLICKED_TEMP_WARNING.equals(action)) {
Salvador Martineza6f7b252017-04-10 10:46:15 -0700460 dismissHighTemperatureWarningInternal();
461 showHighTemperatureDialog();
Andrew Sappersteinb7caf1d2016-12-14 15:39:20 -0800462 } else if (ACTION_DISMISSED_TEMP_WARNING.equals(action)) {
Salvador Martineza6f7b252017-04-10 10:46:15 -0700463 dismissHighTemperatureWarningInternal();
464 } else if (ACTION_CLICKED_THERMAL_SHUTDOWN_WARNING.equals(action)) {
465 dismissThermalShutdownWarning();
466 showThermalShutdownDialog();
467 } else if (ACTION_DISMISSED_THERMAL_SHUTDOWN_WARNING.equals(action)) {
468 dismissThermalShutdownWarning();
John Spurlock3332ba52014-03-10 17:44:07 -0400469 }
470 }
471 }
472
473 private final OnClickListener mStartSaverMode = new OnClickListener() {
474 @Override
475 public void onClick(DialogInterface dialog, int which) {
476 AsyncTask.execute(new Runnable() {
477 @Override
478 public void run() {
John Spurlock8d4e6cb2014-09-14 11:10:22 -0400479 setSaverMode(true);
John Spurlock3332ba52014-03-10 17:44:07 -0400480 }
481 });
482 }
483 };
John Spurlock3332ba52014-03-10 17:44:07 -0400484}