summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java87
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java263
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java43
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java193
4 files changed, 192 insertions, 394 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
index cc3e9c33fe42..c332a598c30b 100644
--- a/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
+++ b/apex/jobscheduler/service/java/com/android/server/AppStateTrackerImpl.java
@@ -105,10 +105,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
@GuardedBy("mLock")
final SparseBooleanArray mActiveUids = new SparseBooleanArray();
- /** UIDs that are in the foreground. */
- @GuardedBy("mLock")
- final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
-
/**
* System except-idle + user exemption list in the device idle controller.
*/
@@ -286,13 +282,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
- * This is called when the foreground state changed for a UID.
- */
- private void onUidForegroundStateChanged(AppStateTrackerImpl sender, int uid) {
- onUidForeground(uid, sender.isUidInForeground(uid));
- }
-
- /**
* This is called when the active/idle state changed for a UID.
*/
private void onUidActiveStateChanged(AppStateTrackerImpl sender, int uid) {
@@ -416,14 +405,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
- * Called when a UID comes into the foreground or the background.
- *
- * @see #isUidInForeground(int)
- */
- public void onUidForeground(int uid, boolean foreground) {
- }
-
- /**
* Called when an ephemeral uid goes to the background, so its alarms need to be removed.
*/
public void removeAlarmsForUid(int uid) {
@@ -460,7 +441,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
mExemptedBucketPackages.remove(userId, pkgName);
mRunAnyRestrictedPackages.remove(Pair.create(uid, pkgName));
mActiveUids.delete(uid);
- mForegroundUids.delete(uid);
}
break;
}
@@ -496,8 +476,7 @@ public class AppStateTrackerImpl implements AppStateTracker {
mIActivityManager.registerUidObserver(new UidObserver(),
ActivityManager.UID_OBSERVER_GONE
| ActivityManager.UID_OBSERVER_IDLE
- | ActivityManager.UID_OBSERVER_ACTIVE
- | ActivityManager.UID_OBSERVER_PROCSTATE,
+ | ActivityManager.UID_OBSERVER_ACTIVE,
ActivityManager.PROCESS_STATE_UNKNOWN, null);
mAppOpsService.startWatchingMode(TARGET_OP, null,
new AppOpsWatcher());
@@ -698,7 +677,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
private final class UidObserver extends IUidObserver.Stub {
@Override
public void onUidStateChanged(int uid, int procState, long procStateSeq, int capability) {
- mHandler.onUidStateChanged(uid, procState);
}
@Override
@@ -769,7 +747,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
private class MyHandler extends Handler {
private static final int MSG_UID_ACTIVE_STATE_CHANGED = 0;
- private static final int MSG_UID_FG_STATE_CHANGED = 1;
private static final int MSG_RUN_ANY_CHANGED = 3;
private static final int MSG_ALL_UNEXEMPTED = 4;
private static final int MSG_ALL_EXEMPTION_LIST_CHANGED = 5;
@@ -779,7 +756,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
private static final int MSG_FORCE_APP_STANDBY_FEATURE_FLAG_CHANGED = 9;
private static final int MSG_EXEMPTED_BUCKET_CHANGED = 10;
- private static final int MSG_ON_UID_STATE_CHANGED = 11;
private static final int MSG_ON_UID_ACTIVE = 12;
private static final int MSG_ON_UID_GONE = 13;
private static final int MSG_ON_UID_IDLE = 14;
@@ -792,10 +768,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
obtainMessage(MSG_UID_ACTIVE_STATE_CHANGED, uid, 0).sendToTarget();
}
- public void notifyUidForegroundStateChanged(int uid) {
- obtainMessage(MSG_UID_FG_STATE_CHANGED, uid, 0).sendToTarget();
- }
-
public void notifyRunAnyAppOpsChanged(int uid, @NonNull String packageName) {
obtainMessage(MSG_RUN_ANY_CHANGED, uid, 0, packageName).sendToTarget();
}
@@ -834,10 +806,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
obtainMessage(MSG_USER_REMOVED, userId, 0).sendToTarget();
}
- public void onUidStateChanged(int uid, int procState) {
- obtainMessage(MSG_ON_UID_STATE_CHANGED, uid, procState).sendToTarget();
- }
-
public void onUidActive(int uid) {
obtainMessage(MSG_ON_UID_ACTIVE, uid, 0).sendToTarget();
}
@@ -875,13 +843,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
mStatLogger.logDurationStat(Stats.UID_ACTIVE_STATE_CHANGED, start);
return;
- case MSG_UID_FG_STATE_CHANGED:
- for (Listener l : cloneListeners()) {
- l.onUidForegroundStateChanged(sender, msg.arg1);
- }
- mStatLogger.logDurationStat(Stats.UID_FG_STATE_CHANGED, start);
- return;
-
case MSG_RUN_ANY_CHANGED:
for (Listener l : cloneListeners()) {
l.onRunAnyAppOpsChanged(sender, msg.arg1, (String) msg.obj);
@@ -944,9 +905,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
handleUserRemoved(msg.arg1);
return;
- case MSG_ON_UID_STATE_CHANGED:
- handleUidStateChanged(msg.arg1, msg.arg2);
- return;
case MSG_ON_UID_ACTIVE:
handleUidActive(msg.arg1);
return;
@@ -971,20 +929,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
}
- public void handleUidStateChanged(int uid, int procState) {
- synchronized (mLock) {
- if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- if (removeUidFromArray(mForegroundUids, uid, false)) {
- mHandler.notifyUidForegroundStateChanged(uid);
- }
- } else {
- if (addUidToArray(mForegroundUids, uid)) {
- mHandler.notifyUidForegroundStateChanged(uid);
- }
- }
- }
- }
-
public void handleUidActive(int uid) {
synchronized (mLock) {
if (addUidToArray(mActiveUids, uid)) {
@@ -1007,9 +951,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
if (removeUidFromArray(mActiveUids, uid, remove)) {
mHandler.notifyUidActiveStateChanged(uid);
}
- if (removeUidFromArray(mForegroundUids, uid, remove)) {
- mHandler.notifyUidForegroundStateChanged(uid);
- }
}
}
}
@@ -1026,7 +967,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
}
cleanUpArrayForUser(mActiveUids, removedUserId);
- cleanUpArrayForUser(mForegroundUids, removedUserId);
mExemptedBucketPackages.remove(removedUserId);
}
}
@@ -1222,22 +1162,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
/**
- * @return whether a UID is in the foreground or not.
- *
- * Note this information is based on the UID proc state callback, meaning it's updated
- * asynchronously and may subtly be stale. If the fresh data is needed, use
- * {@link ActivityManagerInternal#getUidProcessState} instead.
- */
- public boolean isUidInForeground(int uid) {
- if (UserHandle.isCore(uid)) {
- return true;
- }
- synchronized (mLock) {
- return mForegroundUids.get(uid);
- }
- }
-
- /**
* @return whether force all apps standby is enabled or not.
*/
public boolean isForceAllAppsStandbyEnabled() {
@@ -1315,9 +1239,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
pw.print("Active uids: ");
dumpUids(pw, mActiveUids);
- pw.print("Foreground uids: ");
- dumpUids(pw, mForegroundUids);
-
pw.print("Except-idle + user exemption list appids: ");
pw.println(Arrays.toString(mPowerExemptAllAppIds));
@@ -1395,12 +1316,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
}
}
- for (int i = 0; i < mForegroundUids.size(); i++) {
- if (mForegroundUids.valueAt(i)) {
- proto.write(AppStateTrackerProto.FOREGROUND_UIDS, mForegroundUids.keyAt(i));
- }
- }
-
for (int appId : mPowerExemptAllAppIds) {
proto.write(AppStateTrackerProto.POWER_SAVE_EXEMPT_APP_IDS, appId);
}
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 aa46cfdc5c8a..d44169d16d5d 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -90,7 +90,6 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
-import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -152,7 +151,8 @@ public class AlarmManagerService extends SystemService {
static final boolean DEBUG_BG_LIMIT = localLOGV || false;
static final boolean DEBUG_STANDBY = localLOGV || false;
static final boolean RECORD_ALARMS_IN_HISTORY = true;
- static final boolean RECORD_DEVICE_IDLE_ALARMS = false;
+ // TODO (b/178484639): Turn off once allow-while-idle revamp is completed.
+ static final boolean RECORD_DEVICE_IDLE_ALARMS = true;
static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
static final int TICK_HISTORY_DEPTH = 10;
@@ -208,6 +208,7 @@ public class AlarmManagerService extends SystemService {
new ArrayList<>();
AlarmHandler mHandler;
AppWakeupHistory mAppWakeupHistory;
+ AppWakeupHistory mAllowWhileIdleHistory;
ClockReceiver mClockReceiver;
final DeliveryTracker mDeliveryTracker = new DeliveryTracker();
IBinder.DeathRecipient mListenerDeathRecipient;
@@ -230,19 +231,6 @@ public class AlarmManagerService extends SystemService {
*/
int mSystemUiUid;
- /**
- * For each uid, this is the last time we dispatched an "allow while idle" alarm,
- * used to determine the earliest we can dispatch the next such alarm. Times are in the
- * 'elapsed' timebase.
- */
- final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
-
- /**
- * For each uid, we store whether the last allow-while-idle alarm was dispatched while
- * the uid was in foreground or not. We will use the allow_while_idle_short_time in such cases.
- */
- final SparseBooleanArray mUseAllowWhileIdleShortTime = new SparseBooleanArray();
-
static boolean isTimeTickAlarm(Alarm a) {
return a.uid == Process.SYSTEM_UID && TIME_TICK_TAG.equals(a.listenerTag);
}
@@ -290,9 +278,11 @@ public class AlarmManagerService extends SystemService {
private boolean mAppStandbyParole;
/**
- * A rolling window history of previous times when an alarm was sent to a package.
+ * A container to keep rolling window history of previous times when an alarm was sent to
+ * a package.
*/
- private static class AppWakeupHistory {
+ @VisibleForTesting
+ static class AppWakeupHistory {
private ArrayMap<Pair<String, Integer>, LongArrayQueue> mPackageHistory =
new ArrayMap<>();
private long mWindowSize;
@@ -353,7 +343,6 @@ public class AlarmManagerService extends SystemService {
}
void dump(IndentingPrintWriter pw, long nowElapsed) {
- pw.println("App Alarm history:");
pw.increaseIndent();
for (int i = 0; i < mPackageHistory.size(); i++) {
final Pair<String, Integer> packageUser = mPackageHistory.keyAt(i);
@@ -389,10 +378,6 @@ public class AlarmManagerService extends SystemService {
@VisibleForTesting
static final String KEY_MAX_INTERVAL = "max_interval";
@VisibleForTesting
- static final String KEY_ALLOW_WHILE_IDLE_SHORT_TIME = "allow_while_idle_short_time";
- @VisibleForTesting
- static final String KEY_ALLOW_WHILE_IDLE_LONG_TIME = "allow_while_idle_long_time";
- @VisibleForTesting
static final String KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION
= "allow_while_idle_whitelist_duration";
@VisibleForTesting
@@ -422,11 +407,12 @@ public class AlarmManagerService extends SystemService {
private static final String KEY_TIME_TICK_ALLOWED_WHILE_IDLE =
"time_tick_allowed_while_idle";
+ @VisibleForTesting
+ static final String KEY_ALLOW_WHILE_IDLE_QUOTA = "allow_while_idle_quota";
+
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
- private static final long DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_MIN_FUTURITY;
- private static final long DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME = 9 * 60 * 1000;
private static final long DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION = 10 * 1000;
private static final long DEFAULT_LISTENER_TIMEOUT = 5 * 1000;
private static final int DEFAULT_MAX_ALARMS_PER_UID = 500;
@@ -447,6 +433,9 @@ public class AlarmManagerService extends SystemService {
private static final boolean DEFAULT_LAZY_BATCHING = true;
private static final boolean DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE = true;
+ private static final int DEFAULT_ALLOW_WHILE_IDLE_QUOTA = 7;
+ public static final long ALLOW_WHILE_IDLE_WINDOW = 60 * 60 * 1000; // 1 hour.
+
// Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -456,12 +445,6 @@ public class AlarmManagerService extends SystemService {
// Maximum alarm recurrence interval
public long MAX_INTERVAL = DEFAULT_MAX_INTERVAL;
- // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
- public long ALLOW_WHILE_IDLE_SHORT_TIME = DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME;
-
- // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
- public long ALLOW_WHILE_IDLE_LONG_TIME = DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME;
-
// BroadcastOptions.setTemporaryAppWhitelistDuration() to use for FLAG_ALLOW_WHILE_IDLE.
public long ALLOW_WHILE_IDLE_WHITELIST_DURATION
= DEFAULT_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
@@ -478,6 +461,8 @@ public class AlarmManagerService extends SystemService {
public boolean LAZY_BATCHING = DEFAULT_LAZY_BATCHING;
public boolean TIME_TICK_ALLOWED_WHILE_IDLE = DEFAULT_TIME_TICK_ALLOWED_WHILE_IDLE;
+ public int ALLOW_WHILE_IDLE_QUOTA = DEFAULT_ALLOW_WHILE_IDLE_QUOTA;
+
private long mLastAllowWhileIdleWhitelistDuration = -1;
Constants() {
@@ -523,15 +508,13 @@ public class AlarmManagerService extends SystemService {
MAX_INTERVAL = properties.getLong(
KEY_MAX_INTERVAL, DEFAULT_MAX_INTERVAL);
break;
- case KEY_ALLOW_WHILE_IDLE_SHORT_TIME:
- ALLOW_WHILE_IDLE_SHORT_TIME = properties.getLong(
- KEY_ALLOW_WHILE_IDLE_SHORT_TIME,
- DEFAULT_ALLOW_WHILE_IDLE_SHORT_TIME);
- break;
- case KEY_ALLOW_WHILE_IDLE_LONG_TIME:
- ALLOW_WHILE_IDLE_LONG_TIME = properties.getLong(
- KEY_ALLOW_WHILE_IDLE_LONG_TIME,
- DEFAULT_ALLOW_WHILE_IDLE_LONG_TIME);
+ case KEY_ALLOW_WHILE_IDLE_QUOTA:
+ ALLOW_WHILE_IDLE_QUOTA = properties.getInt(KEY_ALLOW_WHILE_IDLE_QUOTA,
+ DEFAULT_ALLOW_WHILE_IDLE_QUOTA);
+ if (ALLOW_WHILE_IDLE_QUOTA <= 0) {
+ Slog.w(TAG, "Cannot have allow-while-idle quota lower than 1.");
+ ALLOW_WHILE_IDLE_QUOTA = 1;
+ }
break;
case KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION:
ALLOW_WHILE_IDLE_WHITELIST_DURATION = properties.getLong(
@@ -660,14 +643,11 @@ public class AlarmManagerService extends SystemService {
TimeUtils.formatDuration(LISTENER_TIMEOUT, pw);
pw.println();
- pw.print(KEY_ALLOW_WHILE_IDLE_SHORT_TIME);
- pw.print("=");
- TimeUtils.formatDuration(ALLOW_WHILE_IDLE_SHORT_TIME, pw);
+ pw.print("allow_while_idle_window=");
+ TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WINDOW, pw);
pw.println();
- pw.print(KEY_ALLOW_WHILE_IDLE_LONG_TIME);
- pw.print("=");
- TimeUtils.formatDuration(ALLOW_WHILE_IDLE_LONG_TIME, pw);
+ pw.print(KEY_ALLOW_WHILE_IDLE_QUOTA, ALLOW_WHILE_IDLE_QUOTA);
pw.println();
pw.print(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION);
@@ -675,9 +655,8 @@ public class AlarmManagerService extends SystemService {
TimeUtils.formatDuration(ALLOW_WHILE_IDLE_WHITELIST_DURATION, pw);
pw.println();
- pw.print(KEY_MAX_ALARMS_PER_UID);
- pw.print("=");
- pw.println(MAX_ALARMS_PER_UID);
+ pw.print(KEY_MAX_ALARMS_PER_UID, MAX_ALARMS_PER_UID);
+ pw.println();
pw.print(KEY_APP_STANDBY_WINDOW);
pw.print("=");
@@ -685,14 +664,12 @@ public class AlarmManagerService extends SystemService {
pw.println();
for (int i = 0; i < KEYS_APP_STANDBY_QUOTAS.length; i++) {
- pw.print(KEYS_APP_STANDBY_QUOTAS[i]);
- pw.print("=");
- pw.println(APP_STANDBY_QUOTAS[i]);
+ pw.print(KEYS_APP_STANDBY_QUOTAS[i], APP_STANDBY_QUOTAS[i]);
+ pw.println();
}
- pw.print(KEY_APP_STANDBY_RESTRICTED_QUOTA);
- pw.print("=");
- pw.println(APP_STANDBY_RESTRICTED_QUOTA);
+ pw.print(KEY_APP_STANDBY_RESTRICTED_QUOTA, APP_STANDBY_RESTRICTED_QUOTA);
+ pw.println();
pw.print(KEY_APP_STANDBY_RESTRICTED_WINDOW);
pw.print("=");
@@ -715,10 +692,6 @@ public class AlarmManagerService extends SystemService {
proto.write(ConstantsProto.MIN_INTERVAL_DURATION_MS, MIN_INTERVAL);
proto.write(ConstantsProto.MAX_INTERVAL_DURATION_MS, MAX_INTERVAL);
proto.write(ConstantsProto.LISTENER_TIMEOUT_DURATION_MS, LISTENER_TIMEOUT);
- proto.write(ConstantsProto.ALLOW_WHILE_IDLE_SHORT_DURATION_MS,
- ALLOW_WHILE_IDLE_SHORT_TIME);
- proto.write(ConstantsProto.ALLOW_WHILE_IDLE_LONG_DURATION_MS,
- ALLOW_WHILE_IDLE_LONG_TIME);
proto.write(ConstantsProto.ALLOW_WHILE_IDLE_WHITELIST_DURATION_MS,
ALLOW_WHILE_IDLE_WHITELIST_DURATION);
@@ -1268,6 +1241,7 @@ public class AlarmManagerService extends SystemService {
mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater);
mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
+ mAllowWhileIdleHistory = new AppWakeupHistory(Constants.ALLOW_WHILE_IDLE_WINDOW);
mNextWakeup = mNextNonWakeup = 0;
@@ -1636,25 +1610,28 @@ public class AlarmManagerService extends SystemService {
return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, nowElapsed);
}
- final long batterSaverPolicyElapsed;
+ final long batterySaverPolicyElapsed;
if ((alarm.flags & (AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED)) != 0) {
// Unrestricted.
- batterSaverPolicyElapsed = nowElapsed;
+ batterySaverPolicyElapsed = 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;
+ final int userId = UserHandle.getUserId(alarm.creatorUid);
+ final int quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
+ final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow(
+ alarm.sourcePackage, userId);
+ if (dispatchesInWindow < quota) {
+ // fine to go out immediately.
+ batterySaverPolicyElapsed = nowElapsed;
} else {
- minDelay = mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
+ batterySaverPolicyElapsed = mAllowWhileIdleHistory.getNthLastWakeupForPackage(
+ alarm.sourcePackage, userId, quota) + Constants.ALLOW_WHILE_IDLE_WINDOW;
}
- final long lastDispatch = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0);
- batterSaverPolicyElapsed = (lastDispatch == 0) ? nowElapsed : lastDispatch + minDelay;
} else {
// Not allowed.
- batterSaverPolicyElapsed = nowElapsed + INDEFINITE_DELAY;
+ batterySaverPolicyElapsed = nowElapsed + INDEFINITE_DELAY;
}
- return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, batterSaverPolicyElapsed);
+ return alarm.setPolicyElapsed(BATTERY_SAVER_POLICY_INDEX, batterySaverPolicyElapsed);
}
/**
@@ -1676,9 +1653,18 @@ public class AlarmManagerService extends SystemService {
deviceIdlePolicyTime = nowElapsed;
} else if ((alarm.flags & AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
// Allowed but limited.
- final long lastDispatch = mLastAllowWhileIdleDispatch.get(alarm.creatorUid, 0);
- deviceIdlePolicyTime = (lastDispatch == 0) ? nowElapsed
- : lastDispatch + mConstants.ALLOW_WHILE_IDLE_LONG_TIME;
+ final int userId = UserHandle.getUserId(alarm.creatorUid);
+ final int quota = mConstants.ALLOW_WHILE_IDLE_QUOTA;
+ final int dispatchesInWindow = mAllowWhileIdleHistory.getTotalWakeupsInWindow(
+ alarm.sourcePackage, userId);
+ if (dispatchesInWindow < quota) {
+ // fine to go out immediately.
+ deviceIdlePolicyTime = nowElapsed;
+ } else {
+ final long whenInQuota = mAllowWhileIdleHistory.getNthLastWakeupForPackage(
+ alarm.sourcePackage, userId, quota) + Constants.ALLOW_WHILE_IDLE_WINDOW;
+ deviceIdlePolicyTime = Math.min(whenInQuota, mPendingIdleUntil.getWhenElapsed());
+ }
} else {
// Not allowed.
deviceIdlePolicyTime = mPendingIdleUntil.getWhenElapsed();
@@ -1723,11 +1709,11 @@ public class AlarmManagerService extends SystemService {
if (wakeupsInWindow >= quotaForBucket) {
final long minElapsed;
if (quotaForBucket <= 0) {
- // Just keep deferring for a day till the quota changes
- minElapsed = nowElapsed + MILLIS_IN_DAY;
+ // Just keep deferring indefinitely till the quota changes.
+ minElapsed = nowElapsed + INDEFINITE_DELAY;
} else {
// Suppose the quota for window was q, and the qth last delivery time for this
- // package was t(q) then the next delivery must be after t(q) + <window_size>
+ // package was t(q) then the next delivery must be after t(q) + <window_size>.
final long t = mAppWakeupHistory.getNthLastWakeupForPackage(
sourcePackage, sourceUserId, quotaForBucket);
minElapsed = t + mConstants.APP_STANDBY_WINDOW;
@@ -1748,17 +1734,10 @@ public class AlarmManagerService extends SystemService {
ent.uid = a.uid;
ent.pkg = a.operation.getCreatorPackage();
ent.tag = a.operation.getTag("");
- ent.op = "SET";
+ ent.op = "START IDLE";
ent.elapsedRealtime = mInjector.getElapsedRealtime();
ent.argRealtime = a.getWhenElapsed();
mAllowWhileIdleDispatches.add(ent);
- if (mPendingIdleUntil == null) {
- IdleDispatchEntry ent2 = new IdleDispatchEntry();
- ent2.uid = 0;
- ent2.pkg = "START IDLE";
- ent2.elapsedRealtime = mInjector.getElapsedRealtime();
- mAllowWhileIdleDispatches.add(ent2);
- }
}
if ((mPendingIdleUntil != a) && (mPendingIdleUntil != null)) {
Slog.wtfStack(TAG, "setImplLocked: idle until changed from " + mPendingIdleUntil
@@ -2182,6 +2161,7 @@ public class AlarmManagerService extends SystemService {
pw.println("]");
pw.println();
+ pw.println("App Alarm history:");
mAppWakeupHistory.dump(pw, nowELAPSED);
if (mPendingIdleUntil != null) {
@@ -2259,30 +2239,8 @@ public class AlarmManagerService extends SystemService {
pw.println();
}
- if (mLastAllowWhileIdleDispatch.size() > 0) {
- pw.println("Last allow while idle dispatch times:");
- pw.increaseIndent();
- for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); i++) {
- pw.print("UID ");
- final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
- UserHandle.formatUid(pw, uid);
- pw.print(": ");
- final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
- TimeUtils.formatDuration(lastTime, nowELAPSED, pw);
- pw.println();
- }
- pw.decreaseIndent();
- }
-
- pw.print("mUseAllowWhileIdleShortTime: [");
- for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
- if (mUseAllowWhileIdleShortTime.valueAt(i)) {
- UserHandle.formatUid(pw, mUseAllowWhileIdleShortTime.keyAt(i));
- pw.print(" ");
- }
- }
- pw.println("]");
- pw.println();
+ pw.println("Allow while idle history:");
+ mAllowWhileIdleHistory.dump(pw, nowELAPSED);
if (mLog.dump(pw, "Recent problems:")) {
pw.println();
@@ -2533,25 +2491,6 @@ public class AlarmManagerService extends SystemService {
f.dumpDebug(proto, AlarmManagerServiceDumpProto.OUTSTANDING_DELIVERIES);
}
- for (int i = 0; i < mLastAllowWhileIdleDispatch.size(); ++i) {
- final long token = proto.start(
- AlarmManagerServiceDumpProto.LAST_ALLOW_WHILE_IDLE_DISPATCH_TIMES);
- final int uid = mLastAllowWhileIdleDispatch.keyAt(i);
- final long lastTime = mLastAllowWhileIdleDispatch.valueAt(i);
-
- proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.UID, uid);
- proto.write(AlarmManagerServiceDumpProto.LastAllowWhileIdleDispatch.TIME_MS,
- lastTime);
- proto.end(token);
- }
-
- for (int i = 0; i < mUseAllowWhileIdleShortTime.size(); i++) {
- if (mUseAllowWhileIdleShortTime.valueAt(i)) {
- proto.write(AlarmManagerServiceDumpProto.USE_ALLOW_WHILE_IDLE_SHORT_TIME,
- mUseAllowWhileIdleShortTime.keyAt(i));
- }
- }
-
mLog.dumpDebug(proto, AlarmManagerServiceDumpProto.RECENT_PROBLEMS);
final FilterStats[] topFilters = new FilterStats[10];
@@ -3049,11 +2988,6 @@ public class AlarmManagerService extends SystemService {
mPendingBackgroundAlarms.removeAt(i);
}
}
- for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
- if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
- mLastAllowWhileIdleDispatch.removeAt(i);
- }
- }
if (mNextWakeFromIdle != null && whichAlarms.test(mNextWakeFromIdle)) {
mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
if (mPendingIdleUntil != null) {
@@ -3215,6 +3149,16 @@ public class AlarmManagerService extends SystemService {
if (mPendingIdleUntil == alarm) {
mPendingIdleUntil = null;
mAlarmStore.updateAlarmDeliveries(a -> adjustDeliveryTimeBasedOnDeviceIdle(a));
+ 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 = "END IDLE";
+ ent.elapsedRealtime = mInjector.getElapsedRealtime();
+ ent.argRealtime = alarm.getWhenElapsed();
+ mAllowWhileIdleDispatches.add(ent);
+ }
}
if (mNextWakeFromIdle == alarm) {
mNextWakeFromIdle = mAlarmStore.getNextWakeFromIdleAlarm();
@@ -3829,7 +3773,6 @@ public class AlarmManagerService extends SystemService {
IntentFilter sdFilter = new IntentFilter();
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
sdFilter.addAction(Intent.ACTION_USER_STOPPED);
- sdFilter.addAction(Intent.ACTION_UID_REMOVED);
getContext().registerReceiver(this, sdFilter);
}
@@ -3856,12 +3799,7 @@ public class AlarmManagerService extends SystemService {
if (userHandle >= 0) {
removeUserLocked(userHandle);
mAppWakeupHistory.removeForUser(userHandle);
- }
- return;
- case Intent.ACTION_UID_REMOVED:
- if (uid >= 0) {
- mLastAllowWhileIdleDispatch.delete(uid);
- mUseAllowWhileIdleShortTime.delete(uid);
+ mAllowWhileIdleHistory.removeForUser(userHandle);
}
return;
case Intent.ACTION_PACKAGE_REMOVED:
@@ -3885,6 +3823,7 @@ public class AlarmManagerService extends SystemService {
if (uid >= 0) {
// package-removed and package-restarted case
mAppWakeupHistory.removeForPackage(pkg, UserHandle.getUserId(uid));
+ mAllowWhileIdleHistory.removeForPackage(pkg, UserHandle.getUserId(uid));
removeLocked(uid);
} else {
// external-applications-unavailable case
@@ -3980,23 +3919,6 @@ public class AlarmManagerService extends SystemService {
}
@Override
- public void onUidForeground(int uid, boolean foreground) {
- synchronized (mLock) {
- if (foreground) {
- mUseAllowWhileIdleShortTime.put(uid, true);
- if (mAlarmStore.updateAlarmDeliveries(a -> {
- if (a.creatorUid != uid || (a.flags & FLAG_ALLOW_WHILE_IDLE) == 0) {
- return false;
- }
- return adjustDeliveryTimeBasedOnBatterySaver(a);
- })) {
- rescheduleKernelAlarmsLocked();
- }
- }
- }
- }
-
- @Override
public void removeAlarmsForUid(int uid) {
synchronized (mLock) {
removeForStoppedLocked(uid);
@@ -4273,22 +4195,23 @@ public class AlarmManagerService extends SystemService {
notifyBroadcastAlarmPendingLocked(alarm.uid);
}
if (allowWhileIdle) {
- // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
- mLastAllowWhileIdleDispatch.put(alarm.creatorUid, nowELAPSED);
- if ((mAppStateTracker == null)
- || mAppStateTracker.isUidInForeground(alarm.creatorUid)) {
- mUseAllowWhileIdleShortTime.put(alarm.creatorUid, true);
- } else {
- mUseAllowWhileIdleShortTime.put(alarm.creatorUid, false);
+ final boolean doze = (mPendingIdleUntil != null);
+ final boolean batterySaver = (mAppStateTracker != null
+ && mAppStateTracker.isForceAllAppsStandbyEnabled());
+ if (doze || batterySaver) {
+ // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm while the
+ // device was in doze or battery saver.
+ mAllowWhileIdleHistory.recordAlarmForPackage(alarm.sourcePackage,
+ UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
+ mAlarmStore.updateAlarmDeliveries(a -> {
+ if (a.creatorUid != alarm.creatorUid
+ || (a.flags & FLAG_ALLOW_WHILE_IDLE) == 0) {
+ return false;
+ }
+ return (doze && adjustDeliveryTimeBasedOnDeviceIdle(a))
+ || (batterySaver && adjustDeliveryTimeBasedOnBatterySaver(a));
+ });
}
- 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;
@@ -4300,8 +4223,6 @@ public class AlarmManagerService extends SystemService {
}
}
if (!isExemptFromAppStandby(alarm)) {
- final Pair<String, Integer> packageUser = Pair.create(alarm.sourcePackage,
- UserHandle.getUserId(alarm.creatorUid));
mAppWakeupHistory.recordAlarmForPackage(alarm.sourcePackage,
UserHandle.getUserId(alarm.creatorUid), nowELAPSED);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
index a691a8d44e48..607fb4760236 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AppStateTrackerTest.java
@@ -271,8 +271,7 @@ public class AppStateTrackerTest {
verify(mMockIActivityManager).registerUidObserver(
uidObserverArgumentCaptor.capture(),
eq(ActivityManager.UID_OBSERVER_GONE | ActivityManager.UID_OBSERVER_IDLE
- | ActivityManager.UID_OBSERVER_ACTIVE
- | ActivityManager.UID_OBSERVER_PROCSTATE),
+ | ActivityManager.UID_OBSERVER_ACTIVE),
eq(ActivityManager.PROCESS_STATE_UNKNOWN),
isNull());
verify(mMockIAppOpsService).startWatchingMode(
@@ -650,11 +649,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
- assertFalse(instance.isUidInForeground(UID_1));
- assertFalse(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
-
mIUidObserver.onUidStateChanged(UID_2,
ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE, 0,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -670,11 +664,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
- assertFalse(instance.isUidInForeground(UID_1));
- assertTrue(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
-
mIUidObserver.onUidStateChanged(UID_1,
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE, 0,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -686,10 +675,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
- assertTrue(instance.isUidInForeground(UID_1));
- assertTrue(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
mIUidObserver.onUidGone(UID_1, true);
waitUntilMainHandlerDrain();
@@ -699,10 +684,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
- assertFalse(instance.isUidInForeground(UID_1));
- assertTrue(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
mIUidObserver.onUidIdle(UID_2, true);
waitUntilMainHandlerDrain();
@@ -712,10 +693,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
- assertFalse(instance.isUidInForeground(UID_1));
- assertFalse(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
mIUidObserver.onUidStateChanged(UID_1,
ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND, 0,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -727,10 +704,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActive(UID_2));
assertTrue(instance.isUidActive(Process.SYSTEM_UID));
- assertTrue(instance.isUidInForeground(UID_1));
- assertFalse(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
mIUidObserver.onUidStateChanged(UID_1,
ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND, 0,
ActivityManager.PROCESS_CAPABILITY_NONE);
@@ -746,10 +719,6 @@ public class AppStateTrackerTest {
assertFalse(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
- assertFalse(instance.isUidInForeground(UID_1));
- assertFalse(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
// The result from AMI.isUidActive() only affects isUidActiveSynced().
when(mMockIActivityManagerInternal.isUidActive(anyInt())).thenReturn(true);
@@ -760,11 +729,6 @@ public class AppStateTrackerTest {
assertTrue(instance.isUidActiveSynced(UID_1));
assertTrue(instance.isUidActiveSynced(UID_2));
assertTrue(instance.isUidActiveSynced(Process.SYSTEM_UID));
-
- assertFalse(instance.isUidInForeground(UID_1));
- assertFalse(instance.isUidInForeground(UID_2));
- assertTrue(instance.isUidInForeground(Process.SYSTEM_UID));
-
}
@Test
@@ -1480,7 +1444,6 @@ public class AppStateTrackerTest {
callStart(instance);
instance.mActiveUids.put(UID_1, true);
- instance.mForegroundUids.put(UID_2, true);
instance.mRunAnyRestrictedPackages.add(Pair.create(UID_1, PACKAGE_1));
instance.mExemptedBucketPackages.add(UserHandle.getUserId(UID_2), PACKAGE_2);
@@ -1493,7 +1456,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(1, instance.mActiveUids.size());
- assertEquals(1, instance.mForegroundUids.size());
assertEquals(1, instance.mRunAnyRestrictedPackages.size());
assertEquals(1, instance.mExemptedBucketPackages.size());
@@ -1506,7 +1468,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(1, instance.mActiveUids.size());
- assertEquals(1, instance.mForegroundUids.size());
assertEquals(1, instance.mRunAnyRestrictedPackages.size());
assertEquals(1, instance.mExemptedBucketPackages.size());
@@ -1518,7 +1479,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(0, instance.mActiveUids.size());
- assertEquals(1, instance.mForegroundUids.size());
assertEquals(0, instance.mRunAnyRestrictedPackages.size());
assertEquals(1, instance.mExemptedBucketPackages.size());
@@ -1530,7 +1490,6 @@ public class AppStateTrackerTest {
mReceiver.onReceive(mMockContext, packageRemoved);
assertEquals(0, instance.mActiveUids.size());
- assertEquals(0, instance.mForegroundUids.size());
assertEquals(0, instance.mRunAnyRestrictedPackages.size());
assertEquals(0, instance.mExemptedBucketPackages.size());
}
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 7a970a1c3d46..1254df95a1c0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -44,14 +44,15 @@ import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_FOR_CANCELED;
-import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
-import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
+import static com.android.server.alarm.AlarmManagerService.Constants.ALLOW_WHILE_IDLE_WINDOW;
+import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_QUOTA;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LAZY_BATCHING;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT;
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.FREQUENT_INDEX;
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;
@@ -409,6 +410,12 @@ public class AlarmManagerServiceTest {
return mockPi;
}
+ private void setDeviceConfigInt(String key, int val) {
+ mDeviceConfigKeys.add(key);
+ doReturn(val).when(mDeviceConfigProperties).getInt(eq(key), anyInt());
+ mService.mConstants.onPropertiesChanged(mDeviceConfigProperties);
+ }
+
private void setDeviceConfigLong(String key, long val) {
mDeviceConfigKeys.add(key);
doReturn(val).when(mDeviceConfigProperties).getLong(eq(key), anyLong());
@@ -430,10 +437,12 @@ public class AlarmManagerServiceTest {
setDeviceConfigLong(KEY_MIN_INTERVAL, 0);
mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]);
mDeviceConfigKeys.add(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]);
- doReturn(8).when(mDeviceConfigProperties)
+ doReturn(50).when(mDeviceConfigProperties)
.getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[ACTIVE_INDEX]), anyInt());
- doReturn(5).when(mDeviceConfigProperties)
+ doReturn(35).when(mDeviceConfigProperties)
.getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[WORKING_INDEX]), anyInt());
+ doReturn(20).when(mDeviceConfigProperties)
+ .getInt(eq(mService.mConstants.KEYS_APP_STANDBY_QUOTAS[FREQUENT_INDEX]), anyInt());
mService.mConstants.onPropertiesChanged(mDeviceConfigProperties);
}
@@ -496,15 +505,13 @@ public class AlarmManagerServiceTest {
setDeviceConfigLong(KEY_MIN_FUTURITY, 5);
setDeviceConfigLong(KEY_MIN_INTERVAL, 10);
setDeviceConfigLong(KEY_MAX_INTERVAL, 15);
- setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 20);
- setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, 25);
+ setDeviceConfigInt(KEY_ALLOW_WHILE_IDLE_QUOTA, 20);
setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION, 30);
setDeviceConfigLong(KEY_LISTENER_TIMEOUT, 35);
assertEquals(5, mService.mConstants.MIN_FUTURITY);
assertEquals(10, mService.mConstants.MIN_INTERVAL);
assertEquals(15, mService.mConstants.MAX_INTERVAL);
- assertEquals(20, mService.mConstants.ALLOW_WHILE_IDLE_SHORT_TIME);
- assertEquals(25, mService.mConstants.ALLOW_WHILE_IDLE_LONG_TIME);
+ assertEquals(20, mService.mConstants.ALLOW_WHILE_IDLE_QUOTA);
assertEquals(30, mService.mConstants.ALLOW_WHILE_IDLE_WHITELIST_DURATION);
assertEquals(35, mService.mConstants.LISTENER_TIMEOUT);
}
@@ -1301,62 +1308,54 @@ public class AlarmManagerServiceTest {
public void allowWhileIdleAlarmsWhileDeviceIdle() throws Exception {
doReturn(0).when(mService).fuzzForDuration(anyLong());
- final long awiDelayForTest = 23;
- setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest);
-
- setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000,
+ setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + ALLOW_WHILE_IDLE_WINDOW + 1000,
getNewMockPendingIntent());
assertNotNull(mService.mPendingIdleUntil);
- final long seedTrigger = mNowElapsedTest + 3;
- final int numAlarms = 10;
- final PendingIntent[] pis = new PendingIntent[numAlarms];
- for (int i = 0; i < numAlarms; i++) {
- pis[i] = getNewMockPendingIntent();
- setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, seedTrigger + i * i, pis[i], false);
- }
-
- long lastAwiDispatch = -1;
- int i = 0;
- while (i < numAlarms) {
- final long nextDispatch = (lastAwiDispatch >= 0) ? (lastAwiDispatch + awiDelayForTest)
- : (seedTrigger + i * i);
- assertEquals("Wrong allow-while-idle dispatch", nextDispatch, mTestTimer.getElapsed());
-
- mNowElapsedTest = nextDispatch;
+ final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA;
+ final long firstTrigger = mNowElapsedTest + 10;
+ for (int i = 0; i < quota; i++) {
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
+ getNewMockPendingIntent(), false);
+ mNowElapsedTest = mTestTimer.getElapsed();
mTestTimer.expire();
-
- while (i < numAlarms && (seedTrigger + i * i) <= nextDispatch) {
- verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(),
- any(Handler.class), isNull(), any());
- i++;
- }
- Log.d(TAG, "Dispatched alarms upto " + i + " at " + nextDispatch);
- lastAwiDispatch = nextDispatch;
}
+ // This one should get deferred on set.
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
+ getNewMockPendingIntent(), false);
+ final long expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW;
+ assertEquals("Incorrect trigger when no quota left", expectedNextTrigger,
+ mTestTimer.getElapsed());
+
+ // Bring the idle until alarm back.
+ setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger - 50,
+ getNewMockPendingIntent());
+ assertEquals(expectedNextTrigger - 50, mService.mPendingIdleUntil.getWhenElapsed());
+ assertEquals(expectedNextTrigger - 50, mTestTimer.getElapsed());
}
@Test
- public void allowWhileIdleUnrestrictedInIdle() throws Exception {
+ public void allowWhileIdleUnrestricted() throws Exception {
doReturn(0).when(mService).fuzzForDuration(anyLong());
- final long awiDelayForTest = 127;
- setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_LONG_TIME, awiDelayForTest);
- setDeviceConfigLong(KEY_ALLOW_WHILE_IDLE_SHORT_TIME, 0);
-
+ // Both battery saver and doze are on.
setIdleUntilAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1000,
getNewMockPendingIntent());
assertNotNull(mService.mPendingIdleUntil);
- final long seedTrigger = mNowElapsedTest + 3;
- for (int i = 1; i <= 5; i++) {
- setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, seedTrigger + i * i,
+ when(mAppStateTracker.areAlarmsRestrictedByBatterySaver(TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE)).thenReturn(true);
+
+ final int numAlarms = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA + 100;
+ final long firstTrigger = mNowElapsedTest + 10;
+ for (int i = 0; i < numAlarms; i++) {
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
getNewMockPendingIntent(), true);
}
- for (int i = 1; i <= 5; i++) {
- final long nextTrigger = mTestTimer.getElapsed();
- assertEquals("Wrong trigger for alarm " + i, seedTrigger + i * i, nextTrigger);
- mNowElapsedTest = nextTrigger;
+ // All of them should fire as expected.
+ for (int i = 0; i < numAlarms; i++) {
+ mNowElapsedTest = mTestTimer.getElapsed();
+ assertEquals("Incorrect trigger at i=" + i, firstTrigger + i, mNowElapsedTest);
mTestTimer.expire();
}
}
@@ -1427,9 +1426,10 @@ public class AlarmManagerServiceTest {
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);
+
+ final PendingIntent alarmPi = getNewMockPendingIntent();
setTestAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 7, alarmPi);
assertEquals(mNowElapsedTest + INDEFINITE_DELAY, mTestTimer.getElapsed());
@@ -1446,61 +1446,64 @@ public class AlarmManagerServiceTest {
@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);
+ when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true);
- assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed());
-
- mNowElapsedTest += 1;
- mTestTimer.expire();
+ final int quota = mService.mConstants.ALLOW_WHILE_IDLE_QUOTA;
+ long firstTrigger = mNowElapsedTest + 10;
+ for (int i = 0; i < quota; i++) {
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
+ getNewMockPendingIntent(), false);
+ mNowElapsedTest = mTestTimer.getElapsed();
+ mTestTimer.expire();
+ }
+ // This one should get deferred on set.
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
+ getNewMockPendingIntent(), false);
+ long expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW;
+ assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
+ mTestTimer.getElapsed());
- assertEquals(mNowElapsedTest + longDelay, mTestTimer.getElapsed());
- listener.onUidForeground(TEST_CALLING_UID, true);
- // The next alarm should be deferred by shortDelay.
- assertEquals(mNowElapsedTest + shortDelay, mTestTimer.getElapsed());
+ // Refresh the state
+ mService.removeLocked(TEST_CALLING_UID);
+ mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
- mNowElapsedTest = mTestTimer.getElapsed();
- setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 1,
+ firstTrigger = mNowElapsedTest + 10;
+ for (int i = 0; i < quota; i++) {
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
+ getNewMockPendingIntent(), false);
+ }
+ // This one should get deferred after the latest alarm expires.
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + quota,
getNewMockPendingIntent(), false);
+ for (int i = 0; i < quota; i++) {
+ mNowElapsedTest = mTestTimer.getElapsed();
+ mTestTimer.expire();
+ }
+ expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW;
+ assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
+ mTestTimer.getElapsed());
- 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());
+ // Refresh the state
+ mService.removeLocked(TEST_CALLING_UID);
+ mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
- 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,
+ firstTrigger = mNowElapsedTest + 10;
+ for (int i = 0; i < quota; i++) {
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, firstTrigger + i,
+ getNewMockPendingIntent(), false);
+ }
+ // This delivery time maintains the quota invariant. Should not be deferred.
+ expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW + 5;
+ setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, expectedNextTrigger,
getNewMockPendingIntent(), false);
- mTestTimer.expire();
- assertEquals(lastAwiDispatch + longDelay, mTestTimer.getElapsed());
-
- listener.onUidForeground(TEST_CALLING_UID, true);
- assertEquals(lastAwiDispatch + shortDelay + 1, mTestTimer.getElapsed());
+ for (int i = 0; i < quota; i++) {
+ mNowElapsedTest = mTestTimer.getElapsed();
+ mTestTimer.expire();
+ }
+ assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
+ mTestTimer.getElapsed());
}
@Test