Implement reminder power dialog and invalid charger dialog.

Bug: 2510318
Bug: 2974431
Change-Id: I92eb419eeffb657e5572a35a490735a96b303d6b
This commit is contained in:
Joe Onorato
2010-10-27 15:32:23 -07:00
parent 31b2610dee
commit 4ca7f1e281
5 changed files with 235 additions and 85 deletions

View File

@@ -87,7 +87,7 @@ public class BatteryManager {
/**
* Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
* Boolean value set to true if an unsupported charger is attached
* Int value set to nonzero if an unsupported charger is attached
* to the device.
* {@hide}
*/

View File

@@ -290,6 +290,11 @@
<bool name="config_use_strict_phone_number_comparation">false</bool>
<!-- Display low battery warning when battery level dips to this value.
Also, the battery stats are flushed to disk when we hit this level. -->
<integer name="config_criticalBatteryWarningLevel">4</integer>
<!-- Display low battery warning when battery level dips to this value -->
<!-- Display low battery warning when battery level dips to this value -->
<integer name="config_lowBatteryWarningLevel">15</integer>

View File

@@ -53,11 +53,17 @@
<string name="battery_low_title">Please connect charger</string>
<!-- When the battery is low, this is displayed to the user in a dialog. The subtitle of the low battery alert. -->
<string name="battery_low_subtitle">The battery is getting low:</string>
<string name="battery_low_subtitle">The battery is getting low.</string>
<!-- A message that appears when the battery level is getting low in a dialog. This is appened to the subtitle of the low battery alert. -->
<string name="battery_low_percent_format"><xliff:g id="number">%d%%</xliff:g>
or less remaining.</string>
<!-- A message that appears when the battery level is getting low in a dialog. This is
appened to the subtitle of the low battery alert. -->
<string name="battery_low_percent_format"><xliff:g id="number">%d%%</xliff:g> remaining</string>
<!-- A message that appears when a USB charger is plugged in and the device does not
support charging on it. That is, a charger that fits into the USB port and goes into
a wall socket, not into a computer. (This happens because some devices require more
current than the USB spec allows. -->
<string name="invalid_charger">USB charging not supported.\nUse only the supplied charger.</string>
<!-- When the battery is low, this is the label of the button to go to the
power usage activity to find out what drained the battery. -->

View File

@@ -28,6 +28,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Handler;
import android.media.AudioManager;
import android.media.Ringtone;
@@ -46,32 +47,116 @@ public class PowerUI extends SystemUI {
Handler mHandler = new Handler();
int mBatteryLevel = 100;
int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
int mPlugType = 0;
int mInvalidCharger = 0;
int mLowBatteryAlertCloseLevel;
int[] mLowBatteryReminderLevels = new int[2];
AlertDialog mInvalidChargerDialog;
AlertDialog mLowBatteryDialog;
int mBatteryLevel;
TextView mBatteryLevelTextView;
public void start() {
mLowBatteryAlertCloseLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryCloseWarningLevel);
mLowBatteryReminderLevels[0] = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
mLowBatteryReminderLevels[1] = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
// Register for Intent broadcasts for...
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(Intent.ACTION_BATTERY_LOW);
filter.addAction(Intent.ACTION_BATTERY_OKAY);
filter.addAction(Intent.ACTION_POWER_CONNECTED);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
}
/**
* Buckets the battery level.
*
* The code in this function is a little weird because I couldn't comprehend
* the bucket going up when the battery level was going down. --joeo
*
* 1 means that the battery is "ok"
* 0 means that the battery is between "ok" and what we should warn about.
* less than 0 means that the battery is low
*/
private int findBatteryLevelBucket(int level) {
if (level >= mLowBatteryAlertCloseLevel) {
return 1;
}
if (level >= mLowBatteryReminderLevels[0]) {
return 0;
}
final int N = mLowBatteryReminderLevels.length;
for (int i=N-1; i>=0; i--) {
if (level <= mLowBatteryReminderLevels[i]) {
return -1-i;
}
}
throw new RuntimeException("not possible!");
}
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
mBatteryLevel = intent.getIntExtra("level", -1);
} else if (action.equals(Intent.ACTION_BATTERY_LOW)) {
showLowBatteryWarning();
} else if (action.equals(Intent.ACTION_BATTERY_OKAY)
|| action.equals(Intent.ACTION_POWER_CONNECTED)) {
if (mLowBatteryDialog != null) {
mLowBatteryDialog.dismiss();
final int oldBatteryLevel = mBatteryLevel;
mBatteryLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 100);
final int oldBatteryStatus = mBatteryStatus;
mBatteryStatus = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
final int oldPlugType = mPlugType;
mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
final int oldInvalidCharger = mInvalidCharger;
mInvalidCharger = intent.getIntExtra(BatteryManager.EXTRA_INVALID_CHARGER, 0);
final boolean plugged = mPlugType != 0;
final boolean oldPlugged = oldPlugType != 0;
int oldBucket = findBatteryLevelBucket(oldBatteryLevel);
int bucket = findBatteryLevelBucket(mBatteryLevel);
if (false) {
Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
+ " .. " + mLowBatteryReminderLevels[0]
+ " .. " + mLowBatteryReminderLevels[1]);
Slog.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
Slog.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
Slog.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
Slog.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
Slog.d(TAG, "bucket " + oldBucket + " --> " + bucket);
Slog.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
}
if (oldInvalidCharger == 0 && mInvalidCharger != 0) {
Slog.d(TAG, "showing invalid charger warning");
showInvalidChargerDialog();
return;
} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
Slog.d(TAG, "closing invalid charger warning");
dismissInvalidChargerDialog();
} else if (mInvalidChargerDialog != null) {
// if invalid charger is showing, don't show low battery
return;
}
if (!plugged
&& (bucket < oldBucket || oldPlugged)
&& mBatteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN
&& bucket < 0) {
Slog.d(TAG, "showing low battery warning: level=" + mBatteryLevel);
showLowBatteryWarning();
} else if (plugged || (bucket > oldBucket && bucket > 0)) {
Slog.d(TAG, "closing low battery warning: level=" + mBatteryLevel);
dismissLowBatteryWarning();
} else if (mBatteryLevelTextView != null) {
showLowBatteryWarning();
}
} else {
Slog.w(TAG, "unknown intent: " + intent);
@@ -79,6 +164,12 @@ public class PowerUI extends SystemUI {
}
};
void dismissLowBatteryWarning() {
if (mLowBatteryDialog != null) {
mLowBatteryDialog.dismiss();
}
}
void showLowBatteryWarning() {
CharSequence levelText = mContext.getString(
R.string.battery_low_percent_format, mBatteryLevel);
@@ -98,25 +189,30 @@ public class PowerUI extends SystemUI {
b.setIcon(android.R.drawable.ic_dialog_alert);
b.setPositiveButton(android.R.string.ok, null);
final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_NO_HISTORY);
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
b.setNegativeButton(R.string.battery_low_why,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mContext.startActivity(intent);
if (mLowBatteryDialog != null) {
mLowBatteryDialog.dismiss();
}
final Intent intent = new Intent(Intent.ACTION_POWER_USAGE_SUMMARY);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_NO_HISTORY);
if (intent.resolveActivity(mContext.getPackageManager()) != null) {
b.setNegativeButton(R.string.battery_low_why,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
mContext.startActivity(intent);
if (mLowBatteryDialog != null) {
mLowBatteryDialog.dismiss();
}
});
}
}
});
}
AlertDialog d = b.create();
d.setOnDismissListener(mLowBatteryListener);
d.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
mLowBatteryDialog = null;
mBatteryLevelTextView = null;
}
});
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
d.show();
mLowBatteryDialog = d;
@@ -141,45 +237,53 @@ if (false) { // getRingtone ANRs
}
}
private DialogInterface.OnDismissListener mLowBatteryListener
= new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
mLowBatteryDialog = null;
mBatteryLevelTextView = null;
void dismissInvalidChargerDialog() {
if (mInvalidChargerDialog != null) {
mInvalidChargerDialog.dismiss();
}
};
}
void showInvalidChargerDialog() {
dismissLowBatteryWarning();
AlertDialog.Builder b = new AlertDialog.Builder(mContext);
b.setCancelable(true);
b.setMessage(mContext.getString(R.string.invalid_charger));
b.setIcon(android.R.drawable.ic_dialog_alert);
b.setPositiveButton(android.R.string.ok, null);
AlertDialog d = b.create();
d.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(DialogInterface dialog) {
mInvalidChargerDialog = null;
mBatteryLevelTextView = null;
}
});
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
d.show();
mInvalidChargerDialog = d;
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (false) {
pw.println("args=" + Arrays.toString(args));
}
if (args == null || args.length == 0) {
pw.print("mLowBatteryDialog=");
pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
pw.print("mBatteryLevel=");
pw.println(Integer.toString(mBatteryLevel));
}
// DO NOT SUBMIT with this turned on.
if (false) {
if (args.length == 3 && "level".equals(args[1])) {
try {
final int level = Integer.parseInt(args[2]);
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.putExtra("level", level);
mIntentReceiver.onReceive(mContext, intent);
} catch (NumberFormatException ex) {
pw.println(ex);
}
} else if (args.length == 2 && "low".equals(args[1])) {
Intent intent = new Intent(Intent.ACTION_BATTERY_LOW);
mIntentReceiver.onReceive(mContext, intent);
} else if (args.length == 2 && "ok".equals(args[1])) {
Intent intent = new Intent(Intent.ACTION_BATTERY_OKAY);
mIntentReceiver.onReceive(mContext, intent);
}
}
pw.print("mLowBatteryAlertCloseLevel=");
pw.println(mLowBatteryAlertCloseLevel);
pw.print("mLowBatteryReminderLevels=");
pw.println(Arrays.toString(mLowBatteryReminderLevels));
pw.print("mInvalidChargerDialog=");
pw.println(mInvalidChargerDialog == null ? "null" : mInvalidChargerDialog.toString());
pw.print("mLowBatteryDialog=");
pw.println(mLowBatteryDialog == null ? "null" : mLowBatteryDialog.toString());
pw.print("mBatteryLevel=");
pw.println(Integer.toString(mBatteryLevel));
pw.print("mBatteryStatus=");
pw.println(Integer.toString(mBatteryStatus));
pw.print("mPlugType=");
pw.println(Integer.toString(mPlugType));
pw.print("mInvalidCharger=");
pw.println(Integer.toString(mInvalidCharger));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
}
}

