From 14272302a8b635bd8e9267c1411d0a7ef11bff45 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 10 Jun 2014 23:13:02 -0700 Subject: [PATCH] Implement control of auto power save mode. Follow the setting for auto power save mode in both battery service and battery UI. Default level is 15 when setting is not set; otherwise it is whatever the setting gives, with 0 meaning auto battery save is off. Change how we define the "turn off warn" level to be an adjustment from the warn level, so we can have a good value for whatever auto setting is set. Fix power manager to never go in to power save mode when plugged in, even if the user has manually turned it on. Add new delete option to settings command, because I needed it for testing. Change-Id: I512b691df84399d50b8e751fd50732c6093ebe85 --- .../commands/settings/SettingsCmd.java | 34 ++++++++- core/java/android/provider/Settings.java | 1 + core/res/res/values/config.xml | 7 +- core/res/res/values/symbols.xml | 2 +- .../com/android/systemui/power/PowerUI.java | 47 +++++++++--- .../com/android/server/BatteryService.java | 72 +++++++++++++++---- .../server/power/PowerManagerService.java | 21 +++++- 7 files changed, 154 insertions(+), 30 deletions(-) diff --git a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java index dce0a758b0b55..e6847a9946cf8 100644 --- a/cmds/settings/src/com/android/commands/settings/SettingsCmd.java +++ b/cmds/settings/src/com/android/commands/settings/SettingsCmd.java @@ -20,6 +20,7 @@ import android.app.ActivityManagerNative; import android.app.IActivityManager; import android.app.IActivityManager.ContentProviderHolder; import android.content.IContentProvider; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -33,7 +34,8 @@ public final class SettingsCmd { enum CommandVerb { UNSPECIFIED, GET, - PUT + PUT, + DELETE } static String[] mArgs; @@ -74,6 +76,8 @@ public final class SettingsCmd { mVerb = CommandVerb.GET; } else if ("put".equalsIgnoreCase(arg)) { mVerb = CommandVerb.PUT; + } else if ("delete".equalsIgnoreCase(arg)) { + mVerb = CommandVerb.DELETE; } else { // invalid System.err.println("Invalid command: " + arg); @@ -87,7 +91,7 @@ public final class SettingsCmd { break; // invalid } mTable = arg.toLowerCase(); - } else if (mVerb == CommandVerb.GET) { + } else if (mVerb == CommandVerb.GET || mVerb == CommandVerb.DELETE) { mKey = arg; if (mNextArg >= mArgs.length) { valid = true; @@ -136,6 +140,10 @@ public final class SettingsCmd { case PUT: putForUser(provider, mUser, mTable, mKey, mValue); break; + case DELETE: + System.out.println("Deleted " + + deleteForUser(provider, mUser, mTable, mKey) + " rows"); + break; default: System.err.println("Unspecified command"); break; @@ -211,9 +219,31 @@ public final class SettingsCmd { } } + int deleteForUser(IContentProvider provider, int userHandle, + final String table, final String key) { + Uri targetUri; + if ("system".equals(table)) targetUri = Settings.System.getUriFor(key); + else if ("secure".equals(table)) targetUri = Settings.Secure.getUriFor(key); + else if ("global".equals(table)) targetUri = Settings.Global.getUriFor(key); + else { + System.err.println("Invalid table; no delete performed"); + throw new IllegalArgumentException("Invalid table " + table); + } + + int num = 0; + try { + num = provider.delete(null, targetUri, null, null); + } catch (RemoteException e) { + System.err.println("Can't clear key " + key + " in " + table + " for user " + + userHandle); + } + return num; + } + private static void printUsage() { System.err.println("usage: settings [--user NUM] get namespace key"); System.err.println(" settings [--user NUM] put namespace key value"); + System.err.println(" settings [--user NUM] delete namespace key"); System.err.println("\n'namespace' is one of {system, secure, global}, case-insensitive"); System.err.println("If '--user NUM' is not given, the operations are performed on the owner user."); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index bd988a6f5e60d..55c66baec2acd 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6029,6 +6029,7 @@ public final class Settings { /** * Battery level [1-99] at which low power mode automatically turns on. + * If 0, it will not automatically turn on. * @hide */ public static final String LOW_POWER_MODE_TRIGGER_LEVEL = "low_power_trigger_level"; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 59d01dea40d45..27ac6c30b1808 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -595,10 +595,11 @@ 680 - 20 + 15 - - 25 + + 5 #ffffffff diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index bfdb8a444385d..578d91b5ef345 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1509,7 +1509,7 @@ - + diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java index 0fb0f8b02c65f..192ba5722bd0e 100644 --- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java +++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java @@ -17,13 +17,16 @@ package com.android.systemui.power; import android.content.BroadcastReceiver; +import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.database.ContentObserver; 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.Slog; @@ -54,17 +57,22 @@ public class PowerUI extends SystemUI { 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); - final PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mScreenOffTime = pm.isScreenOn() ? -1 : SystemClock.elapsedRealtime(); mWarnings = new PowerDialogWarnings(mContext); + ContentObserver obs = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + updateBatteryWarningLevels(); + } + }; + final ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(Settings.Global.getUriFor( + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL), + false, obs, UserHandle.USER_ALL); + updateBatteryWarningLevels(); + // Register for Intent broadcasts for... IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_BATTERY_CHANGED); @@ -73,6 +81,29 @@ public class PowerUI extends SystemUI { mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); } + void updateBatteryWarningLevels() { + int critLevel = mContext.getResources().getInteger( + com.android.internal.R.integer.config_criticalBatteryWarningLevel); + + final ContentResolver resolver = mContext.getContentResolver(); + int defWarnLevel = mContext.getResources().getInteger( + com.android.internal.R.integer.config_lowBatteryWarningLevel); + int warnLevel = Settings.Global.getInt(resolver, + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel); + if (warnLevel == 0) { + warnLevel = defWarnLevel; + } + if (warnLevel < critLevel) { + warnLevel = critLevel; + } + + mLowBatteryReminderLevels[0] = warnLevel; + mLowBatteryReminderLevels[1] = critLevel; + mLowBatteryAlertCloseLevel = mLowBatteryReminderLevels[0] + + mContext.getResources().getInteger( + com.android.internal.R.integer.config_lowBatteryCloseWarningBump); + } + /** * Buckets the battery level. * @@ -87,7 +118,7 @@ public class PowerUI extends SystemUI { if (level >= mLowBatteryAlertCloseLevel) { return 1; } - if (level >= mLowBatteryReminderLevels[0]) { + if (level > mLowBatteryReminderLevels[0]) { return 0; } final int N = mLowBatteryReminderLevels.length; diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index fe5c2ef3ad06f..aeb195fe945e4 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -16,6 +16,7 @@ package com.android.server; +import android.database.ContentObserver; import android.os.BatteryStats; import com.android.internal.app.IBatteryStats; import com.android.server.am.BatteryStatsService; @@ -149,8 +150,8 @@ public final class BatteryService extends Binder { com.android.internal.R.integer.config_criticalBatteryWarningLevel); mLowBatteryWarningLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_lowBatteryWarningLevel); - mLowBatteryCloseWarningLevel = mContext.getResources().getInteger( - com.android.internal.R.integer.config_lowBatteryCloseWarningLevel); + mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger( + com.android.internal.R.integer.config_lowBatteryCloseWarningBump); mShutdownBatteryTemperature = mContext.getResources().getInteger( com.android.internal.R.integer.config_shutdownBatteryTemperature); @@ -173,11 +174,39 @@ public final class BatteryService extends Binder { void systemReady() { // check our power situation now that it is safe to display the shutdown dialog. synchronized (mLock) { - shutdownIfNoPowerLocked(); - shutdownIfOverTempLocked(); + ContentObserver obs = new ContentObserver(mHandler) { + @Override + public void onChange(boolean selfChange) { + synchronized (mLock) { + updateBatteryWarningLevelLocked(); + } + } + }; + final ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(Settings.Global.getUriFor( + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL), + false, obs, UserHandle.USER_ALL); + updateBatteryWarningLevelLocked(); } } + void updateBatteryWarningLevelLocked() { + final ContentResolver resolver = mContext.getContentResolver(); + int defWarnLevel = mContext.getResources().getInteger( + com.android.internal.R.integer.config_lowBatteryWarningLevel); + mLowBatteryWarningLevel = Settings.Global.getInt(resolver, + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, defWarnLevel); + if (mLowBatteryWarningLevel == 0) { + mLowBatteryWarningLevel = defWarnLevel; + } + if (mLowBatteryWarningLevel < mCriticalBatteryLevel) { + mLowBatteryWarningLevel = mCriticalBatteryLevel; + } + mLowBatteryCloseWarningLevel = mLowBatteryWarningLevel + mContext.getResources().getInteger( + com.android.internal.R.integer.config_lowBatteryCloseWarningBump); + processValuesLocked(true); + } + /** * Returns true if the device is plugged into any of the specified plug types. */ @@ -232,7 +261,7 @@ public final class BatteryService extends Binder { } } - public boolean isBatteryLowLocked() { + public boolean shouldSendBatteryLowLocked() { final boolean plugged = mPlugType != BATTERY_PLUGGED_NONE; final boolean oldPlugged = mLastPlugType != BATTERY_PLUGGED_NONE; @@ -299,14 +328,14 @@ public final class BatteryService extends Binder { if (!mUpdatesStopped) { mBatteryProps = props; // Process the new values. - processValuesLocked(); + processValuesLocked(false); } else { mLastBatteryProps.set(props); } } } - private void processValuesLocked() { + private void processValuesLocked(boolean force) { boolean logOutlier = false; long dischargeDuration = 0; @@ -349,14 +378,14 @@ public final class BatteryService extends Binder { shutdownIfNoPowerLocked(); shutdownIfOverTempLocked(); - if (mBatteryProps.batteryStatus != mLastBatteryStatus || + if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus || mBatteryProps.batteryHealth != mLastBatteryHealth || mBatteryProps.batteryPresent != mLastBatteryPresent || mBatteryProps.batteryLevel != mLastBatteryLevel || mPlugType != mLastPlugType || mBatteryProps.batteryVoltage != mLastBatteryVoltage || mBatteryProps.batteryTemperature != mLastBatteryTemperature || - mInvalidCharger != mLastInvalidCharger) { + mInvalidCharger != mLastInvalidCharger)) { if (mPlugType != mLastPlugType) { if (mLastPlugType == BATTERY_PLUGGED_NONE) { @@ -400,7 +429,24 @@ public final class BatteryService extends Binder { logOutlier = true; } - mBatteryLevelLow = isBatteryLowLocked(); + if (!mBatteryLevelLow) { + // Should we now switch in to low battery mode? + if (mPlugType == BATTERY_PLUGGED_NONE + && mBatteryProps.batteryLevel <= mLowBatteryWarningLevel) { + mBatteryLevelLow = true; + } + } else { + // Should we now switch out of low battery mode? + if (mPlugType != BATTERY_PLUGGED_NONE) { + mBatteryLevelLow = false; + } else if (mBatteryProps.batteryLevel >= mLowBatteryCloseWarningLevel) { + mBatteryLevelLow = false; + } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) { + // If being forced, the previous state doesn't matter, we will just + // absolutely check to see if we are now above the warning level. + mBatteryLevelLow = false; + } + } sendIntentLocked(); @@ -428,7 +474,7 @@ public final class BatteryService extends Binder { }); } - if (mBatteryLevelLow) { + if (shouldSendBatteryLowLocked()) { mSentLowBatteryBroadcast = true; mHandler.post(new Runnable() { @Override @@ -650,7 +696,7 @@ public final class BatteryService extends Binder { long ident = Binder.clearCallingIdentity(); try { mUpdatesStopped = true; - processValuesLocked(); + processValuesLocked(false); } finally { Binder.restoreCallingIdentity(ident); } @@ -664,7 +710,7 @@ public final class BatteryService extends Binder { if (mUpdatesStopped) { mUpdatesStopped = false; mBatteryProps.set(mLastBatteryProps); - processValuesLocked(); + processValuesLocked(false); } } finally { Binder.restoreCallingIdentity(ident); diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index d8671d9535e79..fb4b8f0b69c69 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -409,6 +409,9 @@ public final class PowerManagerService extends com.android.server.SystemService // Current state of the low power mode setting. private boolean mLowPowerModeSetting; + // Current state of whether the settings are allowing auto low power mode. + private boolean mAutoLowPowerModeEnabled; + // True if the battery level is currently considered low. private boolean mBatteryLevelLow; @@ -558,6 +561,9 @@ public final class PowerManagerService extends com.android.server.SystemService resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.LOW_POWER_MODE), false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Global.getUriFor( + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL), + false, mSettingsObserver, UserHandle.USER_ALL); // Go. readConfigurationLocked(); updateSettingsLocked(); @@ -645,8 +651,12 @@ public final class PowerManagerService extends com.android.server.SystemService final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver, Settings.Global.LOW_POWER_MODE, 0) != 0; - if (lowPowerModeEnabled != mLowPowerModeSetting) { + final boolean autoLowPowerModeEnabled = Settings.Global.getInt(resolver, + Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15) != 0; + if (lowPowerModeEnabled != mLowPowerModeSetting + || autoLowPowerModeEnabled != mAutoLowPowerModeEnabled) { mLowPowerModeSetting = lowPowerModeEnabled; + mAutoLowPowerModeEnabled = autoLowPowerModeEnabled; updateLowPowerModeLocked(); } @@ -654,7 +664,8 @@ public final class PowerManagerService extends com.android.server.SystemService } void updateLowPowerModeLocked() { - final boolean lowPowerModeEnabled = mLowPowerModeSetting || mBatteryLevelLow; + final boolean lowPowerModeEnabled = !mIsPowered + && (mLowPowerModeSetting || (mAutoLowPowerModeEnabled && mBatteryLevelLow)); if (mLowPowerModeEnabled != lowPowerModeEnabled) { mLowPowerModeEnabled = lowPowerModeEnabled; powerHintInternal(POWER_HINT_LOW_POWER_MODE, lowPowerModeEnabled ? 1 : 0); @@ -1197,7 +1208,7 @@ public final class PowerManagerService extends com.android.server.SystemService } } - if (oldLevelLow != mBatteryLevelLow) { + if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) { updateLowPowerModeLocked(); } } @@ -2168,6 +2179,8 @@ public final class PowerManagerService extends com.android.server.SystemService pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity); pw.println(" mSandmanScheduled=" + mSandmanScheduled); pw.println(" mSandmanSummoned=" + mSandmanSummoned); + pw.println(" mLowPowerModeEnabled=" + mLowPowerModeEnabled); + pw.println(" mBatteryLevelLow=" + mBatteryLevelLow); pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime)); pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime)); pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime)); @@ -2204,6 +2217,8 @@ public final class PowerManagerService extends com.android.server.SystemService pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting); pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting); pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting); + pw.println(" mLowPowerModeSetting=" + mLowPowerModeSetting); + pw.println(" mAutoLowPowerModeEnabled=" + mAutoLowPowerModeEnabled); pw.println(" mMinimumScreenOffTimeoutConfig=" + mMinimumScreenOffTimeoutConfig); pw.println(" mMaximumScreenDimDurationConfig=" + mMaximumScreenDimDurationConfig); pw.println(" mMaximumScreenDimRatioConfig=" + mMaximumScreenDimRatioConfig);