diff options
author | 2021-01-12 16:44:09 +0000 | |
---|---|---|
committer | 2021-01-12 16:44:09 +0000 | |
commit | eedea4c824cd218b8df244ead4ee1ccc44ac100d (patch) | |
tree | 9dd5dde749e4485ba0c620fad7752da6eb11987f | |
parent | 44859f7117238c456a28157ed96a5869061f5900 (diff) | |
parent | 17f6e2007fd1e455dd52e4ff7fa50db84f848540 (diff) |
Merge "Adding Battery saver policy to alarms"
5 files changed, 657 insertions, 238 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java index 4dc9cf850893..cc3e9c33fe42 100644 --- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java +++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java @@ -274,11 +274,8 @@ public class AppStateTrackerImpl implements AppStateTracker { int uid, @NonNull String packageName) { updateJobsForUidPackage(uid, packageName, sender.isUidActive(uid)); - if (!sender.areAlarmsRestricted(uid, packageName, /*allowWhileIdle=*/ false)) { + if (!sender.areAlarmsRestricted(uid, packageName)) { 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(); } if (!sender.isRunAnyInBackgroundAppOpsAllowed(uid, packageName)) { @@ -302,6 +299,7 @@ public class AppStateTrackerImpl implements AppStateTracker { final boolean isActive = sender.isUidActive(uid); updateJobsForUid(uid, isActive); + updateAlarmsForUid(uid); if (isActive) { unblockAlarmsForUid(uid); @@ -313,7 +311,7 @@ public class AppStateTrackerImpl implements AppStateTracker { */ private void onPowerSaveUnexempted(AppStateTrackerImpl sender) { updateAllJobs(); - unblockAllUnrestrictedAlarms(); + updateAllAlarms(); } /** @@ -322,6 +320,8 @@ public class AppStateTrackerImpl implements AppStateTracker { */ private void onPowerSaveExemptionListChanged(AppStateTrackerImpl sender) { updateAllJobs(); + updateAllAlarms(); + unblockAllUnrestrictedAlarms(); } /** @@ -344,7 +344,7 @@ public class AppStateTrackerImpl implements AppStateTracker { private void onExemptedBucketChanged(AppStateTrackerImpl sender) { // This doesn't happen very often, so just re-evaluate all jobs / alarms. updateAllJobs(); - unblockAllUnrestrictedAlarms(); + updateAllAlarms(); } /** @@ -352,10 +352,7 @@ public class AppStateTrackerImpl implements AppStateTracker { */ private void onForceAllAppsStandbyChanged(AppStateTrackerImpl sender) { updateAllJobs(); - - if (!sender.isForceAllAppsStandbyEnabled()) { - unblockAllUnrestrictedAlarms(); - } + updateAllAlarms(); } /** @@ -387,6 +384,19 @@ public class AppStateTrackerImpl implements AppStateTracker { } /** + * Called when all alarms need to be re-evaluated for eligibility based on + * {@link #areAlarmsRestrictedByBatterySaver}. + */ + public void updateAllAlarms() { + } + + /** + * Called when the given uid state changes to active / idle. + */ + public void updateAlarmsForUid(int uid) { + } + + /** * Called when the job restrictions for multiple UIDs might have changed, so the alarm * manager should re-evaluate all restrictions for all blocked jobs. */ @@ -918,7 +928,7 @@ public class AppStateTrackerImpl implements AppStateTracker { // Feature flag for forced app standby changed. final boolean unblockAlarms; synchronized (mLock) { - unblockAlarms = !mForcedAppStandbyEnabled && !mForceAllAppsStandby; + unblockAlarms = !mForcedAppStandbyEnabled; } for (Listener l : cloneListeners()) { l.updateAllJobs(); @@ -1109,53 +1119,64 @@ public class AppStateTrackerImpl implements AppStateTracker { } /** - * @return whether alarms should be restricted for a UID package-name. - */ - public boolean areAlarmsRestricted(int uid, @NonNull String packageName, - boolean isExemptOnBatterySaver) { - return isRestricted(uid, packageName, /*useTempExemptionListToo=*/ false, - isExemptOnBatterySaver); - } - - /** - * @return whether jobs should be restricted for a UID package-name. + * @return whether alarms should be restricted for a UID package-name, due to explicit + * user-forced app standby. Use {{@link #areAlarmsRestrictedByBatterySaver} to check for + * restrictions induced by battery saver. */ - public boolean areJobsRestricted(int uid, @NonNull String packageName, - boolean hasForegroundExemption) { - return isRestricted(uid, packageName, /*useTempExemptionListToo=*/ true, - hasForegroundExemption); + public boolean areAlarmsRestricted(int uid, @NonNull String packageName) { + if (isUidActive(uid)) { + return false; + } + synchronized (mLock) { + final int appId = UserHandle.getAppId(uid); + if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) { + return false; + } + return (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)); + } } /** - * @return whether foreground services should be suppressed in the background - * due to forced app standby for the given app + * @return whether alarms should be restricted when due to battery saver. */ - public boolean areForegroundServicesRestricted(int uid, @NonNull String packageName) { + public boolean areAlarmsRestrictedByBatterySaver(int uid, @NonNull String packageName) { + if (isUidActive(uid)) { + return false; + } synchronized (mLock) { - return isRunAnyRestrictedLocked(uid, packageName); + final int appId = UserHandle.getAppId(uid); + if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) { + return false; + } + final int userId = UserHandle.getUserId(uid); + if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole() + && mExemptedBucketPackages.contains(userId, packageName)) { + return false; + } + return mForceAllAppsStandby; } } + /** - * @return whether force-app-standby is effective for a UID package-name. + * @return whether jobs should be restricted for a UID package-name. This could be due to + * battery saver or user-forced app standby */ - private boolean isRestricted(int uid, @NonNull String packageName, - boolean useTempExemptionListToo, boolean exemptOnBatterySaver) { + public boolean areJobsRestricted(int uid, @NonNull String packageName, + boolean hasForegroundExemption) { if (isUidActive(uid)) { return false; } synchronized (mLock) { final int appId = UserHandle.getAppId(uid); - if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) { - return false; - } - if (useTempExemptionListToo && ArrayUtils.contains(mTempExemptAppIds, appId)) { + if (ArrayUtils.contains(mPowerExemptAllAppIds, appId) + || ArrayUtils.contains(mTempExemptAppIds, appId)) { return false; } if (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName)) { return true; } - if (exemptOnBatterySaver) { + if (hasForegroundExemption) { return false; } final int userId = UserHandle.getUserId(uid); diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java index a8c0f0ec3e00..657c368d0aee 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java @@ -42,7 +42,7 @@ import java.util.Date; */ class Alarm { @VisibleForTesting - public static final int NUM_POLICIES = 3; + public static final int NUM_POLICIES = 4; /** * Index used to store the time the alarm was requested to expire. To be used with * {@link #setPolicyElapsed(int, long)}. @@ -59,6 +59,12 @@ class Alarm { */ public static final int DEVICE_IDLE_POLICY_INDEX = 2; + /** + * Index used to store the earliest time the alarm can expire based on battery saver policy. + * To be used with {@link #setPolicyElapsed(int, long)}. + */ + public static final int BATTERY_SAVER_POLICY_INDEX = 3; + public final int type; /** * The original trigger time supplied by the caller. This can be in the elapsed or rtc time base @@ -223,6 +229,8 @@ class Alarm { return "app_standby"; case DEVICE_IDLE_POLICY_INDEX: return "device_idle"; + case BATTERY_SAVER_POLICY_INDEX: + return "battery_saver"; default: return "--unknown--"; } diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 7842d487dfb2..aa46cfdc5c8a 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -28,6 +28,7 @@ import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; import static android.os.UserHandle.USER_SYSTEM; import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX; +import static com.android.server.alarm.Alarm.BATTERY_SAVER_POLICY_INDEX; import static com.android.server.alarm.Alarm.DEVICE_IDLE_POLICY_INDEX; import static com.android.server.alarm.Alarm.REQUESTER_POLICY_INDEX; @@ -156,6 +157,7 @@ public class AlarmManagerService extends SystemService { static final int TICK_HISTORY_DEPTH = 10; static final long MILLIS_IN_DAY = 24 * 60 * 60 * 1000; + static final long INDEFINITE_DELAY = 365 * MILLIS_IN_DAY; // Indices into the KEYS_APP_STANDBY_QUOTAS array. static final int ACTIVE_INDEX = 0; @@ -964,8 +966,7 @@ public class AlarmManagerService extends SystemService { * Check all alarms in {@link #mPendingBackgroundAlarms} and send the ones that are not * restricted. * - * This is only called when the global "force all apps-standby" flag changes or when the - * power save whitelist changes, so it's okay to be slow. + * This is only called when the power save whitelist changes, so it's okay to be slow. */ void sendAllUnrestrictedPendingBackgroundAlarmsLocked() { final ArrayList<Alarm> alarmsToDeliver = new ArrayList<>(); @@ -984,7 +985,6 @@ public class AlarmManagerService extends SystemService { Predicate<Alarm> isBackgroundRestricted) { for (int uidIndex = pendingAlarms.size() - 1; uidIndex >= 0; uidIndex--) { - final int uid = pendingAlarms.keyAt(uidIndex); final ArrayList<Alarm> alarmsForUid = pendingAlarms.valueAt(uidIndex); for (int alarmIndex = alarmsForUid.size() - 1; alarmIndex >= 0; alarmIndex--) { @@ -1620,6 +1620,44 @@ public class AlarmManagerService extends SystemService { } /** + * Adjusts the delivery time of the alarm based on battery saver rules. + * + * @param alarm The alarm to adjust + * @return {@code true} if the alarm delivery time was updated. + */ + private boolean adjustDeliveryTimeBasedOnBatterySaver(Alarm alarm) { + final long nowElapsed = mInjector.getElapsedRealtime(); + if (isExemptFromBatterySaver(alarm)) { + return false; + } + + if (!(mAppStateTracker != null && mAppStateTracker.areAlarmsRestrictedByBatterySaver( + alarm.creatorUid, alarm.sourcePackage))) { + return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, nowElapsed); + } + + final long batterSaverPolicyElapsed; + if ((alarm.flags & (AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) { + // Unrestricted. + batterSaverPolicyElapsed = nowElapsed; + } else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) { + // Allowed but limited. + final long minDelay; + if (mUseAllowWhileIdleShortTime.get(alarm.creatorUid)) { + minDelay = mConstants.ALLOW_WHILE_IDLE_SHORT_TIME; + } else { + minDelay = mConstants.ALLOW_WHILE_IDLE_LONG_TIME; + } + final long lastDispatch = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0); + batterSaverPolicyElapsed = (lastDispatch == 0) ? nowElapsed : lastDispatch + minDelay; + } else { + // Not allowed. + batterSaverPolicyElapsed = nowElapsed + INDEFINITE_DELAY; + } + return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, batterSaverPolicyElapsed); + } + + /** * Adjusts the delivery time of the alarm based on device_idle (doze) rules. * * @param alarm The alarm to adjust @@ -1756,6 +1794,7 @@ public class AlarmManagerService extends SystemService { if (a.alarmClock != null) { mNextAlarmClockMayChange = true; } + adjustDeliveryTimeBasedOnBatterySaver(a); adjustDeliveryTimeBasedOnBucketLocked(a); mAlarmStore.add(a); rescheduleKernelAlarmsLocked(); @@ -2230,14 +2269,6 @@ public class AlarmManagerService extends SystemService { pw.print(": "); final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i); TimeUtils.formatDuration(lastTime, nowELAPSED, pw); - - final long minInterval = getWhileIdleMinIntervalLocked(uid); - pw.print(" Next allowed:"); - TimeUtils.formatDuration(lastTime + minInterval, nowELAPSED, pw); - pw.print(" ("); - TimeUtils.formatDuration(minInterval, 0, pw); - pw.print(")"); - pw.println(); } pw.decreaseIndent(); @@ -2511,8 +2542,6 @@ public class AlarmManagerService extends SystemService { proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.UID, uid); proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.TIME_MS, lastTime); - proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.NEXT_ALLOWED_MS, - lastTime + getWhileIdleMinIntervalLocked(uid)); proto.end(token); } @@ -3119,30 +3148,36 @@ public class AlarmManagerService extends SystemService { } } + private boolean isExemptFromBatterySaver(Alarm alarm) { + if (alarm.alarmClock != null) { + return true; + } + if ((alarm.operation != null) + && (alarm.operation.isActivity() || alarm.operation.isForegroundService())) { + return true; + } + if (UserHandle.isCore(alarm.creatorUid)) { + return true; + } + return false; + } + private boolean isBackgroundRestricted(Alarm alarm) { - boolean exemptOnBatterySaver = (alarm.flags & FLAG_ALLOW_WHILE_IDLE) != 0; if (alarm.alarmClock != null) { // Don't defer alarm clocks return false; } - if (alarm.operation != null) { - if (alarm.operation.isActivity()) { - // Don't defer starting actual UI - return false; - } - if (alarm.operation.isForegroundService()) { - // FG service alarms are nearly as important; consult AST policy - exemptOnBatterySaver = true; - } + if (alarm.operation != null && alarm.operation.isActivity()) { + // Don't defer starting actual UI + return false; } final String sourcePackage = alarm.sourcePackage; final int sourceUid = alarm.creatorUid; if (UserHandle.isCore(sourceUid)) { return false; } - return (mAppStateTracker != null) && - mAppStateTracker.areAlarmsRestricted(sourceUid, sourcePackage, - exemptOnBatterySaver); + return (mAppStateTracker != null) && mAppStateTracker.areAlarmsRestricted(sourceUid, + sourcePackage); } private static native long init(); @@ -3153,46 +3188,10 @@ public class AlarmManagerService extends SystemService { private static native int setKernelTimezone(long nativeData, int minuteswest); private static native long getNextAlarm(long nativeData, int type); - private long getWhileIdleMinIntervalLocked(int uid) { - final boolean ebs = (mAppStateTracker != null) - && mAppStateTracker.isForceAllAppsStandbyEnabled(); - - if (!ebs || mUseAllowWhileIdleShortTime.get(uid)) { - // 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. - return mConstants.ALLOW_WHILE_IDLE_SHORT_TIME; - } - return mConstants.ALLOW_WHILE_IDLE_LONG_TIME; - } - boolean triggerAlarmsLocked(ArrayList<Alarm> triggerList, final long nowELAPSED) { boolean hasWakeup = false; final ArrayList<Alarm> pendingAlarms = mAlarmStore.removePendingAlarms(nowELAPSED); for (final Alarm alarm : pendingAlarms) { - 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. The first such alarm from an app is always delivered. - final long lastTime = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, -1); - final long minTime = lastTime + getWhileIdleMinIntervalLocked(alarm.creatorUid); - if (lastTime >= 0 && 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 - // correct time period. - alarm.setPolicyElapsed(REQUESTER_POLICY_INDEX, minTime); - if (RECORD_DEVICE_IDLE_ALARMS) { - IdleDispatchEntry ent = new IdleDispatchEntry(); - ent.uid = alarm.uid; - ent.pkg = alarm.operation.getCreatorPackage(); - ent.tag = alarm.operation.getTag(""); - ent.op = "RESCHEDULE"; - ent.elapsedRealtime = nowELAPSED; - ent.argRealtime = lastTime; - mAllowWhileIdleDispatches.add(ent); - } - setImplLocked(alarm); - continue; - } - } if (isBackgroundRestricted(alarm)) { // Alarms with FLAG_WAKE_FROM_IDLE or mPendingIdleUntil alarm are not deferred if (DEBUG_BG_LIMIT) { @@ -3924,8 +3923,41 @@ public class AlarmManagerService extends SystemService { } private final Listener mForceAppStandbyListener = new Listener() { + + @Override + public void updateAllAlarms() { + // Called when: + // 1. Power exemption list changes, + // 2. Battery saver state is toggled, + // 3. Any package is moved into or out of the EXEMPTED bucket. + synchronized (mLock) { + if (mAlarmStore.updateAlarmDeliveries( + a -> adjustDeliveryTimeBasedOnBatterySaver(a))) { + rescheduleKernelAlarmsLocked(); + } + } + } + + @Override + public void updateAlarmsForUid(int uid) { + // Called when the given uid's state switches b/w active and idle. + synchronized (mLock) { + if (mAlarmStore.updateAlarmDeliveries(a -> { + if (a.creatorUid != uid) { + return false; + } + return adjustDeliveryTimeBasedOnBatterySaver(a); + })) { + rescheduleKernelAlarmsLocked(); + } + } + } + @Override public void unblockAllUnrestrictedAlarms() { + // Called when: + // 1. Power exemption list changes, + // 2. User FAS feature is disabled. synchronized (mLock) { sendAllUnrestrictedPendingBackgroundAlarmsLocked(); } @@ -3934,12 +3966,14 @@ public class AlarmManagerService extends SystemService { @Override public void unblockAlarmsForUid(int uid) { synchronized (mLock) { + // Called when the given uid becomes active. sendPendingBackgroundAlarmsLocked(uid, null); } } @Override public void unblockAlarmsForUidPackage(int uid, String packageName) { + // Called when user turns off FAS for this (uid, package). synchronized (mLock) { sendPendingBackgroundAlarmsLocked(uid, packageName); } @@ -3950,9 +3984,14 @@ public class AlarmManagerService extends SystemService { synchronized (mLock) { if (foreground) { mUseAllowWhileIdleShortTime.put(uid, true); - - // Note we don't have to drain the pending while-idle alarms here, because - // this event should coincide with unblockAlarmsForUid(). + if (mAlarmStore.updateAlarmDeliveries(a -> { + if (a.creatorUid != uid || (a.flags & FLAG_ALLOW_WHILE_IDLE) == 0) { + return false; + } + return adjustDeliveryTimeBasedOnBatterySaver(a); + })) { + rescheduleKernelAlarmsLocked(); + } } } } @@ -4236,18 +4275,20 @@ public class AlarmManagerService extends SystemService { if (allowWhileIdle) { // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm. mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED); - mAlarmStore.updateAlarmDeliveries(a -> { - if (a.creatorUid != alarm.creatorUid) { - return false; - } - return adjustDeliveryTimeBasedOnDeviceIdle(a); - }); if ((mAppStateTracker == null) || mAppStateTracker.isUidInForeground(alarm.creatorUid)) { mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true); } else { mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false); } + mAlarmStore.updateAlarmDeliveries(a -> { + if (a.creatorUid != alarm.creatorUid + || (a.flags & FLAG_ALLOW_WHILE_IDLE) == 0) { + return false; + } + return adjustDeliveryTimeBasedOnDeviceIdle(a) + | adjustDeliveryTimeBasedOnBatterySaver(a); + }); if (RECORD_DEVICE_IDLE_ALARMS) { IdleDispatchEntry ent = new IdleDispatchEntry(); ent.uid = alarm.uid; diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java index 3220dff553d3..a691a8d44e48 100644 --- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java @@ -313,29 +313,30 @@ public class AppStateTrackerTest { } } - private static final int NONE = 0; - private static final int ALARMS_ONLY = 1 << 0; - private static final int JOBS_ONLY = 1 << 1; - private static final int JOBS_AND_ALARMS = ALARMS_ONLY | JOBS_ONLY; - - private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName, - int restrictionTypes, boolean exemptFromBatterySaver) { - assertEquals(((restrictionTypes & JOBS_ONLY) != 0), - instance.areJobsRestricted(uid, packageName, exemptFromBatterySaver)); - assertEquals(((restrictionTypes & ALARMS_ONLY) != 0), - instance.areAlarmsRestricted(uid, packageName, exemptFromBatterySaver)); + private void areJobsRestricted(AppStateTrackerTestable instance, int[] uids, String[] packages, + boolean[] restricted, boolean exemption) { + assertTrue(uids.length == packages.length && uids.length == restricted.length); + for (int i = 0; i < uids.length; i++) { + assertEquals(restricted[i], + instance.areJobsRestricted(uids[i], packages[i], exemption)); + } } - private void areRestricted(AppStateTrackerTestable instance, int uid, String packageName, - int restrictionTypes) { - areRestricted(instance, uid, packageName, restrictionTypes, - /*exemptFromBatterySaver=*/ false); + private void areAlarmsRestrictedByFAS(AppStateTrackerTestable instance, int[] uids, + String[] packages, boolean[] restricted) { + assertTrue(uids.length == packages.length && uids.length == restricted.length); + for (int i = 0; i < uids.length; i++) { + assertEquals(restricted[i], instance.areAlarmsRestricted(uids[i], packages[i])); + } } - private void areRestrictedWithExemption(AppStateTrackerTestable instance, - int uid, String packageName, int restrictionTypes) { - areRestricted(instance, uid, packageName, restrictionTypes, - /*exemptFromBatterySaver=*/ true); + private void areAlarmsRestrictedByBatterySaver(AppStateTrackerTestable instance, int[] uids, + String[] packages, boolean[] restricted) { + assertTrue(uids.length == packages.length && uids.length == restricted.length); + for (int i = 0; i < uids.length; i++) { + assertEquals(restricted[i], + instance.areAlarmsRestrictedByBatterySaver(uids[i], packages[i])); + } } @Test @@ -344,30 +345,42 @@ public class AppStateTrackerTest { callStart(instance); assertFalse(instance.isForceAllAppsStandbyEnabled()); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, NONE); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); - - areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE); - areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE); - areRestrictedWithExemption(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false}, + true); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false}); mPowerSaveMode = true; mPowerSaveObserver.accept(getPowerSaveState()); assertTrue(instance.isForceAllAppsStandbyEnabled()); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); - - areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE); - areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE); - areRestrictedWithExemption(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false}, + true); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}); // Toggle the foreground state. - mPowerSaveMode = true; - mPowerSaveObserver.accept(getPowerSaveState()); assertFalse(instance.isUidActive(UID_1)); assertFalse(instance.isUidActive(UID_2)); @@ -376,34 +389,65 @@ public class AppStateTrackerTest { mIUidObserver.onUidActive(UID_1); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, true, true, false}, + false); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, true, true, false}); + assertTrue(instance.isUidActive(UID_1)); assertFalse(instance.isUidActive(UID_2)); mIUidObserver.onUidGone(UID_1, /*disable=*/ false); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}, + false); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}); + assertFalse(instance.isUidActive(UID_1)); assertFalse(instance.isUidActive(UID_2)); mIUidObserver.onUidActive(UID_1); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, true, true, false}, + false); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, true, true, false}); mIUidObserver.onUidIdle(UID_1, /*disable=*/ false); waitUntilMainHandlerDrain(); waitUntilMainHandlerDrain(); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}, + false); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}); + assertFalse(instance.isUidActive(UID_1)); assertFalse(instance.isUidActive(UID_2)); @@ -416,11 +460,19 @@ public class AppStateTrackerTest { assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2)); assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2)); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_10_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, NONE); - areRestricted(instance, UID_10_2, PACKAGE_2, NONE); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, false}, + false); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, false}); + areAlarmsRestrictedByFAS(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, false}); setAppOps(UID_1, PACKAGE_1, true); setAppOps(UID_10_2, PACKAGE_2, true); @@ -429,24 +481,72 @@ public class AppStateTrackerTest { assertTrue(instance.isRunAnyInBackgroundAppOpsAllowed(UID_2, PACKAGE_2)); assertFalse(instance.isRunAnyInBackgroundAppOpsAllowed(UID_10_2, PACKAGE_2)); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, NONE); - areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}, + true); + + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, false}); + areAlarmsRestrictedByFAS(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}); // Toggle power saver, should still be the same. mPowerSaveMode = true; mPowerSaveObserver.accept(getPowerSaveState()); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}, + true); + + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, true, false}); + areAlarmsRestrictedByFAS(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}); + mPowerSaveMode = false; mPowerSaveObserver.accept(getPowerSaveState()); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, NONE); - areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}, + true); + + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, false}); + areAlarmsRestrictedByFAS(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, false, false, true, false}); // Clear the app ops and update the exemption list. setAppOps(UID_1, PACKAGE_1, false); @@ -455,24 +555,41 @@ public class AppStateTrackerTest { mPowerSaveMode = true; mPowerSaveObserver.accept(getPowerSaveState()); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, false}, + true); + + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, true, false}); + areAlarmsRestrictedByFAS(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, false}); instance.setPowerSaveExemptionListAppIds(new int[] {UID_1}, new int[] {}, new int[] {UID_2}); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_10_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, ALARMS_ONLY); - areRestricted(instance, UID_10_2, PACKAGE_2, ALARMS_ONLY); - areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID}, + new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3, + PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, true, true, false}, + false); + + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID}, + new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3, + PACKAGE_SYSTEM}, + new boolean[] {false, false, true, true, true, true, false}); // Again, make sure toggling the global state doesn't change it. mPowerSaveMode = false; @@ -481,13 +598,18 @@ public class AppStateTrackerTest { mPowerSaveMode = true; mPowerSaveObserver.accept(getPowerSaveState()); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_10_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, ALARMS_ONLY); - areRestricted(instance, UID_10_2, PACKAGE_2, ALARMS_ONLY); - areRestricted(instance, UID_3, PACKAGE_3, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_3, PACKAGE_3, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID}, + new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3, + PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false, true, true, false}, + false); + + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_10_1, UID_2, UID_10_2, UID_3, UID_10_3, Process.SYSTEM_UID}, + new String[]{PACKAGE_1, PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_3, PACKAGE_3, + PACKAGE_SYSTEM}, + new boolean[] {false, false, true, true, true, true, false}); assertTrue(instance.isUidPowerSaveExempt(UID_1)); assertTrue(instance.isUidPowerSaveExempt(UID_10_1)); @@ -646,52 +768,98 @@ public class AppStateTrackerTest { } @Test - public void testExempt() throws Exception { + public void testExemptedBucket() throws Exception { final AppStateTrackerTestable instance = newInstance(); callStart(instance); assertFalse(instance.isForceAllAppsStandbyEnabled()); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, NONE); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + + areJobsRestricted(instance, + new int[] {UID_1, UID_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false}, + false); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false}); mPowerSaveMode = true; mPowerSaveObserver.accept(getPowerSaveState()); assertTrue(instance.isForceAllAppsStandbyEnabled()); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, Process.SYSTEM_UID, PACKAGE_SYSTEM, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {false, false, false, false}, + true); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2, Process.SYSTEM_UID}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2, PACKAGE_SYSTEM}, + new boolean[] {true, true, true, false}); // Exempt package 2 on user-10. mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 10, false, UsageStatsManager.STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_2, PACKAGE_2, NONE); - - areRestrictedWithExemption(instance, UID_1, PACKAGE_1, NONE); - areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE); - areRestrictedWithExemption(instance, UID_10_2, PACKAGE_2, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {true, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, false, false}, + true); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {true, true, false}); // Exempt package 1 on user-0. mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_1, /*user=*/ 0, false, UsageStatsManager.STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_2, PACKAGE_2, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, true, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, false, false}, + true); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, true, false}); // Unexempt package 2 on user-10. mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 10, false, UsageStatsManager.STANDBY_BUCKET_ACTIVE, REASON_MAIN_USAGE); - areRestricted(instance, UID_1, PACKAGE_1, NONE); - areRestricted(instance, UID_2, PACKAGE_2, JOBS_AND_ALARMS); - areRestricted(instance, UID_10_2, PACKAGE_2, JOBS_AND_ALARMS); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, true, true}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, false, false}, + true); + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, true, true}); // Check force-app-standby. // EXEMPT doesn't exempt from force-app-standby. @@ -703,13 +871,28 @@ public class AppStateTrackerTest { mAppIdleStateChangeListener.onAppIdleStateChanged(PACKAGE_2, /*user=*/ 0, false, UsageStatsManager.STANDBY_BUCKET_EXEMPTED, REASON_MAIN_DEFAULT); + // All 3 packages (u0:p1, u0:p2, u10:p2) are now in the exempted bucket. setAppOps(UID_1, PACKAGE_1, true); - areRestricted(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestricted(instance, UID_2, PACKAGE_2, NONE); - - areRestrictedWithExemption(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS); - areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {true, false, false}, + false); + areJobsRestricted(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {true, false, false}, + true); + + areAlarmsRestrictedByBatterySaver(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {false, false, false}); + areAlarmsRestrictedByFAS(instance, + new int[] {UID_1, UID_2, UID_10_2}, + new String[] {PACKAGE_1, PACKAGE_2, PACKAGE_2}, + new boolean[] {true, false, false}); } @Test @@ -809,6 +992,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -823,7 +1008,9 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); - verify(l, times(1)).unblockAllUnrestrictedAlarms(); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); + verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); @@ -853,6 +1040,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -865,6 +1054,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(1)).unblockAlarmsForUidPackage(eq(UID_10_2), eq(PACKAGE_2)); @@ -876,15 +1067,16 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); - // Unrestrict while battery saver is on. Shouldn't fire. + // Test overlap with battery saver mPowerSaveMode = true; mPowerSaveObserver.accept(getPowerSaveState()); - // Note toggling appops while BS is on will suppress unblockAlarmsForUidPackage(). setAppOps(UID_10_2, PACKAGE_2, true); waitUntilMainHandlerDrain(); @@ -892,6 +1084,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(1)).updateJobsForUidPackage(eq(UID_10_2), eq(PACKAGE_2), anyBoolean()); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -906,7 +1100,9 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); - verify(l, times(1)).unblockAllUnrestrictedAlarms(); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); + verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); @@ -922,7 +1118,9 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); - verify(l, times(0)).unblockAllUnrestrictedAlarms(); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); + verify(l, times(1)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); @@ -934,7 +1132,9 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); - verify(l, times(1)).unblockAllUnrestrictedAlarms(); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); + verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); @@ -948,6 +1148,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -961,12 +1163,14 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); - // Do the same thing with battery saver on. (Currently same callbacks are called.) + // Do the same thing with battery saver on. mPowerSaveMode = true; mPowerSaveObserver.accept(getPowerSaveState()); @@ -975,6 +1179,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -989,7 +1195,9 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); - verify(l, times(0)).unblockAllUnrestrictedAlarms(); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); + verify(l, times(1)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); @@ -1001,7 +1209,9 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); - verify(l, times(1)).unblockAllUnrestrictedAlarms(); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); + verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); @@ -1015,6 +1225,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1028,6 +1240,8 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(anyInt(), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(anyInt()); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1037,9 +1251,8 @@ public class AppStateTrackerTest { // ------------------------------------------------------------------------- // Tests with proc state changes. - // With battery save. - mPowerSaveMode = true; - mPowerSaveObserver.accept(getPowerSaveState()); + // With battery saver. + // Battery saver is already on. mIUidObserver.onUidActive(UID_10_1); @@ -1049,6 +1262,8 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1062,6 +1277,8 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1075,6 +1292,8 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1088,12 +1307,14 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); - // Without battery save. + // Without battery saver. mPowerSaveMode = false; mPowerSaveObserver.accept(getPowerSaveState()); @@ -1102,7 +1323,9 @@ public class AppStateTrackerTest { verify(l, times(0)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); - verify(l, times(1)).unblockAllUnrestrictedAlarms(); + verify(l, times(1)).updateAllAlarms(); + verify(l, times(0)).updateAlarmsForUid(eq(UID_10_1)); + verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); reset(l); @@ -1115,6 +1338,8 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1128,6 +1353,8 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1141,6 +1368,8 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(1)).unblockAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); @@ -1154,6 +1383,8 @@ public class AppStateTrackerTest { verify(l, times(1)).updateJobsForUid(eq(UID_10_1), anyBoolean()); verify(l, times(0)).updateJobsForUidPackage(anyInt(), anyString(), anyBoolean()); + verify(l, times(0)).updateAllAlarms(); + verify(l, times(1)).updateAlarmsForUid(eq(UID_10_1)); verify(l, times(0)).unblockAllUnrestrictedAlarms(); verify(l, times(0)).unblockAlarmsForUid(anyInt()); verify(l, times(0)).unblockAlarmsForUidPackage(anyInt(), anyString()); diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java index 8edac4f8ce58..7a970a1c3d46 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -52,6 +52,7 @@ import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENE import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_INTERVAL; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_FUTURITY; import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_INTERVAL; +import static com.android.server.alarm.AlarmManagerService.INDEFINITE_DELAY; import static com.android.server.alarm.AlarmManagerService.IS_WAKEUP_MASK; import static com.android.server.alarm.AlarmManagerService.TIME_CHANGED_MASK; import static com.android.server.alarm.AlarmManagerService.WORKING_INDEX; @@ -71,6 +72,7 @@ import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.never; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -817,14 +819,14 @@ public class AlarmManagerServiceTest { } @Test - public void testAlarmRestrictedInBatterySaver() throws Exception { + public void testAlarmRestrictedByFAS() throws Exception { final ArgumentCaptor<AppStateTrackerImpl.Listener> listenerArgumentCaptor = ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class); verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture()); final PendingIntent alarmPi = getNewMockPendingIntent(); - when(mAppStateTracker.areAlarmsRestricted(TEST_CALLING_UID, TEST_CALLING_PACKAGE, - false)).thenReturn(true); + when(mAppStateTracker.areAlarmsRestricted(TEST_CALLING_UID, + TEST_CALLING_PACKAGE)).thenReturn(true); setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, alarmPi); assertEquals(mNowElapsedTest + 2, mTestTimer.getElapsed()); @@ -1301,7 +1303,6 @@ public class AlarmManagerServiceTest { final long awiDelayForTest = 23; setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest); - setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 0); setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000, getNewMockPendingIntent()); @@ -1336,7 +1337,7 @@ public class AlarmManagerServiceTest { } @Test - public void allowWhileIdleUnrestricted() throws Exception { + public void allowWhileIdleUnrestrictedInIdle() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); final long awiDelayForTest = 127; @@ -1361,7 +1362,7 @@ public class AlarmManagerServiceTest { } @Test - public void deviceIdleThrottling() throws Exception { + public void deviceIdleDeferralOnSet() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); final long deviceIdleUntil = mNowElapsedTest + 1234; @@ -1386,6 +1387,123 @@ public class AlarmManagerServiceTest { } @Test + public void deviceIdleStateChanges() throws Exception { + doReturn(0).when(mService).fuzzForDuration(anyLong()); + + final int numAlarms = 10; + final PendingIntent[] pis = new PendingIntent[numAlarms]; + for (int i = 0; i < numAlarms; i++) { + setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + i + 1, + pis[i] = getNewMockPendingIntent()); + assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed()); + } + + final PendingIntent idleUntil = getNewMockPendingIntent(); + setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1234, idleUntil); + + assertEquals(mNowElapsedTest + 1234, mTestTimer.getElapsed()); + + mNowElapsedTest += 5; + mTestTimer.expire(); + // Nothing should happen. + verify(pis[0], never()).send(eq(mMockContext), eq(0), any(Intent.class), any(), + any(Handler.class), isNull(), any()); + + mService.removeLocked(idleUntil, null); + mTestTimer.expire(); + // Now, the first 5 alarms (upto i = 4) should expire. + for (int i = 0; i < 5; i++) { + verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(), + any(Handler.class), isNull(), any()); + } + // Rest should be restored, so the timer should reflect the next alarm. + assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed()); + } + + @Test + public void batterySaverThrottling() { + final ArgumentCaptor<AppStateTrackerImpl.Listener> listenerArgumentCaptor = + ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class); + verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture()); + final AppStateTrackerImpl.Listener listener = listenerArgumentCaptor.getValue(); + + final PendingIntent alarmPi = getNewMockPendingIntent(); + when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, + TEST_CALLING_PACKAGE)).thenReturn(true); + setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 7, alarmPi); + assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed()); + + when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, + TEST_CALLING_PACKAGE)).thenReturn(false); + listener.updateAllAlarms(); + assertEquals(mNowElapsedTest + 7, mTestTimer.getElapsed()); + + when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, + TEST_CALLING_PACKAGE)).thenReturn(true); + listener.updateAlarmsForUid(TEST_CALLING_UID); + assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed()); + } + + @Test + public void allowWhileIdleAlarmsInBatterySaver() throws Exception { + final ArgumentCaptor<AppStateTrackerImpl.Listener> listenerArgumentCaptor = + ArgumentCaptor.forClass(AppStateTrackerImpl.Listener.class); + verify(mAppStateTracker).addListener(listenerArgumentCaptor.capture()); + final AppStateTrackerImpl.Listener listener = listenerArgumentCaptor.getValue(); + + final long longDelay = 23; + final long shortDelay = 7; + setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, longDelay); + setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, shortDelay); + + when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID, + TEST_CALLING_PACKAGE)).thenReturn(true); + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1, + getNewMockPendingIntent(), false); + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2, + getNewMockPendingIntent(), false); + + assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed()); + + mNowElapsedTest += 1; + mTestTimer.expire(); + + assertEquals(mNowElapsedTest + longDelay, mTestTimer.getElapsed()); + listener.onUidForeground(TEST_CALLING_UID, true); + // The next alarm should be deferred by shortDelay. + assertEquals(mNowElapsedTest + shortDelay, mTestTimer.getElapsed()); + + mNowElapsedTest = mTestTimer.getElapsed(); + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1, + getNewMockPendingIntent(), false); + + when(mAppStateTracker.isUidInForeground(TEST_CALLING_UID)).thenReturn(true); + mTestTimer.expire(); + // The next alarm should be deferred by shortDelay again. + assertEquals(mNowElapsedTest + shortDelay, mTestTimer.getElapsed()); + + mNowElapsedTest = mTestTimer.getElapsed(); + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1, + getNewMockPendingIntent(), true); + when(mAppStateTracker.isUidInForeground(TEST_CALLING_UID)).thenReturn(false); + mTestTimer.expire(); + final long lastAwiDispatch = mNowElapsedTest; + // Unrestricted, so should not be changed. + assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed()); + + mNowElapsedTest = mTestTimer.getElapsed(); + // AWI_unrestricted should not affect normal AWI bookkeeping. + // The next alarm is after the short delay but before the long delay. + setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, lastAwiDispatch + shortDelay + 1, + getNewMockPendingIntent(), false); + mTestTimer.expire(); + assertEquals(lastAwiDispatch + longDelay, mTestTimer.getElapsed()); + + listener.onUidForeground(TEST_CALLING_UID, true); + assertEquals(lastAwiDispatch + shortDelay + 1, mTestTimer.getElapsed()); + } + + @Test public void dispatchOrder() throws Exception { doReturn(0).when(mService).fuzzForDuration(anyLong()); |