Merge "Move allow-while-idle throttling to quotas" into sc-dev

This commit is contained in:
Suprabh Shukla
2021-01-27 18:15:04 +00:00
committed by Android (Google) Code Review
4 changed files with 194 additions and 396 deletions

View File

@@ -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.
*/
@@ -285,13 +281,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.
*/
@@ -415,14 +404,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
public void unblockAlarmsForUidPackage(int uid, String packageName) {
}
/**
* 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.
*/
@@ -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);
}
}
@@ -1221,22 +1161,6 @@ public class AppStateTrackerImpl implements AppStateTracker {
return ret;
}
/**
* @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.
*/
@@ -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);
}

View File

@@ -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
@@ -3979,23 +3918,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) {
@@ -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);
}

View File

@@ -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());
}

View File

@@ -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,
when(mAppStateTracker.isForceAllAppsStandbyEnabled()).thenReturn(true);
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);
setAllowWhileIdleAlarm(ELAPSED_REALTIME_WAKEUP, mNowElapsedTest + 2,
long expectedNextTrigger = firstTrigger + ALLOW_WHILE_IDLE_WINDOW;
assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
mTestTimer.getElapsed());
// Refresh the state
mService.removeLocked(TEST_CALLING_UID);
mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
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());
assertEquals(mNowElapsedTest + 1, mTestTimer.getElapsed());
// Refresh the state
mService.removeLocked(TEST_CALLING_UID);
mService.mAllowWhileIdleHistory.removeForPackage(TEST_CALLING_PACKAGE, TEST_CALLING_USER);
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,
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);
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());
for (int i = 0; i < quota; i++) {
mNowElapsedTest = mTestTimer.getElapsed();
mTestTimer.expire();
}
assertEquals("Incorrect trigger when no quota available", expectedNextTrigger,
mTestTimer.getElapsed());
}
@Test