Don't wake users up with low battery sounds.
Battery sounds will always play when the screen is on, and
then for Settings.Global.LOW_BATTERY_SOUND_TIMEOUT
milliseconds after the screen goes off. After that, low
battery alerts will be pushed out the airlock until the
screen comes back on again.
If battery sounds are suppressed via this mechanism you'll
see a log line like:
V/PowerUI ( 3161): screen off too long (5779ms, limit
5000ms): not waking up the user with low battery sound
The default value of LOW_BATTERY_SOUND_TIMEOUT is a settings
provider resource: R.integer.def_low_battery_sound_timeout.
Bug: 10487557
Change-Id: Iddd42038aa630631dc8f1833f20fcc5a0c646681
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 50777fd..6f1c6ba 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5920,6 +5920,16 @@
public static final String DEVELOPMENT_FORCE_RTL = "debug.force_rtl";
/**
+ * Milliseconds after screen-off after which low battery sounds will be silenced.
+ *
+ * If zero, battery sounds will always play.
+ * Defaults to @integer/def_low_battery_sound_timeout in SettingsProvider.
+ *
+ * @hide
+ */
+ public static final String LOW_BATTERY_SOUND_TIMEOUT = "low_battery_sound_timeout";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index bfb0931..a1d8f22 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -168,4 +168,9 @@
<!-- Default for Settings.Secure.USER_SETUP_COMPLETE -->
<bool name="def_user_setup_complete">false</bool>
+
+ <!-- Default for Settings.Global.LOW_BATTERY_SOUND_TIMEOUT.
+ 0 means no timeout; battery sounds will always play
+ >0 is milliseconds of screen-off time after which battery sounds will not play -->
+ <integer name="def_low_battery_sound_timeout">0</integer>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 120b28f2..09c21f3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -72,7 +72,7 @@
// database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
// is properly propagated through your change. Not doing so will result in a loss of user
// settings.
- private static final int DATABASE_VERSION = 97;
+ private static final int DATABASE_VERSION = 98;
private Context mContext;
private int mUserHandle;
@@ -1541,6 +1541,24 @@
upgradeVersion = 97;
}
+ if (upgradeVersion == 97) {
+ if (mUserHandle == UserHandle.USER_OWNER) {
+ db.beginTransaction();
+ SQLiteStatement stmt = null;
+ try {
+ stmt = db.compileStatement("INSERT OR REPLACE INTO global(name,value)"
+ + " VALUES(?,?);");
+ loadIntegerSetting(stmt, Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
+ R.integer.def_low_battery_sound_timeout);
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ if (stmt != null) stmt.close();
+ }
+ }
+ upgradeVersion = 98;
+ }
+
// *** Remember to update DATABASE_VERSION above!
if (upgradeVersion != currentVersion) {
@@ -2253,6 +2271,9 @@
CdmaSubscriptionSourceManager.PREFERRED_CDMA_SUBSCRIPTION);
loadSetting(stmt, Settings.Global.CDMA_SUBSCRIPTION_MODE, type);
+ loadIntegerSetting(stmt, Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
+ R.integer.def_low_battery_sound_timeout);
+
// --- New global settings start here
} finally {
if (stmt != null) stmt.close();
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index a08eb9b..28c2772 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -29,9 +29,11 @@
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Handler;
+import android.os.PowerManager;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
-import android.util.Log;
+import android.util.Slog;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
@@ -62,6 +64,8 @@
AlertDialog mLowBatteryDialog;
TextView mBatteryLevelTextView;
+ private long mScreenOffTime = -1;
+
public void start() {
mLowBatteryAlertCloseLevel = mContext.getResources().getInteger(
@@ -71,10 +75,14 @@
mLowBatteryReminderLevels[1] = mContext.getResources().getInteger(
com.android.internal.R.integer.config_criticalBatteryWarningLevel);
+ final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
+
// Register for Intent broadcasts for...
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- filter.addAction(Intent.ACTION_POWER_CONNECTED);
+ filter.addAction(Intent.ACTION_SCREEN_OFF);
+ filter.addAction(Intent.ACTION_SCREEN_ON);
mContext.registerReceiver(mIntentReceiver, filter, null, mHandler);
}
@@ -126,19 +134,19 @@
int bucket = findBatteryLevelBucket(mBatteryLevel);
if (DEBUG) {
- Log.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
+ Slog.d(TAG, "buckets ....." + mLowBatteryAlertCloseLevel
+ " .. " + mLowBatteryReminderLevels[0]
+ " .. " + mLowBatteryReminderLevels[1]);
- Log.d(TAG, "level " + oldBatteryLevel + " --> " + mBatteryLevel);
- Log.d(TAG, "status " + oldBatteryStatus + " --> " + mBatteryStatus);
- Log.d(TAG, "plugType " + oldPlugType + " --> " + mPlugType);
- Log.d(TAG, "invalidCharger " + oldInvalidCharger + " --> " + mInvalidCharger);
- Log.d(TAG, "bucket " + oldBucket + " --> " + bucket);
- Log.d(TAG, "plugged " + oldPlugged + " --> " + plugged);
+ 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) {
- Log.d(TAG, "showing invalid charger warning");
+ Slog.d(TAG, "showing invalid charger warning");
showInvalidChargerDialog();
return;
} else if (oldInvalidCharger != 0 && mInvalidCharger == 0) {
@@ -163,21 +171,25 @@
} else if (mBatteryLevelTextView != null) {
showLowBatteryWarning();
}
+ } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+ mScreenOffTime = SystemClock.elapsedRealtime();
+ } else if (Intent.ACTION_SCREEN_ON.equals(action)) {
+ mScreenOffTime = -1;
} else {
- Log.w(TAG, "unknown intent: " + intent);
+ Slog.w(TAG, "unknown intent: " + intent);
}
}
};
void dismissLowBatteryWarning() {
if (mLowBatteryDialog != null) {
- Log.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
+ Slog.i(TAG, "closing low battery warning: level=" + mBatteryLevel);
mLowBatteryDialog.dismiss();
}
}
void showLowBatteryWarning() {
- Log.i(TAG,
+ Slog.i(TAG,
((mBatteryLevelTextView == null) ? "showing" : "updating")
+ " low battery warning: level=" + mBatteryLevel
+ " [" + findBatteryLevelBucket(mBatteryLevel) + "]");
@@ -233,11 +245,23 @@
}
void playLowBatterySound() {
- if (DEBUG) {
- Log.i(TAG, "playing low battery sound. WOMP-WOMP!");
+ final ContentResolver cr = mContext.getContentResolver();
+
+ final int silenceAfter = Settings.Global.getInt(cr,
+ Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0);
+ final long offTime = SystemClock.elapsedRealtime() - mScreenOffTime;
+ if (silenceAfter > 0
+ && mScreenOffTime > 0
+ && offTime > silenceAfter) {
+ Slog.i(TAG, "screen off too long (" + offTime + "ms, limit " + silenceAfter
+ + "ms): not waking up the user with low battery sound");
+ return;
}
- final ContentResolver cr = mContext.getContentResolver();
+ if (DEBUG) {
+ Slog.d(TAG, "playing low battery sound. pick-a-doop!"); // WOMP-WOMP is deprecated
+ }
+
if (Settings.Global.getInt(cr, Settings.Global.POWER_SOUNDS_ENABLED, 1) == 1) {
final String soundPath = Settings.Global.getString(cr,
Settings.Global.LOW_BATTERY_SOUND);
@@ -261,7 +285,7 @@
}
void showInvalidChargerDialog() {
- Log.d(TAG, "showing invalid charger dialog");
+ Slog.d(TAG, "showing invalid charger dialog");
dismissLowBatteryWarning();
@@ -301,6 +325,17 @@
pw.println(Integer.toString(mPlugType));
pw.print("mInvalidCharger=");
pw.println(Integer.toString(mInvalidCharger));
+ pw.print("mScreenOffTime=");
+ pw.print(mScreenOffTime);
+ if (mScreenOffTime >= 0) {
+ pw.print(" (");
+ pw.print(SystemClock.elapsedRealtime() - mScreenOffTime);
+ pw.print(" ago)");
+ }
+ pw.println();
+ pw.print("soundTimeout=");
+ pw.println(Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
}