Merge "Adding Battery saver policy to alarms"

This commit is contained in:
TreeHugger Robot
2021-01-12 16:44:09 +00:00
committed by Android (Google) Code Review
5 changed files with 663 additions and 244 deletions

View File

@@ -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();
}
/**
@@ -386,6 +383,19 @@ public class AppStateTrackerImpl implements AppStateTracker {
public void stopForegroundServicesForUidPackage(int uid, String packageName) {
}
/**
* 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,38 +1119,11 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
* @return whether alarms 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 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.
*/
public boolean areJobsRestricted(int uid, @NonNull String packageName,
boolean hasForegroundExemption) {
return isRestricted(uid, packageName, /*useTempExemptionListToo=*/ true,
hasForegroundExemption);
}
/**
* @return whether foreground services should be suppressed in the background
* due to forced app standby for the given app
*/
public boolean areForegroundServicesRestricted(int uid, @NonNull String packageName) {
synchronized (mLock) {
return isRunAnyRestrictedLocked(uid, packageName);
}
}
/**
* @return whether force-app-standby is effective for a UID package-name.
*/
private boolean isRestricted(int uid, @NonNull String packageName,
boolean useTempExemptionListToo, boolean exemptOnBatterySaver) {
public boolean areAlarmsRestricted(int uid, @NonNull String packageName) {
if (isUidActive(uid)) {
return false;
}
@@ -1149,13 +1132,51 @@ public class AppStateTrackerImpl implements AppStateTracker {
if (ArrayUtils.contains(mPowerExemptAllAppIds, appId)) {
return false;
}
if (useTempExemptionListToo && ArrayUtils.contains(mTempExemptAppIds, appId)) {
return (mForcedAppStandbyEnabled && isRunAnyRestrictedLocked(uid, packageName));
}
}
/**
* @return whether alarms should be restricted when due to battery saver.
*/
public boolean areAlarmsRestrictedByBatterySaver(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;
}
final int userId = UserHandle.getUserId(uid);
if (mAppStandbyInternal.isAppIdleEnabled() && !mAppStandbyInternal.isInParole()
&& mExemptedBucketPackages.contains(userId, packageName)) {
return false;
}
return mForceAllAppsStandby;
}
}
/**
* @return whether jobs should be restricted for a UID package-name. This could be due to
* battery saver or user-forced app standby
*/
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)
|| 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);

View File

@@ -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--";
}

View File

@@ -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--) {
@@ -1619,6 +1619,44 @@ public class AlarmManagerService extends SystemService {
return true;
}
/**
* 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.
*
@@ -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;

View File

@@ -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);
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);
areRestrictedWithExemption(instance, UID_1, PACKAGE_1, JOBS_AND_ALARMS);
areRestrictedWithExemption(instance, UID_2, PACKAGE_2, NONE);
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());

View File

@@ -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;
@@ -1385,6 +1386,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());