diff options
author | Suprabh Shukla <suprabh@google.com> | 2018-01-19 16:43:35 -0800 |
---|---|---|
committer | Suprabh Shukla <suprabh@google.com> | 2018-01-24 18:57:56 -0800 |
commit | c25447daa1ce6b51a8fe8eb13b376220c62849bd (patch) | |
tree | d300b75293014843932f183b8d5e77a8f03417a8 | |
parent | 6e618d6034f9ab23ea2a2dea1bc468d026f518eb (diff) |
Exempting allow-while-idle alarms in EBS
Exempting allow-while-idle alarms when the device is in Extreme battery
saver. The throttling of one allow-while-idle alarm per
ALLOW_WHILE_IDLE_LONG_TIME is applied even when the device may not be
dozing. The throttling is relaxed to ALLOW_WHILE_IDLE_SHORT_TIME if the
uid was in the foreground recently.
Test: atest android.alarmmanager.cts.BatterySaverTests
Bug: 72124522
Change-Id: Ic75bac6234745c73a345180387c83bc725823aa8
3 files changed, 53 insertions, 30 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 15c0f3c11545..342b48ee7f72 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -82,6 +82,7 @@ import java.util.TimeZone; import java.util.TreeSet; import java.util.function.Predicate; +import static android.app.AlarmManager.FLAG_ALLOW_WHILE_IDLE; import static android.app.AlarmManager.RTC_WAKEUP; import static android.app.AlarmManager.RTC; import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP; @@ -175,7 +176,6 @@ class AlarmManagerService extends SystemService { long mNextNonWakeupDeliveryTime; long mLastTimeChangeClockTime; long mLastTimeChangeRealtime; - long mAllowWhileIdleMinTime; int mNumTimeChanged; // Bookkeeping about the identity of the "System UI" package, determined at runtime. @@ -199,6 +199,12 @@ class AlarmManagerService extends SystemService { */ final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray(); + /** + * For each uid, we store whether the last allow-while-idle alarm was dispatched while + * the uid was in foreground or not. We will use the allow_while_idle_short_time in such cases. + */ + final SparseBooleanArray mUseAllowWhileIdleShortTime = new SparseBooleanArray(); + final static class IdleDispatchEntry { int uid; String pkg; @@ -242,7 +248,6 @@ class AlarmManagerService extends SystemService { private static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION = "allow_while_idle_whitelist_duration"; private static final String KEY_LISTENER_TIMEOUT = "listener_timeout"; - private static final String KEY_BG_RESTRICTIONS_ENABLED = "limit_bg_alarms_enabled"; private static final long DEFAULT_MIN_FUTURITY = 5 * 1000; private static final long DEFAULT_MIN_INTERVAL = 60 * 1000; @@ -277,7 +282,6 @@ class AlarmManagerService extends SystemService { public Constants(Handler handler) { super(handler); - updateAllowWhileIdleMinTimeLocked(); updateAllowWhileIdleWhitelistDurationLocked(); } @@ -288,11 +292,6 @@ class AlarmManagerService extends SystemService { updateConstants(); } - public void updateAllowWhileIdleMinTimeLocked() { - mAllowWhileIdleMinTime = mPendingIdleUntil != null - ? ALLOW_WHILE_IDLE_LONG_TIME : ALLOW_WHILE_IDLE_SHORT_TIME; - } - public void updateAllowWhileIdleWhitelistDurationLocked() { if (mLastAllowWhileIdleWhitelistDuration != ALLOW_WHILE_IDLE_WHITELIST_DURATION) { mLastAllowWhileIdleWhitelistDuration = ALLOW_WHILE_IDLE_WHITELIST_DURATION; @@ -330,7 +329,6 @@ class AlarmManagerService extends SystemService { LISTENER_TIMEOUT = mParser.getLong(KEY_LISTENER_TIMEOUT, DEFAULT_LISTENER_TIMEOUT); - updateAllowWhileIdleMinTimeLocked(); updateAllowWhileIdleWhitelistDurationLocked(); } } @@ -967,9 +965,6 @@ class AlarmManagerService extends SystemService { } } - // Make sure we are using the correct ALLOW_WHILE_IDLE min time. - mConstants.updateAllowWhileIdleMinTimeLocked(); - // Reschedule everything. rescheduleKernelAlarmsLocked(); updateNextAlarmClockLocked(); @@ -1421,7 +1416,6 @@ class AlarmManagerService extends SystemService { return; } } - if (RECORD_DEVICE_IDLE_ALARMS) { if ((a.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) { IdleDispatchEntry ent = new IdleDispatchEntry(); @@ -1472,7 +1466,6 @@ class AlarmManagerService extends SystemService { } mPendingIdleUntil = a; - mConstants.updateAllowWhileIdleMinTimeLocked(); needRebatch = true; } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) { if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) { @@ -1751,6 +1744,15 @@ class AlarmManagerService extends SystemService { if (!blocked) { pw.println(" none"); } + pw.print(" mUseAllowWhileIdleShortTime: ["); + for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) { + if (mUseAllowWhileIdleShortTime.valueAt(i)) { + UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i)); + pw.print(" "); + } + } + pw.println("]"); + if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) { pw.println(); pw.println(" Idle mode state:"); @@ -1803,9 +1805,6 @@ class AlarmManagerService extends SystemService { pw.println(); } - pw.print(" mAllowWhileIdleMinTime="); - TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw); - pw.println(); if (mLastAllowWhileIdleDispatch.size() > 0) { pw.println(" Last allow while idle dispatch times:"); for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) { @@ -2072,8 +2071,6 @@ class AlarmManagerService extends SystemService { f.writeToProto(proto, AlarmManagerServiceProto.OUTSTANDING_DELIVERIES); } - proto.write(AlarmManagerServiceProto.ALLOW_WHILE_IDLE_MIN_DURATION_MS, - mAllowWhileIdleMinTime); for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) { final long token = proto.start( AlarmManagerServiceProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES); @@ -2739,6 +2736,7 @@ class AlarmManagerService extends SystemService { } private boolean isBackgroundRestricted(Alarm alarm) { + final boolean allowWhileIdle = (alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0; if (alarm.alarmClock != null) { // Don't block alarm clocks return false; @@ -2751,7 +2749,8 @@ class AlarmManagerService extends SystemService { final String sourcePackage = (alarm.operation != null) ? alarm.operation.getCreatorPackage() : alarm.packageName; final int sourceUid = alarm.creatorUid; - return mForceAppStandbyTracker.areAlarmsRestricted(sourceUid, sourcePackage); + return mForceAppStandbyTracker.areAlarmsRestricted(sourceUid, sourcePackage, + allowWhileIdle); } private native long init(); @@ -2785,8 +2784,21 @@ class AlarmManagerService extends SystemService { if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) { // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can // schedule such alarms. - long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0); - long minTime = lastTime + mAllowWhileIdleMinTime; + final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0); + final boolean dozing = mPendingIdleUntil != null; + final boolean ebs = mForceAppStandbyTracker.isForceAllAppsStandbyEnabled(); + final long minTime; + if (!dozing && !ebs) { + minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME; + } else if (dozing) { + minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME; + } else if (mUseAllowWhileIdleShortTime.get(alarm.creatorUid)) { + // if the last allow-while-idle went off while uid was fg, or the uid + // recently came into fg, don't block the alarm for long. + minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_SHORT_TIME; + } else { + minTime = lastTime + mConstants.ALLOW_WHILE_IDLE_LONG_TIME; + } if (nowELAPSED < minTime) { // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE // alarm went off for this app. Reschedule the alarm to be in the @@ -3526,6 +3538,7 @@ class AlarmManagerService extends SystemService { @Override public void onUidGone(int uid, boolean disabled) { synchronized (mLock) { + mUseAllowWhileIdleShortTime.delete(uid); if (disabled) { removeForStoppedLocked(uid); } @@ -3533,6 +3546,9 @@ class AlarmManagerService extends SystemService { } @Override public void onUidActive(int uid) { + synchronized (mLock) { + mUseAllowWhileIdleShortTime.put(uid, true); + } } @Override public void onUidIdle(int uid, boolean disabled) { @@ -3547,7 +3563,6 @@ class AlarmManagerService extends SystemService { } }; - private final Listener mForceAppStandbyListener = new Listener() { @Override public void unblockAllUnrestrictedAlarms() { @@ -3829,7 +3844,12 @@ class AlarmManagerService extends SystemService { if (allowWhileIdle) { // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm. - mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED); + mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED); + if (mForceAppStandbyTracker.isInForeground(alarm.creatorUid)) { + mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true); + } else { + mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false); + } if (RECORD_DEVICE_IDLE_ALARMS) { IdleDispatchEntry ent = new IdleDispatchEntry(); ent.uid = alarm.uid; diff --git a/services/core/java/com/android/server/ForceAppStandbyTracker.java b/services/core/java/com/android/server/ForceAppStandbyTracker.java index 792fdfe42d17..257845e365be 100644 --- a/services/core/java/com/android/server/ForceAppStandbyTracker.java +++ b/services/core/java/com/android/server/ForceAppStandbyTracker.java @@ -214,8 +214,11 @@ public class ForceAppStandbyTracker { int uid, @NonNull String packageName) { updateJobsForUidPackage(uid, packageName); - if (!sender.areAlarmsRestricted(uid, packageName)) { + if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ false)) { unblockAlarmsForUidPackage(uid, packageName); + } else if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ true)){ + // we need to deliver the allow-while-idle alarms for this uid, package + unblockAllUnrestrictedAlarms(); } } @@ -706,7 +709,7 @@ public class ForceAppStandbyTracker { synchronized (mLock) { unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby; } - for (Listener l: cloneListeners()) { + for (Listener l : cloneListeners()) { l.updateAllJobs(); if (unblockAlarms) { l.unblockAllUnrestrictedAlarms(); @@ -818,9 +821,10 @@ public class ForceAppStandbyTracker { /** * @return whether alarms should be restricted for a UID package-name. */ - public boolean areAlarmsRestricted(int uid, @NonNull String packageName) { + public boolean areAlarmsRestricted(int uid, @NonNull String packageName, + boolean allowWhileIdle) { return isRestricted(uid, packageName, /*useTempWhitelistToo=*/ false, - /* exemptOnBatterySaver =*/ false); + /* exemptOnBatterySaver =*/ allowWhileIdle); } /** @@ -879,7 +883,6 @@ public class ForceAppStandbyTracker { /** * @return whether force all apps standby is enabled or not. * - * Note clients normally shouldn't need to access it. */ boolean isForceAllAppsStandbyEnabled() { synchronized (mLock) { diff --git a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java index a29e169cb196..b68bf2db1237 100644 --- a/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/ForceAppStandbyTrackerTest.java @@ -266,7 +266,7 @@ public class ForceAppStandbyTrackerTest { assertEquals(((restrictionTypes & JOBS_ONLY) != 0), instance.areJobsRestricted(uid, packageName, exemptFromBatterySaver)); assertEquals(((restrictionTypes & ALARMS_ONLY) != 0), - instance.areAlarmsRestricted(uid, packageName)); + instance.areAlarmsRestricted(uid, packageName, exemptFromBatterySaver)); } private void areRestricted(ForceAppStandbyTrackerTestable instance, int uid, String packageName, |