View File

@@ -43,6 +43,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
/**
@@ -76,7 +77,7 @@ class BatteryService extends Binder {
// Used locally for determining when to make a last ditch effort to log
// discharge stats before the device dies.
private static final int CRITICAL_BATTERY_LEVEL = 4;
private int mCriticalBatteryLevel;
private static final int DUMP_MAX_LENGTH = 24 * 1024;
private static final String[] DUMPSYS_ARGS = new String[] { "--checkin", "-u" };
@@ -100,7 +101,7 @@ class BatteryService extends Binder {
private int mBatteryTemperature;
private String mBatteryTechnology;
private boolean mBatteryLevelCritical;
private boolean mInvalidCharger;
private int mInvalidCharger;
private int mLastBatteryStatus;
private int mLastBatteryHealth;
@@ -109,7 +110,7 @@ class BatteryService extends Binder {
private int mLastBatteryVoltage;
private int mLastBatteryTemperature;
private boolean mLastBatteryLevelCritical;
private boolean mLastInvalidCharger;
private int mLastInvalidCharger;
private int mLowBatteryWarningLevel;
private int mLowBatteryCloseWarningLevel;
@@ -129,6 +130,8 @@ class BatteryService extends Binder {
mLed = new Led(context, lights);
mBatteryStats = BatteryStatsService.getService();
mCriticalBatteryLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
mLowBatteryWarningLevel = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lowBatteryWarningLevel);
mLowBatteryCloseWarningLevel = mContext.getResources().getInteger(
@@ -183,7 +186,7 @@ class BatteryService extends Binder {
private UEventObserver mInvalidChargerObserver = new UEventObserver() {
@Override
public void onUEvent(UEventObserver.UEvent event) {
boolean invalidCharger = "1".equals(event.get("SWITCH_STATE"));
int invalidCharger = "1".equals(event.get("SWITCH_STATE")) ? 1 : 0;
if (mInvalidCharger != invalidCharger) {
mInvalidCharger = invalidCharger;
update();
@@ -228,11 +231,14 @@ class BatteryService extends Binder {
private synchronized final void update() {
native_update();
processValues();
}
private void processValues() {
boolean logOutlier = false;
long dischargeDuration = 0;
mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
mBatteryLevelCritical = mBatteryLevel <= mCriticalBatteryLevel;
if (mAcOnline) {
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
} else if (mUsbOnline) {
@@ -384,8 +390,8 @@ class BatteryService extends Binder {
intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mBatteryTechnology);
intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger);
if (false) {
Slog.d(TAG, "updateBattery level:" + mBatteryLevel +
if (true) {
Slog.d(TAG, "level:" + mBatteryLevel +
" scale:" + BATTERY_SCALE + " status:" + mBatteryStatus +
" health:" + mBatteryHealth + " present:" + mBatteryPresent +
" voltage: " + mBatteryVoltage +
@@ -487,18 +493,47 @@ class BatteryService extends Binder {
return;
}
synchronized (this) {
pw.println("Current Battery Service state:");
pw.println(" AC powered: " + mAcOnline);
pw.println(" USB powered: " + mUsbOnline);
pw.println(" status: " + mBatteryStatus);
pw.println(" health: " + mBatteryHealth);
pw.println(" present: " + mBatteryPresent);
pw.println(" level: " + mBatteryLevel);
pw.println(" scale: " + BATTERY_SCALE);
pw.println(" voltage:" + mBatteryVoltage);
pw.println(" temperature: " + mBatteryTemperature);
pw.println(" technology: " + mBatteryTechnology);
if (args == null || args.length == 0) {
synchronized (this) {
pw.println("Current Battery Service state:");
pw.println(" AC powered: " + mAcOnline);
pw.println(" USB powered: " + mUsbOnline);
pw.println(" status: " + mBatteryStatus);
pw.println(" health: " + mBatteryHealth);
pw.println(" present: " + mBatteryPresent);
pw.println(" level: " + mBatteryLevel);
pw.println(" scale: " + BATTERY_SCALE);
pw.println(" voltage:" + mBatteryVoltage);
pw.println(" temperature: " + mBatteryTemperature);
pw.println(" technology: " + mBatteryTechnology);
}
} else if (false) {
// DO NOT SUBMIT WITH THIS TURNED ON
if (args.length == 3 && "set".equals(args[0])) {
String key = args[1];
String value = args[2];
try {
boolean update = true;
if ("ac".equals(key)) {
mAcOnline = Integer.parseInt(value) != 0;
} else if ("usb".equals(key)) {
mUsbOnline = Integer.parseInt(value) != 0;
} else if ("status".equals(key)) {
mBatteryStatus = Integer.parseInt(value);
} else if ("level".equals(key)) {
mBatteryLevel = Integer.parseInt(value);
} else if ("invalid".equals(key)) {
mInvalidCharger = Integer.parseInt(value);
} else {
update = false;
}
if (update) {
processValues();
}
} catch (NumberFormatException ex) {
pw.println("Bad value: " + value);
}
}
}
}