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