13332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock/* 23332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * Copyright (C) 2014 The Android Open Source Project 33332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * 43332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 53332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * you may not use this file except in compliance with the License. 63332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * You may obtain a copy of the License at 73332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * 83332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * http://www.apache.org/licenses/LICENSE-2.0 93332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * 103332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * Unless required by applicable law or agreed to in writing, software 113332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 123332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * See the License for the specific language governing permissions and 143332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock * limitations under the License. 153332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock */ 163332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 173332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockpackage com.android.systemui.power; 183332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 193332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.app.Notification; 203332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.app.NotificationManager; 213332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.app.PendingIntent; 223332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.content.BroadcastReceiver; 233332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.content.ContentResolver; 243332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.content.Context; 253332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.content.DialogInterface; 263332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.content.DialogInterface.OnClickListener; 271bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlockimport android.content.DialogInterface.OnDismissListener; 283332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.content.Intent; 293332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.content.IntentFilter; 301bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlockimport android.media.AudioAttributes; 313332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.net.Uri; 323332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.os.AsyncTask; 333332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.os.Handler; 348d4e6cb06005a2ce994360340a6191f0690db8f4John Spurlockimport android.os.PowerManager; 353332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.os.SystemClock; 363332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.os.UserHandle; 373332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.provider.Settings; 383332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.util.Slog; 393332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport android.view.View; 403332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 413332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport com.android.systemui.R; 428de4311c51229efbe2f2d0afbf298982c5cadd96Jorim Jaggiimport com.android.systemui.statusbar.phone.PhoneStatusBar; 431bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlockimport com.android.systemui.statusbar.phone.SystemUIDialog; 443332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 453332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockimport java.io.PrintWriter; 463332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 473332ba54ae85df14d761447d86d2aa19d448ce11John Spurlockpublic class PowerNotificationWarnings implements PowerUI.WarningsUI { 483332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final String TAG = PowerUI.TAG + ".Notification"; 493332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final boolean DEBUG = PowerUI.DEBUG; 503332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 513332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final String TAG_NOTIFICATION = "low_battery"; 523332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final int ID_NOTIFICATION = 100; 533332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 543332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final int SHOWING_NOTHING = 0; 553332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final int SHOWING_WARNING = 1; 563332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final int SHOWING_SAVER = 2; 573332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final int SHOWING_INVALID_CHARGER = 3; 583332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final String[] SHOWING_STRINGS = { 593332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock "SHOWING_NOTHING", 603332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock "SHOWING_WARNING", 613332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock "SHOWING_SAVER", 623332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock "SHOWING_INVALID_CHARGER", 633332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock }; 643332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 653332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final String ACTION_SHOW_BATTERY_SETTINGS = "PNW.batterySettings"; 663332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static final String ACTION_START_SAVER = "PNW.startSaver"; 671bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock private static final String ACTION_STOP_SAVER = "PNW.stopSaver"; 681bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock 691bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock private static final AudioAttributes AUDIO_ATTRIBUTES = new AudioAttributes.Builder() 701bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) 711bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) 721bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock .build(); 733332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 743332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final Context mContext; 753332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final NotificationManager mNoMan; 768d4e6cb06005a2ce994360340a6191f0690db8f4John Spurlock private final PowerManager mPowerMan; 773332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final Handler mHandler = new Handler(); 783332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final Receiver mReceiver = new Receiver(); 793332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY); 803332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final Intent mOpenSaverSettings = settings(Settings.ACTION_BATTERY_SAVER_SETTINGS); 813332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 823332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private int mBatteryLevel; 833332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private int mBucket; 843332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private long mScreenOffTime; 853332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private int mShowing; 863332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 8765fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer private long mBucketDroppedNegativeTimeMs; 8865fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer 893332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private boolean mSaver; 903332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private boolean mWarning; 913332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private boolean mPlaySound; 923332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private boolean mInvalidCharger; 931bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock private SystemUIDialog mSaverConfirmation; 943332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 958de4311c51229efbe2f2d0afbf298982c5cadd96Jorim Jaggi public PowerNotificationWarnings(Context context, PhoneStatusBar phoneStatusBar) { 963332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mContext = context; 973332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 988d4e6cb06005a2ce994360340a6191f0690db8f4John Spurlock mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 993332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mReceiver.init(); 1003332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1013332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 1023332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 1033332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void dump(PrintWriter pw) { 1043332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock pw.print("mSaver="); pw.println(mSaver); 1053332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock pw.print("mWarning="); pw.println(mWarning); 1063332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock pw.print("mPlaySound="); pw.println(mPlaySound); 1073332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock pw.print("mInvalidCharger="); pw.println(mInvalidCharger); 1083332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock pw.print("mShowing="); pw.println(SHOWING_STRINGS[mShowing]); 1091bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock pw.print("mSaverConfirmation="); pw.println(mSaverConfirmation != null ? "not null" : null); 1103332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1113332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 1123332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 1133332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void update(int batteryLevel, int bucket, long screenOffTime) { 1143332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mBatteryLevel = batteryLevel; 11565fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer if (bucket >= 0) { 11665fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer mBucketDroppedNegativeTimeMs = 0; 11765fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer } else if (bucket < mBucket) { 11865fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer mBucketDroppedNegativeTimeMs = System.currentTimeMillis(); 11965fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer } 1203332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mBucket = bucket; 1213332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mScreenOffTime = screenOffTime; 1223332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1233332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 1243332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 1253332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void showSaverMode(boolean mode) { 1263332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mSaver = mode; 1271bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock if (mSaver && mSaverConfirmation != null) { 1281bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock mSaverConfirmation.dismiss(); 1291bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock } 1303332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock updateNotification(); 1313332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1323332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 1333332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private void updateNotification() { 13486c3de81ea324c5d2ebb2e0c396bba1c0250d4eeJohn Spurlock if (DEBUG) Slog.d(TAG, "updateNotification mWarning=" + mWarning + " mPlaySound=" 13586c3de81ea324c5d2ebb2e0c396bba1c0250d4eeJohn Spurlock + mPlaySound + " mSaver=" + mSaver + " mInvalidCharger=" + mInvalidCharger); 1363332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (mInvalidCharger) { 1373332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock showInvalidChargerNotification(); 1383332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mShowing = SHOWING_INVALID_CHARGER; 1393332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } else if (mWarning) { 1403332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock showWarningNotification(); 1413332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mShowing = SHOWING_WARNING; 1423332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } else if (mSaver) { 1433332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock showSaverNotification(); 1443332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mShowing = SHOWING_SAVER; 1453332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } else { 1463332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mNoMan.cancel(TAG_NOTIFICATION, ID_NOTIFICATION); 1473332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mShowing = SHOWING_NOTHING; 1483332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1493332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1503332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 1513332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private void showInvalidChargerNotification() { 1523332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final Notification.Builder nb = new Notification.Builder(mContext) 1533332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setSmallIcon(R.drawable.ic_power_low) 15465fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer .setWhen(0) 1553332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setShowWhen(false) 1563332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setOngoing(true) 1573332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setContentTitle(mContext.getString(R.string.invalid_charger_title)) 1583332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setContentText(mContext.getString(R.string.invalid_charger_text)) 1593332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setPriority(Notification.PRIORITY_MAX) 1603332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setCategory(Notification.CATEGORY_SYSTEM) 161a0388bb6ffaf22e4996081b4969dcc9d4056580bJohn Spurlock .setVisibility(Notification.VISIBILITY_PUBLIC) 162255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setColor(mContext.getResources().getColor( 163255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek com.android.internal.R.color.system_notification_accent_color)); 1643332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final Notification n = nb.build(); 1653332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (n.headsUpContentView != null) { 1663332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE); 1673332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1683332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.CURRENT); 1693332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1703332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 1713332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private void showWarningNotification() { 1723332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final int textRes = mSaver ? R.string.battery_low_percent_format_saver_started 1733332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock : R.string.battery_low_percent_format; 1743332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final Notification.Builder nb = new Notification.Builder(mContext) 1753332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setSmallIcon(R.drawable.ic_power_low) 17665fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer // Bump the notification when the bucket dropped. 17765fa0a923c2613cc2a10a97b9eee4d21ed744e0bChristoph Studer .setWhen(mBucketDroppedNegativeTimeMs) 1783332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setShowWhen(false) 1793332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setContentTitle(mContext.getString(R.string.battery_low_title)) 1803332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setContentText(mContext.getString(textRes, mBatteryLevel)) 1811bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock .setOnlyAlertOnce(true) 1823332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setPriority(Notification.PRIORITY_MAX) 1833332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setCategory(Notification.CATEGORY_SYSTEM) 184a0388bb6ffaf22e4996081b4969dcc9d4056580bJohn Spurlock .setVisibility(Notification.VISIBILITY_PUBLIC) 185255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setColor(mContext.getResources().getColor( 186255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek com.android.internal.R.color.battery_saver_mode_color)); 1873332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (hasBatterySettings()) { 1883332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock nb.setContentIntent(pendingBroadcast(ACTION_SHOW_BATTERY_SETTINGS)); 1893332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1901bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock if (!mSaver) { 19104c8fd33669cd54a97e488ee9737153e54692096John Spurlock nb.addAction(0, 1923332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mContext.getString(R.string.battery_saver_start_action), 1933332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock pendingBroadcast(ACTION_START_SAVER)); 1941bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock } else { 1951bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock addStopSaverAction(nb); 1963332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 1973332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (mPlaySound) { 1983332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock attachLowBatterySound(nb); 1997290d192c8a0c1a19ef3c298f2eeab63e82190a8John Spurlock mPlaySound = false; 2003332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2013332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final Notification n = nb.build(); 2023332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (n.headsUpContentView != null) { 2033332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock n.headsUpContentView.setViewVisibility(com.android.internal.R.id.right_icon, View.GONE); 2043332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2053332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, n, UserHandle.CURRENT); 2063332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2073332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2083332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private void showSaverNotification() { 2093332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final Notification.Builder nb = new Notification.Builder(mContext) 2103332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setSmallIcon(R.drawable.ic_power_saver) 2113332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setContentTitle(mContext.getString(R.string.battery_saver_notification_title)) 2123332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setContentText(mContext.getString(R.string.battery_saver_notification_text)) 2133332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setOngoing(true) 2143332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock .setShowWhen(false) 215a0388bb6ffaf22e4996081b4969dcc9d4056580bJohn Spurlock .setCategory(Notification.CATEGORY_SYSTEM) 216255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setVisibility(Notification.VISIBILITY_PUBLIC) 217255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek .setColor(mContext.getResources().getColor( 218255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek com.android.internal.R.color.battery_saver_mode_color)); 2191bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock addStopSaverAction(nb); 2203332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (hasSaverSettings()) { 2213332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock nb.setContentIntent(pendingActivity(mOpenSaverSettings)); 2223332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2233332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mNoMan.notifyAsUser(TAG_NOTIFICATION, ID_NOTIFICATION, nb.build(), UserHandle.CURRENT); 2243332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2253332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2261bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock private void addStopSaverAction(Notification.Builder nb) { 22704c8fd33669cd54a97e488ee9737153e54692096John Spurlock nb.addAction(0, 2281bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock mContext.getString(R.string.battery_saver_notification_action_text), 2291bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock pendingBroadcast(ACTION_STOP_SAVER)); 2301bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock } 2311bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock 2321bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock private void dismissSaverNotification() { 2331bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock if (mSaver) Slog.i(TAG, "dismissing saver notification"); 2341bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock mSaver = false; 2351bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock updateNotification(); 2361bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock } 2371bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock 2383332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private PendingIntent pendingActivity(Intent intent) { 2393332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock return PendingIntent.getActivityAsUser(mContext, 2403332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 0, intent, 0, null, UserHandle.CURRENT); 2413332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2423332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2433332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private PendingIntent pendingBroadcast(String action) { 2443332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock return PendingIntent.getBroadcastAsUser(mContext, 2453332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 0, new Intent(action), 0, UserHandle.CURRENT); 2463332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2473332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2483332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private static Intent settings(String action) { 2493332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock return new Intent(action).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 2503332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock | Intent.FLAG_ACTIVITY_MULTIPLE_TASK 2513332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 2523332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock | Intent.FLAG_ACTIVITY_NO_HISTORY 2533332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock | Intent.FLAG_ACTIVITY_CLEAR_TOP); 2543332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2553332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2563332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 2573332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public boolean isInvalidChargerWarningShowing() { 2583332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock return mInvalidCharger; 2593332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2603332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2613332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 2623332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void updateLowBatteryWarning() { 2633332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock updateNotification(); 2643332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2653332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2663332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 2673332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void dismissLowBatteryWarning() { 2683ff2de64f4b84ef60eba4fb3b23eef80ea841cddJohn Spurlock if (DEBUG) Slog.d(TAG, "dismissing low battery warning: level=" + mBatteryLevel); 2693332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock dismissLowBatteryNotification(); 2703332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2713332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2723332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private void dismissLowBatteryNotification() { 2733ff2de64f4b84ef60eba4fb3b23eef80ea841cddJohn Spurlock if (mWarning) Slog.i(TAG, "dismissing low battery notification"); 2743332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mWarning = false; 2753332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock updateNotification(); 2763332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2773332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2783332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private boolean hasBatterySettings() { 2793332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock return mOpenBatterySettings.resolveActivity(mContext.getPackageManager()) != null; 2803332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2813332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2823332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private boolean hasSaverSettings() { 2833332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock return mOpenSaverSettings.resolveActivity(mContext.getPackageManager()) != null; 2843332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2853332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2863332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 2873332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void showLowBatteryWarning(boolean playSound) { 2883332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock Slog.i(TAG, 2893332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock "show low battery warning: level=" + mBatteryLevel 2907290d192c8a0c1a19ef3c298f2eeab63e82190a8John Spurlock + " [" + mBucket + "] playSound=" + playSound); 2913332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mPlaySound = playSound; 2923332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mWarning = true; 2933332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock updateNotification(); 2943332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 2953332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2963332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private void attachLowBatterySound(Notification.Builder b) { 2973332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final ContentResolver cr = mContext.getContentResolver(); 2983332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 2993332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final int silenceAfter = Settings.Global.getInt(cr, 3003332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0); 3013332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime; 3023332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (silenceAfter > 0 3033332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock && mScreenOffTime > 0 3043332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock && offTime > silenceAfter) { 3053332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter 3063332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock + "ms): not waking up the user with low battery sound"); 3073332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock return; 3083332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3093332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3103332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (DEBUG) { 3113332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated 3123332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3133332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3143332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) { 3153332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final String soundPath = Settings.Global.getString(cr, 3163332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock Settings.Global.LOW_BATTERY_SOUND); 3173332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (soundPath != null) { 3183332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final Uri soundUri = Uri.parse("file://" + soundPath); 3193332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock if (soundUri != null) { 3201bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock b.setSound(soundUri, AUDIO_ATTRIBUTES); 3211bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock if (DEBUG) Slog.d(TAG, "playing sound " + soundUri); 3223332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3233332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3243332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3253332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3263332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3273332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 3283332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void dismissInvalidChargerWarning() { 329eb44a7de47a994f93398b5880cd9f2d6badc6e3aJohn Spurlock dismissInvalidChargerNotification(); 330eb44a7de47a994f93398b5880cd9f2d6badc6e3aJohn Spurlock } 331eb44a7de47a994f93398b5880cd9f2d6badc6e3aJohn Spurlock 332eb44a7de47a994f93398b5880cd9f2d6badc6e3aJohn Spurlock private void dismissInvalidChargerNotification() { 3333ff2de64f4b84ef60eba4fb3b23eef80ea841cddJohn Spurlock if (mInvalidCharger) Slog.i(TAG, "dismissing invalid charger notification"); 3343332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mInvalidCharger = false; 3353332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock updateNotification(); 3363332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3373332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3383332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 3393332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void showInvalidChargerWarning() { 3403332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mInvalidCharger = true; 3413332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock updateNotification(); 3423332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3433332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3443332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private void showStartSaverConfirmation() { 3451bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock if (mSaverConfirmation != null) return; 3461bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock final SystemUIDialog d = new SystemUIDialog(mContext); 3471bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock d.setTitle(R.string.battery_saver_confirmation_title); 3481bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock d.setMessage(com.android.internal.R.string.battery_saver_description); 3491bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock d.setNegativeButton(android.R.string.cancel, null); 3501bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock d.setPositiveButton(R.string.battery_saver_confirmation_ok, mStartSaverMode); 3511bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock d.setShowForAllUsers(true); 3521bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock d.setOnDismissListener(new OnDismissListener() { 3531bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock @Override 3541bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock public void onDismiss(DialogInterface dialog) { 3551bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock mSaverConfirmation = null; 3561bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock } 3571bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock }); 3583332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock d.show(); 3591bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock mSaverConfirmation = d; 3603332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3613332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3628d4e6cb06005a2ce994360340a6191f0690db8f4John Spurlock private void setSaverMode(boolean mode) { 3638d4e6cb06005a2ce994360340a6191f0690db8f4John Spurlock mPowerMan.setPowerSaveMode(mode); 3643332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3653332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3663332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final class Receiver extends BroadcastReceiver { 3673332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3683332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void init() { 3693332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock IntentFilter filter = new IntentFilter(); 3703332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock filter.addAction(ACTION_SHOW_BATTERY_SETTINGS); 3713332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock filter.addAction(ACTION_START_SAVER); 3721bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock filter.addAction(ACTION_STOP_SAVER); 3733332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mContext.registerReceiver(this, filter, null, mHandler); 3743332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3753332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3763332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 3773332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void onReceive(Context context, Intent intent) { 3783332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock final String action = intent.getAction(); 379eb44a7de47a994f93398b5880cd9f2d6badc6e3aJohn Spurlock Slog.i(TAG, "Received " + action); 38086c3de81ea324c5d2ebb2e0c396bba1c0250d4eeJohn Spurlock if (action.equals(ACTION_SHOW_BATTERY_SETTINGS)) { 3813332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock dismissLowBatteryNotification(); 3823332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock mContext.startActivityAsUser(mOpenBatterySettings, UserHandle.CURRENT); 3833332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } else if (action.equals(ACTION_START_SAVER)) { 3843332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock dismissLowBatteryNotification(); 3853332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock showStartSaverConfirmation(); 3861bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock } else if (action.equals(ACTION_STOP_SAVER)) { 3871bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock dismissSaverNotification(); 3881bb480a3a4ce2ce63c5d09fa7f5cc38ec160ebf4John Spurlock dismissLowBatteryNotification(); 3898d4e6cb06005a2ce994360340a6191f0690db8f4John Spurlock setSaverMode(false); 3903332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3913332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3923332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 3933332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock 3943332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock private final OnClickListener mStartSaverMode = new OnClickListener() { 3953332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 3963332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void onClick(DialogInterface dialog, int which) { 3973332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock AsyncTask.execute(new Runnable() { 3983332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock @Override 3993332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock public void run() { 4008d4e6cb06005a2ce994360340a6191f0690db8f4John Spurlock setSaverMode(true); 4013332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 4023332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock }); 4033332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock } 4043332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock }; 4053332ba54ae85df14d761447d86d2aa19d448ce11John Spurlock} 406